Bullet Collision Detection & Physics Library
btOptimizedBvh.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #include "btOptimizedBvh.h"
18 #include "LinearMath/btAabbUtil2.h"
20 
22 {
23 }
24 
26 {
27 }
28 
29 void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
30 {
31  m_useQuantization = useQuantizedAabbCompression;
32 
33  // NodeArray triangleNodes;
34 
35  struct NodeTriangleCallback : public btInternalTriangleIndexCallback
36  {
37  NodeArray& m_triangleNodes;
38 
39  NodeTriangleCallback& operator=(NodeTriangleCallback& other)
40  {
41  m_triangleNodes.copyFromArray(other.m_triangleNodes);
42  return *this;
43  }
44 
45  NodeTriangleCallback(NodeArray& triangleNodes)
46  : m_triangleNodes(triangleNodes)
47  {
48  }
49 
50  virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
51  {
52  btOptimizedBvhNode node;
53  btVector3 aabbMin, aabbMax;
56  aabbMin.setMin(triangle[0]);
57  aabbMax.setMax(triangle[0]);
58  aabbMin.setMin(triangle[1]);
59  aabbMax.setMax(triangle[1]);
60  aabbMin.setMin(triangle[2]);
61  aabbMax.setMax(triangle[2]);
62 
63  //with quantization?
64  node.m_aabbMinOrg = aabbMin;
65  node.m_aabbMaxOrg = aabbMax;
66 
67  node.m_escapeIndex = -1;
68 
69  //for child nodes
70  node.m_subPart = partId;
71  node.m_triangleIndex = triangleIndex;
72  m_triangleNodes.push_back(node);
73  }
74  };
75  struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
76  {
77  QuantizedNodeArray& m_triangleNodes;
78  const btQuantizedBvh* m_optimizedTree; // for quantization
79 
80  QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
81  {
82  m_triangleNodes.copyFromArray(other.m_triangleNodes);
83  m_optimizedTree = other.m_optimizedTree;
84  return *this;
85  }
86 
87  QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const btQuantizedBvh* tree)
88  : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
89  {
90  }
91 
92  virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
93  {
94  // The partId and triangle index must fit in the same (positive) integer
95  btAssert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
96  btAssert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
97  //negative indices are reserved for escapeIndex
98  btAssert(triangleIndex >= 0);
99 
100  btQuantizedBvhNode node;
101  btVector3 aabbMin, aabbMax;
104  aabbMin.setMin(triangle[0]);
105  aabbMax.setMax(triangle[0]);
106  aabbMin.setMin(triangle[1]);
107  aabbMax.setMax(triangle[1]);
108  aabbMin.setMin(triangle[2]);
109  aabbMax.setMax(triangle[2]);
110 
111  //PCK: add these checks for zero dimensions of aabb
112  const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
113  const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
114  if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
115  {
116  aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
117  aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
118  }
119  if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
120  {
121  aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
122  aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
123  }
124  if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
125  {
126  aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
127  aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
128  }
129 
130  m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
131  m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
132 
133  node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
134 
135  m_triangleNodes.push_back(node);
136  }
137  };
138 
139  int numLeafNodes = 0;
140 
141  if (m_useQuantization)
142  {
143  //initialize quantization values
144  setQuantizationValues(bvhAabbMin, bvhAabbMax);
145 
146  QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
147 
148  triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
149 
150  //now we have an array of leafnodes in m_leafNodes
151  numLeafNodes = m_quantizedLeafNodes.size();
152 
153  m_quantizedContiguousNodes.resize(2 * numLeafNodes);
154  }
155  else
156  {
157  NodeTriangleCallback callback(m_leafNodes);
158 
161 
162  triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
163 
164  //now we have an array of leafnodes in m_leafNodes
165  numLeafNodes = m_leafNodes.size();
166 
167  m_contiguousNodes.resize(2 * numLeafNodes);
168  }
169 
170  m_curNodeIndex = 0;
171 
172  buildTree(0, numLeafNodes);
173 
176  {
179  subtree.m_rootNodeIndex = 0;
180  subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
181  }
182 
183  //PCK: update the copy of the size
185 
186  //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
188  m_leafNodes.clear();
189 }
190 
191 void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
192 {
193  if (m_useQuantization)
194  {
195  setQuantizationValues(aabbMin, aabbMax);
196 
197  updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
198 
200 
201  int i;
202  for (i = 0; i < m_SubtreeHeaders.size(); i++)
203  {
204  btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
206  }
207  }
208  else
209  {
210  }
211 }
212 
213 void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
214 {
215  //incrementally initialize quantization values
217 
218  btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
219  btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
220  btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
221 
222  btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
223  btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
224  btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
225 
228 
229  unsigned short quantizedQueryAabbMin[3];
230  unsigned short quantizedQueryAabbMax[3];
231 
232  quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
233  quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
234 
235  int i;
236  for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
237  {
238  btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
239 
240  //PCK: unsigned instead of bool
241  unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
242  if (overlap != 0)
243  {
244  updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
245 
247  }
248  }
249 }
250 
251 void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
252 {
253  (void)index;
254 
256 
257  int curNodeSubPart = -1;
258 
259  //get access info to trianglemesh data
260  const unsigned char* vertexbase = 0;
261  int numverts = 0;
263  int stride = 0;
264  const unsigned char* indexbase = 0;
265  int indexstride = 0;
266  int numfaces = 0;
267  PHY_ScalarType indicestype = PHY_INTEGER;
268 
269  btVector3 triangleVerts[3];
270  btVector3 aabbMin, aabbMax;
271  const btVector3& meshScaling = meshInterface->getScaling();
272 
273  int i;
274  for (i = endNode - 1; i >= firstNode; i--)
275  {
277  if (curNode.isLeafNode())
278  {
279  //recalc aabb from triangle data
280  int nodeSubPart = curNode.getPartId();
281  int nodeTriangleIndex = curNode.getTriangleIndex();
282  if (nodeSubPart != curNodeSubPart)
283  {
284  if (curNodeSubPart >= 0)
285  meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
286  meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
287 
288  curNodeSubPart = nodeSubPart;
289  btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
290  }
291  //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
292 
293  unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
294 
295  for (int j = 2; j >= 0; j--)
296  {
297  int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
298  if (type == PHY_FLOAT)
299  {
300  float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
301  triangleVerts[j] = btVector3(
302  graphicsbase[0] * meshScaling.getX(),
303  graphicsbase[1] * meshScaling.getY(),
304  graphicsbase[2] * meshScaling.getZ());
305  }
306  else
307  {
308  double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
309  triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
310  }
311  }
312 
315  aabbMin.setMin(triangleVerts[0]);
316  aabbMax.setMax(triangleVerts[0]);
317  aabbMin.setMin(triangleVerts[1]);
318  aabbMax.setMax(triangleVerts[1]);
319  aabbMin.setMin(triangleVerts[2]);
320  aabbMax.setMax(triangleVerts[2]);
321 
322  quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
323  quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
324  }
325  else
326  {
327  //combine aabb from both children
328 
329  btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
330 
331  btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
332 
333  {
334  for (int i = 0; i < 3; i++)
335  {
336  curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
337  if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
338  curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
339 
340  curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
341  if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
342  curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
343  }
344  }
345  }
346  }
347 
348  if (curNodeSubPart >= 0)
349  meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
350 }
351 
353 btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
354 {
355  btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
356 
357  //we don't add additional data so just do a static upcast
358  return static_cast<btOptimizedBvh*>(bvh);
359 }
void push_back(const T &_Val)
#define BT_LARGE_FLOAT
Definition: btScalar.h:296
void setQuantizationValues(const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax, btScalar quantizationMargin=btScalar(1.0))
***************************************** expert/internal use only ************************* ...
int getTriangleIndex() const
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
void setZ(btScalar _z)
Set the z value.
Definition: btVector3.h:571
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
btVector3 m_bvhAabbMax
bool isLeafNode() const
#define btAssert(x)
Definition: btScalar.h:133
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
void updateBvhNodes(btStridingMeshInterface *meshInterface, int firstNode, int endNode, int index)
void copyFromArray(const btAlignedObjectArray &otherArray)
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
btBvhSubtreeInfo provides info to gather a subtree of limited size
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
void setX(btScalar _x)
Set the x value.
Definition: btVector3.h:567
#define MAX_NUM_PARTS_IN_BITS
NodeArray m_contiguousNodes
NodeArray m_leafNodes
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
void setAabbFromQuantizeNode(const btQuantizedBvhNode &quantizedNode)
unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int *aabbMin1, const unsigned short int *aabbMax1, const unsigned short int *aabbMin2, const unsigned short int *aabbMax2)
Definition: btAabbUtil2.h:201
btOptimizedBvhNode contains both internal and leaf node information.
void setY(btScalar _y)
Set the y value.
Definition: btVector3.h:569
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
btQuantizedBvhNode is a compressed aabb node, 16 bytes.
BvhSubtreeInfoArray m_SubtreeHeaders
btVector3 m_bvhAabbMin
static btQuantizedBvh * deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
deSerializeInPlace loads and initializes a BVH from a buffer in memory &#39;in place&#39; ...
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
int size() const
return the number of elements in the array
unsigned short int m_quantizedAabbMax[3]
The btStridingMeshInterface is the interface class for high performance generic access to triangle me...
const btVector3 & getScaling() const
void resize(int newsize, const T &fillData=T())
static btOptimizedBvh * deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
deSerializeInPlace loads and initializes a BVH from a buffer in memory &#39;in place&#39; ...
int getEscapeIndex() const
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int &numverts, PHY_ScalarType &type, int &stride, const unsigned char **indexbase, int &indexstride, int &numfaces, PHY_ScalarType &indicestype, int subpart=0) const =0
The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU...
unsigned short int m_quantizedAabbMin[3]
T & expand(const T &fillValue=T())
unsigned short int m_quantizedAabbMax[3]
void buildTree(int startIndex, int endIndex)
virtual void unLockReadOnlyVertexBase(int subpart) const =0
void quantize(unsigned short *out, const btVector3 &point, int isMax) const
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:609
QuantizedNodeArray m_quantizedLeafNodes
unsigned short int m_quantizedAabbMin[3]
virtual ~btOptimizedBvh()
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:626
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
void refitPartial(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
QuantizedNodeArray m_quantizedContiguousNodes
int getPartId() const