0025159: Collections and common types in BVH package are named in non-conformant...
[occt.git] / src / BVH / BVH_BinnedBuilder.lxx
CommitLineData
3c4e78f2 1// Created on: 2013-12-20
2// Created by: Denis BOGOLEPOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
3c4e78f2 4//
5// This file is part of Open CASCADE Technology software library.
6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
3c4e78f2 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16// =======================================================================
17// function : BVH_BinnedBuilder
18// purpose :
19// =======================================================================
20template<class T, int N, int Bins>
21BVH_BinnedBuilder<T, N, Bins>::BVH_BinnedBuilder (const Standard_Integer theLeafNodeSize,
22 const Standard_Integer theMaxTreeDepth)
0ef61b50 23: BVH_QueueBuilder<T, N> (theLeafNodeSize,
24 theMaxTreeDepth)
3c4e78f2 25{
26 //
27}
28
29// =======================================================================
30// function : ~BVH_BinnedBuilder
31// purpose :
32// =======================================================================
33template<class T, int N, int Bins>
34BVH_BinnedBuilder<T, N, Bins>::~BVH_BinnedBuilder()
35{
36 //
37}
38
39// =======================================================================
40// function : GetSubVolumes
41// purpose :
42// =======================================================================
43template<class T, int N, int Bins>
44void BVH_BinnedBuilder<T, N, Bins>::GetSubVolumes (BVH_Set<T, N>* theSet,
45 BVH_Tree<T, N>* theBVH,
46 const Standard_Integer theNode,
47 BVH_BinVector& theBins,
48 const Standard_Integer theAxis)
49{
3a7a7013 50 const T aMin = BVH::VecComp<T, N>::Get (theBVH->MinPoint (theNode), theAxis);
51 const T aMax = BVH::VecComp<T, N>::Get (theBVH->MaxPoint (theNode), theAxis);
3c4e78f2 52
3a7a7013 53 const T anInverseStep = static_cast<T> (Bins) / (aMax - aMin);
3c4e78f2 54
55 for (Standard_Integer anIdx = theBVH->BegPrimitive (theNode); anIdx <= theBVH->EndPrimitive (theNode); ++anIdx)
56 {
57 typename BVH_Set<T, N>::BVH_BoxNt aBox = theSet->Box (anIdx);
58
3a7a7013 59 Standard_Integer aBinIndex = BVH::IntFloor<T> (
60 (theSet->Center (anIdx, theAxis) - aMin) * anInverseStep);
61
3c4e78f2 62 if (aBinIndex < 0)
63 {
64 aBinIndex = 0;
65 }
66 else if (aBinIndex >= Bins)
67 {
68 aBinIndex = Bins - 1;
69 }
70
71 theBins[aBinIndex].Count++;
72 theBins[aBinIndex].Box.Combine (aBox);
73 }
74}
75
3a7a7013 76namespace BVH
3c4e78f2 77{
78 // =======================================================================
79 // function : SplitPrimitives
80 // purpose :
81 // =======================================================================
82 template<class T, int N>
83 Standard_Integer SplitPrimitives (BVH_Set<T, N>* theSet,
84 const BVH_Box<T, N>& theBox,
85 const Standard_Integer theBeg,
86 const Standard_Integer theEnd,
87 const Standard_Integer theBin,
88 const Standard_Integer theAxis,
89 const Standard_Integer theBins)
90 {
3a7a7013 91 const T aMin = BVH::VecComp<T, N>::Get (theBox.CornerMin(), theAxis);
92 const T aMax = BVH::VecComp<T, N>::Get (theBox.CornerMax(), theAxis);
3c4e78f2 93
3a7a7013 94 const T anInverseStep = static_cast<T> (theBins) / (aMax - aMin);
3c4e78f2 95
96 Standard_Integer aLftIdx (theBeg);
97 Standard_Integer aRghIdx (theEnd);
98
99 do
100 {
3a7a7013 101 while (BVH::IntFloor<T> ((theSet->Center (aLftIdx, theAxis) - aMin) * anInverseStep) <= theBin && aLftIdx < theEnd)
3c4e78f2 102 {
103 ++aLftIdx;
104 }
3a7a7013 105 while (BVH::IntFloor<T> ((theSet->Center (aRghIdx, theAxis) - aMin) * anInverseStep) > theBin && aRghIdx > theBeg)
3c4e78f2 106 {
107 --aRghIdx;
108 }
109
110 if (aLftIdx <= aRghIdx)
111 {
112 if (aLftIdx != aRghIdx)
113 {
114 theSet->Swap (aLftIdx, aRghIdx);
115 }
116
117 ++aLftIdx;
118 --aRghIdx;
119 }
120 } while (aLftIdx <= aRghIdx);
121
122 return aLftIdx;
123 }
124}
125
126#if defined (_WIN32) && defined (max)
127 #undef max
128#endif
129
130#include <limits>
131
132// =======================================================================
133// function : BuildNode
134// purpose :
135// =======================================================================
136template<class T, int N, int Bins>
137void BVH_BinnedBuilder<T, N, Bins>::BuildNode (BVH_Set<T, N>* theSet,
138 BVH_Tree<T, N>* theBVH,
139 const Standard_Integer theNode)
140{
228de226 141 const Standard_Integer aNodeBegPrimitive = theBVH->BegPrimitive (theNode);
142 const Standard_Integer aNodeEndPrimitive = theBVH->EndPrimitive (theNode);
3c4e78f2 143
228de226 144 if (aNodeEndPrimitive - aNodeBegPrimitive < BVH_Builder<T, N>::myLeafNodeSize)
145 {
146 return; // node does not require partitioning
147 }
148
149 const BVH_Box<T, N> anAABB (theBVH->MinPoint (theNode),
150 theBVH->MaxPoint (theNode));
151
152 const typename BVH_Box<T, N>::BVH_VecNt aSize = anAABB.Size();
3c4e78f2 153
154 // Parameters for storing best split
155 Standard_Integer aMinSplitAxis = -1;
156 Standard_Integer aMinSplitIndex = 0;
157 Standard_Integer aMinSplitNumLft = 0;
158 Standard_Integer aMinSplitNumRgh = 0;
159
160 BVH_Box<T, N> aMinSplitBoxLft;
161 BVH_Box<T, N> aMinSplitBoxRgh;
162
163 Standard_Real aMinSplitCost = std::numeric_limits<Standard_Real>::max();
164
165 // Find best split
166 for (Standard_Integer anAxis = 0; anAxis < (N < 4 ? N : 3); ++anAxis)
167 {
679d3878 168 if (BVH::VecComp<T, N>::Get (aSize, anAxis) <= BVH::THE_NODE_MIN_SIZE)
3c4e78f2 169 continue;
170
171 BVH_BinVector aBins;
172 GetSubVolumes (theSet, theBVH, theNode, aBins, anAxis);
173
174 // Choose the best split (with minimum SAH cost)
175 for (Standard_Integer aSplit = 1; aSplit < Bins; ++aSplit)
176 {
177 Standard_Integer aLftCount = 0;
178 Standard_Integer aRghCount = 0;
179
180 BVH_Box<T, N> aLftAABB;
181 BVH_Box<T, N> aRghAABB;
182
183 for (Standard_Integer anIndex = 0; anIndex < aSplit; ++anIndex)
184 {
185 aLftCount += aBins[anIndex].Count;
186 aLftAABB.Combine (aBins[anIndex].Box);
187 }
188
189 for (Standard_Integer anIndex = aSplit; anIndex < Bins; ++anIndex)
190 {
191 aRghCount += aBins[anIndex].Count;
192 aRghAABB.Combine (aBins[anIndex].Box);
193 }
194
195 // Simple SAH evaluation
196 Standard_Real aCost = (static_cast<Standard_Real> (aLftAABB.Area()) /* / aNodeArea */) * aLftCount
197 + (static_cast<Standard_Real> (aRghAABB.Area()) /* / aNodeArea */) * aRghCount;
198
199 if (aCost <= aMinSplitCost)
200 {
201 aMinSplitCost = aCost;
202 aMinSplitAxis = anAxis;
203 aMinSplitIndex = aSplit;
204 aMinSplitBoxLft = aLftAABB;
205 aMinSplitBoxRgh = aRghAABB;
206 aMinSplitNumLft = aLftCount;
207 aMinSplitNumRgh = aRghCount;
208 }
209 }
210 }
211
3c4e78f2 212 theBVH->SetInner (theNode);
213
228de226 214 Standard_Integer aMiddle = -1;
215
61aa7f3d 216 if (aMinSplitNumLft == 0 || aMinSplitNumRgh == 0 || aMinSplitAxis == -1) // case of objects with the same center
228de226 217 {
218 aMinSplitBoxLft.Clear();
219 aMinSplitBoxRgh.Clear();
220
221 aMiddle = std::max (aNodeBegPrimitive + 1,
222 static_cast<Standard_Integer> ((aNodeBegPrimitive + aNodeEndPrimitive) / 2.f));
223
224 aMinSplitNumLft = aMiddle - aNodeBegPrimitive;
225
226 for (Standard_Integer anIndex = aNodeBegPrimitive; anIndex < aMiddle; ++anIndex)
227 {
228 aMinSplitBoxLft.Combine (theSet->Box (anIndex));
229 }
230
231 aMinSplitNumRgh = aNodeEndPrimitive - aMiddle + 1;
232
233 for (Standard_Integer anIndex = aNodeEndPrimitive; anIndex >= aMiddle; --anIndex)
234 {
235 aMinSplitBoxRgh.Combine (theSet->Box (anIndex));
236 }
237 }
238 else
239 {
3a7a7013 240 aMiddle = BVH::SplitPrimitives<T, N> (theSet, anAABB,
228de226 241 aNodeBegPrimitive, aNodeEndPrimitive, aMinSplitIndex - 1, aMinSplitAxis, Bins);
242 }
3c4e78f2 243
244 static const Standard_Integer aLftNode = 1;
245 static const Standard_Integer aRghNode = 2;
246
247 // Setting up tasks for child nodes
248 for (Standard_Integer aSide = aLftNode; aSide <= aRghNode; ++aSide)
249 {
250 typename BVH_Box<T, N>::BVH_VecNt aMinPoint = (aSide == aLftNode)
251 ? aMinSplitBoxLft.CornerMin()
252 : aMinSplitBoxRgh.CornerMin();
253 typename BVH_Box<T, N>::BVH_VecNt aMaxPoint = (aSide == aLftNode)
254 ? aMinSplitBoxLft.CornerMax()
255 : aMinSplitBoxRgh.CornerMax();
256
257 Standard_Integer aBegPrimitive = (aSide == aLftNode)
228de226 258 ? aNodeBegPrimitive
3c4e78f2 259 : aMiddle;
260 Standard_Integer aEndPrimitive = (aSide == aLftNode)
261 ? aMiddle - 1
228de226 262 : aNodeEndPrimitive;
3c4e78f2 263
264 Standard_Integer aChildIndex = theBVH->AddLeafNode (aMinPoint, aMaxPoint, aBegPrimitive, aEndPrimitive);
265
266 theBVH->Level (aChildIndex) = theBVH->Level (theNode) + 1;
267
268 // Check to see if child node must be split
269 const Standard_Integer aNbPimitives = (aSide == aLftNode)
270 ? aMinSplitNumLft
271 : aMinSplitNumRgh;
272
273 if (aSide == aLftNode)
274 theBVH->LeftChild (theNode) = aChildIndex;
275 else
276 theBVH->RightChild (theNode) = aChildIndex;
277
278 const Standard_Boolean isLeaf = aNbPimitives <= BVH_Builder<T, N>::myLeafNodeSize
279 || theBVH->Level (aChildIndex) >= BVH_Builder<T, N>::myMaxTreeDepth;
280
281 if (!isLeaf)
fc73a202 282 {
0ef61b50 283 BVH_QueueBuilder<T, N>::myTasksQueue.Append (aChildIndex);
fc73a202 284 }
285
286 BVH_Builder<T, N>::UpdateDepth (theBVH, theBVH->Level (aChildIndex));
3c4e78f2 287 }
288}