55 AABBTreeNode::AABBTreeNode() :
61 mNodePrimitives (
null),
64 #ifdef OPC_USE_TREE_COHERENCE 73 AABBTreeNode::~AABBTreeNode()
78 #ifndef OPC_NO_NEG_VANILLA_TREE 85 mNodePrimitives =
null;
102 float SplitValue = builder->
GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis);
110 udword Index = mNodePrimitives[
i];
117 if(PrimitiveValue > SplitValue)
120 udword Tmp = mNodePrimitives[
i];
121 mNodePrimitives[
i] = mNodePrimitives[NbPos];
122 mNodePrimitives[NbPos] = Tmp;
153 if(!builder)
return false;
157 if(mNbPrimitives==1)
return true;
162 bool ValidSplit =
true;
167 Point Extents; mBV.GetExtents(Extents);
171 NbPos = Split(Axis, builder);
174 if(!NbPos || NbPos==mNbPrimitives) ValidSplit =
false;
182 udword Index = mNodePrimitives[
i];
187 Means/=float(mNbPrimitives);
193 udword Index = mNodePrimitives[
i];
197 Vars.x += (Cx - Means.x)*(Cx - Means.x);
198 Vars.y += (Cy - Means.y)*(Cy - Means.y);
199 Vars.z += (Cz - Means.z)*(Cz - Means.z);
201 Vars/=float(mNbPrimitives-1);
204 udword Axis = Vars.LargestAxis();
207 NbPos = Split(Axis, builder);
210 if(!NbPos || NbPos==mNbPrimitives) ValidSplit =
false;
216 NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives);
217 NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives);
218 NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives);
219 Results[0]-=0.5f; Results[0]*=Results[0];
220 Results[1]-=0.5f; Results[1]*=Results[1];
221 Results[2]-=0.5f; Results[2]*=Results[2];
223 if(Results[1]<Results[Min]) Min = 1;
224 if(Results[2]<Results[Min]) Min = 2;
227 NbPos = Split(Min, builder);
230 if(!NbPos || NbPos==mNbPrimitives) ValidSplit =
false;
237 Point Extents; mBV.GetExtents(Extents);
238 udword SortedAxis[] = { 0, 1, 2 };
239 float* Keys = (
float*)&Extents.
x;
244 if(Keys[SortedAxis[
i]]<Keys[SortedAxis[
i+1]])
247 SortedAxis[
i] = SortedAxis[
i+1];
248 SortedAxis[
i+1] = Tmp;
256 while(!ValidSplit && CurAxis!=3)
258 NbPos = Split(SortedAxis[CurAxis], builder);
260 if(!NbPos || NbPos==mNbPrimitives) CurAxis++;
261 else ValidSplit =
true;
267 NbPos = mNbPrimitives>>1;
281 NbPos = mNbPrimitives>>1;
295 mPos =
EXWORD(&Pool[Count+0])|1;
296 #ifndef OPC_NO_NEG_VANILLA_TREE 297 mNeg =
EXWORD(&Pool[Count+1])|1;
303 #ifndef OPC_NO_NEG_VANILLA_TREE 362 if(Pos) Pos->
_Refit(builder);
363 if(Neg) Neg->
_Refit(builder);
424 mNodePrimitives = mIndices;
438 _BuildHierarchy(builder);
441 mTotalNbNodes = builder->
GetCount();
477 if(!current_node)
return;
481 if(current_depth>max_depth) max_depth = current_depth;
484 if(callback && !(callback)(current_node, current_depth, user_data))
return;
487 if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; }
488 if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; }
491 Local::_Walk(
this, MaxDepth, CurrentDepth, callback, user_data);
503 if(!builder)
return false;
517 if(!builder)
return false;
524 udword Index = mTotalNbNodes;
535 Current.GetPos()->GetAABB()->GetMin(Min);
536 Current.GetPos()->GetAABB()->GetMax(Max);
538 Current.GetNeg()->GetAABB()->GetMin(Min_);
539 Current.GetNeg()->GetAABB()->GetMax(Max_);
544 ((
AABB*)Current.GetAABB())->SetMinMax(Min, Max);
558 udword TotalSize = mTotalNbNodes*GetNodeSize();
559 if(mIndices) TotalSize+=mNbPrimitives*
sizeof(
udword);
572 return (GetNbNodes()==GetNbPrimitives()*2-1);
inline_ const udword * GetPrimitives() const
udword GetUsedBytes() const
udword * mNodePrimitives
Node-related primitives (shortcut to a position in mIndices below)
#define null
our own NULL pointer
void * mNodeBase
Address of node pool [Opcode 1.3].
bool Build(AABBTreeBuilder *builder)
#define OPC_NO_NEG_VANILLA_TREE
Use tree-coherence or not [not implemented yet].
Splatter primitive centers (QuickCD-style)
inline_ void IncreaseCount(udword nb)
#define DELETEARRAY(x)
Deletes an array.
virtual BOOL ValidateSubdivision(const udword *primitives, udword nb_prims, const AABB &global_box)
void _Refit(AABBTreeBuilder *builder)
bool Refit(AABBTreeBuilder *builder)
void _BuildHierarchy(AABBTreeBuilder *builder)
udword mRules
Building/Splitting rules (a combination of SplittingRules flags)
unsigned int udword
sizeof(udword) must be 4
inline_ float Min() const
Returns MIN(x, y, z);.
udword Split(udword axis, AABBTreeBuilder *builder)
inline_ void IncreaseNbInvalidSplits()
#define DELETESINGLE(x)
Deletes an instance of a class.
udword mNbPrimitives
Total number of primitives.
inline_ float Max() const
Returns MAX(x, y, z);.
bool Refit2(AABBTreeBuilder *builder)
inline_ void SetCount(udword nb)
inline_ PointComponent LargestAxis() const
Returns largest axis.
udword Walk(WalkingCallback callback, void *user_data) const
virtual float GetSplittingValue(udword index, udword axis) const =0
udword mLimit
Limit number of primitives / node. If limit is 1, build a complete tree (2*N-1 nodes) ...
inline_ udword GetCount() const
Try largest axis, then second, then last.
inline_ udword GetNbPrimitives() const
virtual bool ComputeGlobalBox(const udword *primitives, udword nb_prims, AABB &global_box) const =0
bool(* WalkingCallback)(const AABBTreeNode *current, udword depth, void *user_data)
Try to keep a well-balanced tree.
bool Subdivide(AABBTreeBuilder *builder)
udword ComputeDepth() const
inline_ void SetNbInvalidSplits(udword nb)
void _Refit(AABBTreeBuilder *builder)
udword mNbPrimitives
Number of primitives for this node.
Split along the largest axis.
BuildSettings mSettings
Splitting rules & split limit [Opcode 1.3].
void _BuildHierarchy(AABBTreeBuilder *builder)