1 #ifndef GIM_BOX_SET_H_INCLUDED
2 #define GIM_BOX_SET_H_INCLUDED
4 /*! \file gim_box_set.h
5 \author Francisco Leon Najera
8 This source file is part of GIMPACT Library.
10 For the latest info, see http://gimpact.sourceforge.net/
12 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
13 email: projectileman@yahoo.com
16 This software is provided 'as-is', without any express or implied warranty.
17 In no event will the authors be held liable for any damages arising from the use of this software.
18 Permission is granted to anyone to use this software for any purpose,
19 including commercial applications, and to alter it and redistribute it freely,
20 subject to the following restrictions:
22 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.
23 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
24 3. This notice may not be removed or altered from any source distribution.
28 #include "LinearMath/btAlignedObjectArray.h"
30 #include "btBoxCollision.h"
31 #include "btTriangleShapeEx.h"
45 GIM_PAIR(const GIM_PAIR & p)
47 m_index1 = p.m_index1;
48 m_index2 = p.m_index2;
51 GIM_PAIR(int index1, int index2)
59 class btPairSet: public btAlignedObjectArray<GIM_PAIR>
66 inline void push_pair(int index1,int index2)
68 push_back(GIM_PAIR(index1,index2));
71 inline void push_pair_inv(int index1,int index2)
73 push_back(GIM_PAIR(index2,index1));
78 ///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
85 //! Node Structure for trees
86 class GIM_BVH_TREE_NODE
91 int m_escapeIndexOrDataIndex;
95 m_escapeIndexOrDataIndex = 0;
98 SIMD_FORCE_INLINE bool isLeafNode() const
100 //skipindex is negative (internal node), triangleindex >=0 (leafnode)
101 return (m_escapeIndexOrDataIndex>=0);
104 SIMD_FORCE_INLINE int getEscapeIndex() const
106 //btAssert(m_escapeIndexOrDataIndex < 0);
107 return -m_escapeIndexOrDataIndex;
110 SIMD_FORCE_INLINE void setEscapeIndex(int index)
112 m_escapeIndexOrDataIndex = -index;
115 SIMD_FORCE_INLINE int getDataIndex() const
117 //btAssert(m_escapeIndexOrDataIndex >= 0);
119 return m_escapeIndexOrDataIndex;
122 SIMD_FORCE_INLINE void setDataIndex(int index)
124 m_escapeIndexOrDataIndex = index;
130 class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
135 class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<GIM_BVH_TREE_NODE>
142 //! Basic Box tree structure
147 GIM_BVH_TREE_NODE_ARRAY m_node_array;
149 int _sort_and_calc_splitting_index(
150 GIM_BVH_DATA_ARRAY & primitive_boxes,
151 int startIndex, int endIndex, int splitAxis);
153 int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
155 void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
162 //! prototype functions for box tree management
164 void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
166 SIMD_FORCE_INLINE void clearNodes()
168 m_node_array.clear();
173 SIMD_FORCE_INLINE int getNodeCount() const
178 //! tells if the node is a leaf
179 SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
181 return m_node_array[nodeindex].isLeafNode();
184 SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
186 return m_node_array[nodeindex].getDataIndex();
189 SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
191 bound = m_node_array[nodeindex].m_bound;
194 SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
196 m_node_array[nodeindex].m_bound = bound;
199 SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
204 SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
206 if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
207 return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
210 SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
212 return m_node_array[nodeindex].getEscapeIndex();
215 SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
217 return &m_node_array[index];
224 //! Prototype Base class for primitive classification
226 This class is a wrapper for primitive collections.
227 This tells relevant info for the Bounding Box set classes, which take care of space classification.
228 This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
230 class btPrimitiveManagerBase
234 virtual ~btPrimitiveManagerBase() {}
236 //! determines if this manager consist on only triangles, which special case will be optimized
237 virtual bool is_trimesh() const = 0;
238 virtual int get_primitive_count() const = 0;
239 virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
240 //! retrieves only the points of the triangle, and the collision margin
241 virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
245 //! Structure for containing Boxes
247 This class offers an structure for managing a box tree of primitives.
248 Requires a Primitive prototype (like btPrimitiveManagerBase )
253 btBvhTree m_box_tree;
254 btPrimitiveManagerBase * m_primitive_manager;
261 //! this constructor doesn't build the tree. you must call buildSet
264 m_primitive_manager = NULL;
267 //! this constructor doesn't build the tree. you must call buildSet
268 btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
270 m_primitive_manager = primitive_manager;
273 SIMD_FORCE_INLINE btAABB getGlobalBox() const
276 getNodeBound(0, totalbox);
280 SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
282 m_primitive_manager = primitive_manager;
285 SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
287 return m_primitive_manager;
291 //! node manager prototype functions
294 //! this attemps to refit the box set.
295 SIMD_FORCE_INLINE void update()
300 //! this rebuild the entire set
303 //! returns the indices of the primitives in the m_primitive_manager
304 bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
306 //! returns the indices of the primitives in the m_primitive_manager
307 SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
308 const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
311 transbox.appy_transform(transform);
312 return boxQuery(transbox,collided_results);
315 //! returns the indices of the primitives in the m_primitive_manager
317 const btVector3 & ray_dir,const btVector3 & ray_origin ,
318 btAlignedObjectArray<int> & collided_results) const;
320 //! tells if this set has hierarcht
321 SIMD_FORCE_INLINE bool hasHierarchy() const
326 //! tells if this set is a trimesh
327 SIMD_FORCE_INLINE bool isTrimesh() const
329 return m_primitive_manager->is_trimesh();
333 SIMD_FORCE_INLINE int getNodeCount() const
335 return m_box_tree.getNodeCount();
338 //! tells if the node is a leaf
339 SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
341 return m_box_tree.isLeafNode(nodeindex);
344 SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
346 return m_box_tree.getNodeData(nodeindex);
349 SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
351 m_box_tree.getNodeBound(nodeindex, bound);
354 SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
356 m_box_tree.setNodeBound(nodeindex, bound);
360 SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
362 return m_box_tree.getLeftNode(nodeindex);
365 SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
367 return m_box_tree.getRightNode(nodeindex);
370 SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
372 return m_box_tree.getEscapeNodeIndex(nodeindex);
375 SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
377 m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
381 SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
383 return m_box_tree.get_node_pointer(index);
386 #ifdef TRI_COLLISION_PROFILING
387 static float getAverageTreeCollisionTime();
388 #endif //TRI_COLLISION_PROFILING
390 static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
391 btGImpactBvh * boxset2, const btTransform & trans2,
392 btPairSet & collision_pairs);
396 #endif // GIM_BOXPRUNING_H_INCLUDED