added everything
This commit is contained in:
276
engine/lightingSystem/sgBinaryVolumePartitionTree.h
Executable file
276
engine/lightingSystem/sgBinaryVolumePartitionTree.h
Executable file
@@ -0,0 +1,276 @@
|
||||
//---------------------------------------------------------------
|
||||
// Synapse Gaming - Binary Volume Partition Tree
|
||||
// Copyright <20> Synapse Gaming 2004 - 2005
|
||||
// Written by John Kabus
|
||||
//
|
||||
// Overview:
|
||||
// The Binary Volume Partition Tree (BVPT) is a hybrid of the
|
||||
// BSP and Oct-tree spacial partitioning schemes that combines
|
||||
// the strengths of both into a system that can efficiently
|
||||
// processes large amounts of geometry and geometry with large
|
||||
// surface area, which allows optimal handling of both brush
|
||||
// and mesh geometry.
|
||||
//
|
||||
// Similar to Oct-tree partitioning, BVPT splits the geometric
|
||||
// 'world' into equal volumes and each volume into sub-volumes
|
||||
// creating a tree that assigns each surface or object into the
|
||||
// smallest volume that completely contains it.
|
||||
//
|
||||
// The main disadvantage to using Oct-trees is that all geometry
|
||||
// that rides the border between *any* two octants is maintained
|
||||
// by the parent volume, which means the geometry is used every
|
||||
// time the parent volume is traversed regardless of the
|
||||
// relationship to the requested octant.
|
||||
//
|
||||
// BVPT avoids Oct-tree inefficiencies by splitting volumes in
|
||||
// half (instead of into eighths). Because of this all geometry
|
||||
// maintained by the parent volume spans both of the two sub-volumes,
|
||||
// meaning that the parent geometry has a definite relationship
|
||||
// to the requested sub-volume.
|
||||
//---------------------------------------------------------------
|
||||
#ifndef BVPT_H_
|
||||
#define BVPT_H_
|
||||
|
||||
#include "platform/types.h"
|
||||
#include "core/color.h"
|
||||
#include "math/mPoint.h"
|
||||
#include "math/mBox.h"
|
||||
#include "math/mPlane.h"
|
||||
#include "core/tVector.h"
|
||||
|
||||
|
||||
template<class Tstoreobj> class BVPT
|
||||
{
|
||||
public:
|
||||
enum axisType
|
||||
{
|
||||
atX = 0,
|
||||
atY = 1,
|
||||
atZ = 2,
|
||||
atNone = 3
|
||||
};
|
||||
|
||||
typedef Vector<Tstoreobj> objectList;
|
||||
|
||||
// used for spacial partitioning...
|
||||
PlaneF plane;
|
||||
|
||||
// objects contained in this partition...
|
||||
objectList object;
|
||||
|
||||
// children in the tree...
|
||||
BVPT *positive;
|
||||
BVPT *negative;
|
||||
|
||||
// only used for passing info into children...
|
||||
axisType axis;
|
||||
// only used for passing info into children...
|
||||
Box3F volume;
|
||||
|
||||
|
||||
BVPT()
|
||||
{
|
||||
positive = negative = NULL;
|
||||
clear();
|
||||
}
|
||||
BVPT(const Box3F &vol)
|
||||
{
|
||||
positive = negative = NULL;
|
||||
init(vol);
|
||||
}
|
||||
~BVPT() {clear();}
|
||||
void init(const Box3F &vol)
|
||||
{
|
||||
clear();
|
||||
volume = vol;
|
||||
calculatePartition();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
axis = atNone;
|
||||
plane.set(0.0f, 0.0f, 0.0f);
|
||||
plane.d = 0.0f;
|
||||
volume.min.set(F32_MAX, F32_MAX, F32_MAX);
|
||||
volume.max.set(-F32_MAX, -F32_MAX, -F32_MAX);
|
||||
object.clear();
|
||||
if(positive)
|
||||
{
|
||||
delete positive;
|
||||
positive = NULL;
|
||||
}
|
||||
if(negative)
|
||||
{
|
||||
delete negative;
|
||||
negative = NULL;
|
||||
}
|
||||
}
|
||||
void calculatePartition()
|
||||
{
|
||||
Point3F span = volume.max - volume.min;
|
||||
F32 bestspan = span.x;
|
||||
axisType bestaxis = atX;
|
||||
|
||||
for(S32 i=1; i<3; i++)
|
||||
{
|
||||
if(bestspan < span[i])
|
||||
{
|
||||
bestspan = span[i];
|
||||
bestaxis = axisType(i);
|
||||
}
|
||||
}
|
||||
|
||||
axis = bestaxis;
|
||||
plane.set(0.0f, 0.0f, 0.0f);
|
||||
plane[axis] = 1.0f;
|
||||
plane.d = -(volume.min[axis] + (bestspan * 0.5f));
|
||||
}
|
||||
void storeObject(const Box3F &boundingbox, const Tstoreobj obj)
|
||||
{
|
||||
bool frontmin = plane.distToPlane(boundingbox.min) > 0.0f;
|
||||
bool frontmax = plane.distToPlane(boundingbox.max) > 0.0f;
|
||||
|
||||
if(frontmin != frontmax)
|
||||
{
|
||||
// only fully contained by this volume...
|
||||
object.push_back(obj);
|
||||
}
|
||||
else if(frontmin)
|
||||
{
|
||||
// positive side...
|
||||
// setup child...
|
||||
Box3F vol = volume;
|
||||
vol.min[axis] = -plane.d;
|
||||
if(!positive)
|
||||
positive = new BVPT(vol);
|
||||
|
||||
// send down the object...
|
||||
positive->storeObject(boundingbox, obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
// negative side...
|
||||
// setup child...
|
||||
Box3F vol = volume;
|
||||
vol.max[axis] = -plane.d;
|
||||
if(!negative)
|
||||
negative = new BVPT(vol);
|
||||
|
||||
// send down the object...
|
||||
negative->storeObject(boundingbox, obj);
|
||||
}
|
||||
}
|
||||
void collectObjects(const Box3F &boundingbox, objectList &objectslist)
|
||||
{
|
||||
// we're here so collect the objects...
|
||||
U32 originalcount = objectslist.size();
|
||||
objectslist.increment(object.size());
|
||||
if(object.size() > 0)
|
||||
{
|
||||
dMemcpy((objectslist.address() + originalcount), object.address(), (object.size() * sizeof(Tstoreobj)));
|
||||
}
|
||||
|
||||
bool frontmin = plane.distToPlane(boundingbox.min) > 0.0f;
|
||||
bool frontmax = plane.distToPlane(boundingbox.max) > 0.0f;
|
||||
|
||||
if((frontmin || frontmax) && positive)
|
||||
positive->collectObjects(boundingbox, objectslist);
|
||||
|
||||
if((!frontmin || !frontmax) && negative)
|
||||
negative->collectObjects(boundingbox, objectslist);
|
||||
}
|
||||
// clips line to outer volume...
|
||||
void collectObjectsClipped(Point3F start, Point3F end, objectList &objectslist)
|
||||
{
|
||||
F32 t;
|
||||
Point3F vect;
|
||||
if(!volume.isContained(start))
|
||||
{
|
||||
if(!volume.collideLine(start, end, &t, &vect))
|
||||
return;// we missed the whole volume...
|
||||
if((t < 0.0f) || (t > 1.0f))
|
||||
return;// we missed the whole volume...
|
||||
vect = end - start;
|
||||
start += (vect * t);
|
||||
}
|
||||
if(!volume.isContained(end))
|
||||
{
|
||||
if(!volume.collideLine(end, start, &t, &vect))
|
||||
return;// we missed the whole volume...
|
||||
if((t < 0.0f) || (t > 1.0f))
|
||||
return;// we missed the whole volume...
|
||||
vect = start - end;
|
||||
end += (vect * t);
|
||||
}
|
||||
collectObjectsUnclipped(start, end, objectslist);
|
||||
}
|
||||
// assumes the line has been clipped to the outer volume!!!
|
||||
void collectObjectsUnclipped(const Point3F &start, const Point3F &end, objectList &objectslist)
|
||||
{
|
||||
// we're here so collect the objects...
|
||||
U32 originalcount = objectslist.size();
|
||||
objectslist.increment(object.size());
|
||||
if(object.size() > 0)
|
||||
{
|
||||
dMemcpy((objectslist.address() + originalcount), object.address(), (object.size() * sizeof(Tstoreobj)));
|
||||
}
|
||||
|
||||
// do we have children?
|
||||
if((!positive) && (!negative))
|
||||
return;
|
||||
|
||||
// test for sides...
|
||||
F32 diststart = plane.distToPlane(start);
|
||||
bool fronts = diststart > 0.0f;
|
||||
bool fronte = plane.distToPlane(end) > 0.0f;
|
||||
|
||||
if(fronts == fronte)// same side?
|
||||
{
|
||||
if(fronts && positive)// in the front...
|
||||
positive->collectObjectsUnclipped(start, end, objectslist);
|
||||
else if((!fronts) && negative)// might be the back...
|
||||
negative->collectObjectsUnclipped(start, end, objectslist);
|
||||
}
|
||||
else
|
||||
{
|
||||
// find the split...
|
||||
Point3F split = end - start;
|
||||
F32 t = mDot(split, plane);
|
||||
if(t == 0)
|
||||
return;
|
||||
t = -diststart / t;
|
||||
if(t > 0.0f)
|
||||
{
|
||||
split *= t;
|
||||
split += start;
|
||||
}
|
||||
else
|
||||
{
|
||||
split = start;
|
||||
}
|
||||
|
||||
// setup the orientation...
|
||||
const Point3F *f;
|
||||
const Point3F *b;
|
||||
if(fronts)
|
||||
{
|
||||
f = &start;
|
||||
b = &end;
|
||||
}
|
||||
else
|
||||
{
|
||||
f = &end;
|
||||
b = &start;
|
||||
}
|
||||
|
||||
// run the two new lines through the children...
|
||||
if(positive)
|
||||
positive->collectObjectsUnclipped((*f), split, objectslist);
|
||||
if(negative)
|
||||
negative->collectObjectsUnclipped(split, (*b), objectslist);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif//BVPT_H_
|
||||
|
||||
Reference in New Issue
Block a user