Newton Dynamics  4.00
ndBvhNode.h
1 /* Copyright (c) <2003-2022> <Julio Jerez, Newton Game Dynamics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 *
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 *
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #ifndef __ND_SCENE_NODE_H__
23 #define __ND_SCENE_NODE_H__
24 
25 #include "ndCollisionStdafx.h"
26 
27 //#define D_NEW_SCENE
28 
29 class ndBodyKinematic;
30 class ndBvhLeafNode;
31 class ndBvhInternalNode;
32 
33 D_MSV_NEWTON_ALIGN_32
34 class ndBvhNode : public ndContainersFreeListAlloc<ndBvhNode>
35 {
36  public:
37  ndBvhNode(ndBvhNode* const parent);
38  ndBvhNode(const ndBvhNode& src);
39  virtual ~ndBvhNode();
40  virtual ndBvhNode* Clone() const;
41 
42  void Kill();
43  void GetAabb(ndVector& minBox, ndVector& maxBox) const;
44  void SetAabb(const ndVector& minBox, const ndVector& maxBox);
45 
46  virtual ndBvhNode* GetAsSceneNode() const;
47  virtual ndBvhLeafNode* GetAsSceneBodyNode() const;
48  virtual ndBvhInternalNode* GetAsSceneTreeNode() const;
49 
50  virtual ndBvhNode* GetLeft() const;
51  virtual ndBvhNode* GetRight() const;
52  virtual ndBodyKinematic* GetBody() const;
53 
54  virtual bool SanityCheck(ndUnsigned32 level) const;
55 
56  ndVector m_minBox;
57  ndVector m_maxBox;
58  ndBvhNode* m_parent;
59 #ifdef D_NEW_SCENE
60  ndBvhNode* m_buildNode;
61 #endif
62  ndSpinLock m_lock;
63  ndInt32 m_depthLevel;
64  ndUnsigned8 m_isDead;
65  ndUnsigned8 m_bhvLinked;
66 #ifdef _DEBUG
67  ndInt32 m_nodeId;
68 #endif
69 
70  static ndVector m_aabbQuantization;
71  static ndVector m_aabbInvQuantization;
72 } D_GCC_NEWTON_ALIGN_32 ;
73 
75 {
76  public:
79  virtual ~ndBvhInternalNode();
80  virtual ndBvhNode* Clone() const;
81 
82  virtual ndBvhNode* GetLeft() const;
83  virtual ndBvhNode* GetRight() const;
84  virtual ndBvhInternalNode* GetAsSceneTreeNode() const;
85 
86  bool SanityCheck(ndUnsigned32 level) const;
87 
88  ndBvhNode* m_left;
89  ndBvhNode* m_right;
90 } D_GCC_NEWTON_ALIGN_32;
91 
92 class ndBvhLeafNode : public ndBvhNode
93 {
94  public:
95  ndBvhLeafNode(ndBodyKinematic* const body);
96  ndBvhLeafNode(const ndBvhLeafNode& src);
97  virtual ~ndBvhLeafNode();
98 
99  virtual ndBvhNode* Clone() const;
100  virtual ndBodyKinematic* GetBody() const;
101  virtual ndBvhLeafNode* GetAsSceneBodyNode() const;
102 
103  ndBodyKinematic* m_body;
104 };
105 
107 {
108  public:
109  ndInt32 m_x;
110  ndInt32 m_y;
111  ndInt32 m_z;
112  ndBvhNode* m_node;
113 };
114 
116 {
117  public:
118  ndInt32 m_location : 30;
119  ndUnsigned32 m_cellTest : 1;
120 };
121 
123 {
124  public:
125  enum ndState
126  {
127  m_beginBuild,
128  m_calculateBoxes,
129  m_buildLayer,
130  m_enumerateLayers,
131  m_endBuild,
132  };
133 
135 
136  void Init(ndInt32 maxCount);
137 
138  ndVector m_size;
139  ndVector m_origin;
140  ndArray<ndBottomUpCell> m_cellBuffer0;
141  ndArray<ndBottomUpCell> m_cellBuffer1;
142  ndArray<ndCellScanPrefix> m_cellCounts0;
143  ndArray<ndCellScanPrefix> m_cellCounts1;
144  ndArray<ndBvhNode*> m_tempNodeBuffer;
145 
146  ndBvhNode* m_root;
147  ndBvhNode** m_srcArray;
148  ndBvhNode** m_tmpArray;
149  ndBvhNode** m_parentsArray;
150 
151  ndInt32 m_depthLevel;
152  ndInt32 m_leafNodesCount;
153  ndState m_state;
154 };
155 
156 class ndBvhNodeArray : public ndArray<ndBvhNode*>
157 {
158  public:
159  ndBvhNodeArray();
160  ndBvhNodeArray(const ndBvhNodeArray& src);
161  ~ndBvhNodeArray();
162 
163  void CleanUp();
164  void Swap(ndBvhNodeArray& src);
165 
166  ndUnsigned32 m_isDirty;
167  ndUnsigned32 m_scansCount;
168  ndUnsigned32 m_scans[256];
169 };
170 
172 {
173  public:
177 
178  void CleanUp();
179  ndBvhNode* AddBody(ndBodyKinematic* const body, ndBvhNode* root);
180  void RemoveBody(ndBodyKinematic* const body);
181 
182  void UpdateScene(ndThreadPool& threadPool);
183  ndBvhNode* BuildBvhTree(ndThreadPool& threadPool);
184 
185  ndBvhNodeArray& GetNodeArray();
186  ndBvhLeafNode* GetLeafNode(ndBodyKinematic* const body) const;
187 
188  private:
189  void Update(ndThreadPool& threadPool);
190  bool BuildBvhTreeInitNodes(ndThreadPool& threadPool);
191  void BuildBvhTreeSetNodesDepth(ndThreadPool& threadPool);
192  void BuildBvhGenerateLayerGrids(ndThreadPool& threadPool);
193  void BuildBvhTreeCalculateLeafBoxes(ndThreadPool& threadPool);
194 
195  ndBvhNode* BuildIncrementalBvhTree(ndThreadPool& threadPool);
196  ndInt32 BuildSmallBvhTree(ndThreadPool& threadPool, ndBvhNode** const parentsArray, ndInt32 bashCount);
197 
198  void BuildBvhTreeSwapBuffers(ndThreadPool& threadPool);
199 
200  ndBvhNodeArray m_workingArray;
201 #ifdef D_NEW_SCENE
202  ndBvhNodeArray m_buildArray;
203 #endif
204 
205  ndBuildBvhTreeBuildState m_bvhBuildState;
206 };
207 
208 
209 // **************************************************************
210 //
211 // inline functions
212 //
213 // **************************************************************
214 inline ndBvhNode::ndBvhNode(ndBvhNode* const parent)
216  ,m_minBox(ndFloat32(-1.0e15f))
217  ,m_maxBox(ndFloat32(1.0e15f))
218  ,m_parent(parent)
219 #ifdef D_NEW_SCENE
220  ,m_buildNode(nullptr)
221 #endif
222  ,m_lock()
223  ,m_depthLevel(0)
224  ,m_isDead(0)
225  ,m_bhvLinked(0)
226 {
227 #ifdef _DEBUG
228  m_nodeId = 0;
229 #endif
230 }
231 
232 inline ndBvhNode::ndBvhNode(const ndBvhNode& src)
234  ,m_minBox(src.m_minBox)
235  ,m_maxBox(src.m_maxBox)
236  ,m_parent(nullptr)
237 #ifdef D_NEW_SCENE
238  ,m_buildNode((ndBvhNode*)&src)
239 #endif
240  ,m_lock()
241  ,m_depthLevel(0)
242  ,m_isDead(0)
243  ,m_bhvLinked(0)
244 {
245 #ifdef D_NEW_SCENE
246  m_buildNode->m_buildNode = this;
247 #endif
248 
249 #ifdef _DEBUG
250  m_nodeId = 0;
251 #endif
252 }
253 
254 inline ndBvhNode::~ndBvhNode()
255 {
256 }
257 
258 inline ndBvhNode* ndBvhNode::GetAsSceneNode() const
259 {
260  return (ndBvhNode*)this;
261 }
262 
263 inline ndBvhLeafNode* ndBvhNode::GetAsSceneBodyNode() const
264 {
265  return nullptr;
266 }
267 
268 inline ndBvhInternalNode* ndBvhNode::GetAsSceneTreeNode() const
269 {
270  return nullptr;
271 }
272 
273 inline ndBodyKinematic* ndBvhNode::GetBody() const
274 {
275  return nullptr;
276 }
277 
278 inline ndBvhNode* ndBvhNode::GetLeft() const
279 {
280  return nullptr;
281 }
282 
283 inline ndBvhNode* ndBvhNode::GetRight() const
284 {
285  return nullptr;
286 }
287 
288 inline void ndBvhNode::Kill()
289 {
290  m_isDead = 1;
291 #ifdef D_NEW_SCENE
292  m_buildNode->m_isDead = 1;
293 #endif
294 }
295 
296 inline void ndBvhNode::GetAabb(ndVector& minBox, ndVector& maxBox) const
297 {
298  minBox = m_minBox;
299  maxBox = m_maxBox;
300 }
301 
302 inline void ndBvhNode::SetAabb(const ndVector& minBox, const ndVector& maxBox)
303 {
304  ndAssert(minBox.m_x <= maxBox.m_x);
305  ndAssert(minBox.m_y <= maxBox.m_y);
306  ndAssert(minBox.m_z <= maxBox.m_z);
307 
308  const ndVector p0(minBox * m_aabbQuantization);
309  const ndVector p1(maxBox * m_aabbQuantization + ndVector::m_one);
310 
311  m_minBox = p0.Floor() * m_aabbInvQuantization;
312  m_maxBox = p1.Floor() * m_aabbInvQuantization;
313 
314  ndAssert(m_minBox.m_w == ndFloat32(0.0f));
315  ndAssert(m_maxBox.m_w == ndFloat32(0.0f));
316 }
317 
318 inline ndBvhNode* ndBvhNode::Clone() const
319 {
320  ndAssert(0);
321  return nullptr;
322 }
323 
324 inline ndBvhLeafNode* ndBvhLeafNode::GetAsSceneBodyNode() const
325 {
326  return (ndBvhLeafNode*)this;
327 }
328 
329 inline ndBodyKinematic* ndBvhLeafNode::GetBody() const
330 {
331  return m_body;
332 }
333 
334 inline ndBvhInternalNode* ndBvhInternalNode::GetAsSceneTreeNode() const
335 {
336  return (ndBvhInternalNode*)this;
337 }
338 
339 inline ndBvhNode* ndBvhInternalNode::GetLeft() const
340 {
341  return m_left;
342 }
343 
344 inline ndBvhNode* ndBvhInternalNode::GetRight() const
345 {
346  return m_right;
347 }
348 
349 inline ndBvhNodeArray& ndBvhSceneManager::GetNodeArray()
350 {
351  return m_workingArray;
352 }
353 
354 #endif
ndSpinLock
Simple spin lock for synchronizing threads for very short period of time.
Definition: ndUtils.h:212
ndArray< ndBottomUpCell >
ndBvhNodeArray
Definition: ndBvhNode.h:157
ndBvhInternalNode
Definition: ndBvhNode.h:75
ndBuildBvhTreeBuildState
Definition: ndBvhNode.h:123
ndBodyKinematic
Definition: ndBodyKinematic.h:40
ndBvhLeafNode
Definition: ndBvhNode.h:93
ndCellScanPrefix
Definition: ndBvhNode.h:116
ndBvhSceneManager
Definition: ndBvhNode.h:172
ndBvhNode
Definition: ndBvhNode.h:35
ndBottomUpCell
Definition: ndBvhNode.h:107
ndContainersFreeListAlloc
Definition: ndContainersAlloc.h:60
ndThreadPool
Definition: ndThreadPool.h:65
ndVector
Definition: ndVectorArmNeon.h:41