Changeset View
Changeset View
Standalone View
Standalone View
extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
| Show All 20 Lines | |||||
| 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. | 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. | ||||
| 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||||
| 3. This notice may not be removed or altered from any source distribution. | 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | */ | ||||
| #include "btGImpactBvh.h" | #include "btGImpactBvh.h" | ||||
| #include "btQuantization.h" | #include "btQuantization.h" | ||||
| #include "btGImpactQuantizedBvhStructs.h" | |||||
| ///btQuantizedBvhNode is a compressed aabb node, 16 bytes. | |||||
| ///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). | |||||
| ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE | |||||
| { | |||||
| //12 bytes | |||||
| unsigned short int m_quantizedAabbMin[3]; | |||||
| unsigned short int m_quantizedAabbMax[3]; | |||||
| //4 bytes | |||||
| int m_escapeIndexOrDataIndex; | |||||
| BT_QUANTIZED_BVH_NODE() | |||||
| { | |||||
| m_escapeIndexOrDataIndex = 0; | |||||
| } | |||||
| SIMD_FORCE_INLINE bool isLeafNode() const | |||||
| { | |||||
| //skipindex is negative (internal node), triangleindex >=0 (leafnode) | |||||
| return (m_escapeIndexOrDataIndex>=0); | |||||
| } | |||||
| SIMD_FORCE_INLINE int getEscapeIndex() const | |||||
| { | |||||
| //btAssert(m_escapeIndexOrDataIndex < 0); | |||||
| return -m_escapeIndexOrDataIndex; | |||||
| } | |||||
| SIMD_FORCE_INLINE void setEscapeIndex(int index) | |||||
| { | |||||
| m_escapeIndexOrDataIndex = -index; | |||||
| } | |||||
| SIMD_FORCE_INLINE int getDataIndex() const | |||||
| { | |||||
| //btAssert(m_escapeIndexOrDataIndex >= 0); | |||||
| return m_escapeIndexOrDataIndex; | |||||
| } | |||||
| SIMD_FORCE_INLINE void setDataIndex(int index) | |||||
| { | |||||
| m_escapeIndexOrDataIndex = index; | |||||
| } | |||||
| SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( | |||||
| unsigned short * quantizedMin,unsigned short * quantizedMax) const | |||||
| { | |||||
| if(m_quantizedAabbMin[0] > quantizedMax[0] || | |||||
| m_quantizedAabbMax[0] < quantizedMin[0] || | |||||
| m_quantizedAabbMin[1] > quantizedMax[1] || | |||||
| m_quantizedAabbMax[1] < quantizedMin[1] || | |||||
| m_quantizedAabbMin[2] > quantizedMax[2] || | |||||
| m_quantizedAabbMax[2] < quantizedMin[2]) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE> | class GIM_QUANTIZED_BVH_NODE_ARRAY : public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE> | ||||
| { | { | ||||
| }; | }; | ||||
| //! Basic Box tree structure | //! Basic Box tree structure | ||||
| class btQuantizedBvhTree | class btQuantizedBvhTree | ||||
| { | { | ||||
| protected: | protected: | ||||
| int m_num_nodes; | int m_num_nodes; | ||||
| GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array; | GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array; | ||||
| btAABB m_global_bound; | btAABB m_global_bound; | ||||
| btVector3 m_bvhQuantization; | btVector3 m_bvhQuantization; | ||||
| protected: | protected: | ||||
| void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); | void calc_quantization(GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin = btScalar(1.0)); | ||||
| int _sort_and_calc_splitting_index( | int _sort_and_calc_splitting_index( | ||||
| GIM_BVH_DATA_ARRAY & primitive_boxes, | GIM_BVH_DATA_ARRAY& primitive_boxes, | ||||
| int startIndex, int endIndex, int splitAxis); | int startIndex, int endIndex, int splitAxis); | ||||
| int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); | int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex); | ||||
| void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); | void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex); | ||||
| public: | public: | ||||
| btQuantizedBvhTree() | btQuantizedBvhTree() | ||||
| { | { | ||||
| m_num_nodes = 0; | m_num_nodes = 0; | ||||
| } | } | ||||
| //! prototype functions for box tree management | //! prototype functions for box tree management | ||||
| //!@{ | //!@{ | ||||
| void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); | void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes); | ||||
| SIMD_FORCE_INLINE void quantizePoint( | SIMD_FORCE_INLINE void quantizePoint( | ||||
| unsigned short * quantizedpoint, const btVector3 & point) const | unsigned short* quantizedpoint, const btVector3& point) const | ||||
| { | { | ||||
| bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization); | bt_quantize_clamp(quantizedpoint, point, m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( | SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( | ||||
| int node_index, | int node_index, | ||||
| unsigned short * quantizedMin,unsigned short * quantizedMax) const | unsigned short* quantizedMin, unsigned short* quantizedMax) const | ||||
| { | { | ||||
| return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax); | return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin, quantizedMax); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void clearNodes() | SIMD_FORCE_INLINE void clearNodes() | ||||
| { | { | ||||
| m_node_array.clear(); | m_node_array.clear(); | ||||
| m_num_nodes = 0; | m_num_nodes = 0; | ||||
| } | } | ||||
| Show All 9 Lines | SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const | ||||
| return m_node_array[nodeindex].isLeafNode(); | return m_node_array[nodeindex].isLeafNode(); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getNodeData(int nodeindex) const | SIMD_FORCE_INLINE int getNodeData(int nodeindex) const | ||||
| { | { | ||||
| return m_node_array[nodeindex].getDataIndex(); | return m_node_array[nodeindex].getDataIndex(); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const | SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const | ||||
| { | { | ||||
| bound.m_min = bt_unquantize( | bound.m_min = bt_unquantize( | ||||
| m_node_array[nodeindex].m_quantizedAabbMin, | m_node_array[nodeindex].m_quantizedAabbMin, | ||||
| m_global_bound.m_min,m_bvhQuantization); | m_global_bound.m_min, m_bvhQuantization); | ||||
| bound.m_max = bt_unquantize( | bound.m_max = bt_unquantize( | ||||
| m_node_array[nodeindex].m_quantizedAabbMax, | m_node_array[nodeindex].m_quantizedAabbMax, | ||||
| m_global_bound.m_min,m_bvhQuantization); | m_global_bound.m_min, m_bvhQuantization); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) | SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound) | ||||
| { | { | ||||
| bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin, | bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMin, | ||||
| bound.m_min, | bound.m_min, | ||||
| m_global_bound.m_min, | m_global_bound.m_min, | ||||
| m_global_bound.m_max, | m_global_bound.m_max, | ||||
| m_bvhQuantization); | m_bvhQuantization); | ||||
| bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax, | bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMax, | ||||
| bound.m_max, | bound.m_max, | ||||
| m_global_bound.m_min, | m_global_bound.m_min, | ||||
| m_global_bound.m_max, | m_global_bound.m_max, | ||||
| m_bvhQuantization); | m_bvhQuantization); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const | SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const | ||||
| { | { | ||||
| return nodeindex+1; | return nodeindex + 1; | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getRightNode(int nodeindex) const | SIMD_FORCE_INLINE int getRightNode(int nodeindex) const | ||||
| { | { | ||||
| if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; | if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2; | ||||
| return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); | return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex(); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const | SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const | ||||
| { | { | ||||
| return m_node_array[nodeindex].getEscapeIndex(); | return m_node_array[nodeindex].getEscapeIndex(); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const | SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const | ||||
| { | { | ||||
| return &m_node_array[index]; | return &m_node_array[index]; | ||||
| } | } | ||||
| //!@} | //!@} | ||||
| }; | }; | ||||
| //! Structure for containing Boxes | //! Structure for containing Boxes | ||||
| /*! | /*! | ||||
| This class offers an structure for managing a box tree of primitives. | This class offers an structure for managing a box tree of primitives. | ||||
| Requires a Primitive prototype (like btPrimitiveManagerBase ) | Requires a Primitive prototype (like btPrimitiveManagerBase ) | ||||
| */ | */ | ||||
| class btGImpactQuantizedBvh | class btGImpactQuantizedBvh | ||||
| { | { | ||||
| protected: | protected: | ||||
| btQuantizedBvhTree m_box_tree; | btQuantizedBvhTree m_box_tree; | ||||
| btPrimitiveManagerBase * m_primitive_manager; | btPrimitiveManagerBase* m_primitive_manager; | ||||
| protected: | protected: | ||||
| //stackless refit | //stackless refit | ||||
| void refit(); | void refit(); | ||||
| public: | |||||
| public: | |||||
| //! this constructor doesn't build the tree. you must call buildSet | //! this constructor doesn't build the tree. you must call buildSet | ||||
| btGImpactQuantizedBvh() | btGImpactQuantizedBvh() | ||||
| { | { | ||||
| m_primitive_manager = NULL; | m_primitive_manager = NULL; | ||||
| } | } | ||||
| //! this constructor doesn't build the tree. you must call buildSet | //! this constructor doesn't build the tree. you must call buildSet | ||||
| btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager) | btGImpactQuantizedBvh(btPrimitiveManagerBase* primitive_manager) | ||||
| { | { | ||||
| m_primitive_manager = primitive_manager; | m_primitive_manager = primitive_manager; | ||||
| } | } | ||||
| SIMD_FORCE_INLINE btAABB getGlobalBox() const | SIMD_FORCE_INLINE btAABB getGlobalBox() const | ||||
| { | { | ||||
| btAABB totalbox; | btAABB totalbox; | ||||
| getNodeBound(0, totalbox); | getNodeBound(0, totalbox); | ||||
| return totalbox; | return totalbox; | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) | SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager) | ||||
| { | { | ||||
| m_primitive_manager = primitive_manager; | m_primitive_manager = primitive_manager; | ||||
| } | } | ||||
| SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const | SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const | ||||
| { | { | ||||
| return m_primitive_manager; | return m_primitive_manager; | ||||
| } | } | ||||
| //! node manager prototype functions | //! node manager prototype functions | ||||
| ///@{ | ///@{ | ||||
| //! this attemps to refit the box set. | //! this attemps to refit the box set. | ||||
| SIMD_FORCE_INLINE void update() | SIMD_FORCE_INLINE void update() | ||||
| { | { | ||||
| refit(); | refit(); | ||||
| } | } | ||||
| //! this rebuild the entire set | //! this rebuild the entire set | ||||
| void buildSet(); | void buildSet(); | ||||
| //! returns the indices of the primitives in the m_primitive_manager | //! returns the indices of the primitives in the m_primitive_manager | ||||
| bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const; | bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const; | ||||
| //! returns the indices of the primitives in the m_primitive_manager | //! returns the indices of the primitives in the m_primitive_manager | ||||
| SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, | SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box, | ||||
| const btTransform & transform, btAlignedObjectArray<int> & collided_results) const | const btTransform& transform, btAlignedObjectArray<int>& collided_results) const | ||||
| { | { | ||||
| btAABB transbox=box; | btAABB transbox = box; | ||||
| transbox.appy_transform(transform); | transbox.appy_transform(transform); | ||||
| return boxQuery(transbox,collided_results); | return boxQuery(transbox, collided_results); | ||||
| } | } | ||||
| //! returns the indices of the primitives in the m_primitive_manager | //! returns the indices of the primitives in the m_primitive_manager | ||||
| bool rayQuery( | bool rayQuery( | ||||
| const btVector3 & ray_dir,const btVector3 & ray_origin , | const btVector3& ray_dir, const btVector3& ray_origin, | ||||
| btAlignedObjectArray<int> & collided_results) const; | btAlignedObjectArray<int>& collided_results) const; | ||||
| //! tells if this set has hierarcht | //! tells if this set has hierarcht | ||||
| SIMD_FORCE_INLINE bool hasHierarchy() const | SIMD_FORCE_INLINE bool hasHierarchy() const | ||||
| { | { | ||||
| return true; | return true; | ||||
| } | } | ||||
| //! tells if this set is a trimesh | //! tells if this set is a trimesh | ||||
| SIMD_FORCE_INLINE bool isTrimesh() const | SIMD_FORCE_INLINE bool isTrimesh() const | ||||
| { | { | ||||
| return m_primitive_manager->is_trimesh(); | return m_primitive_manager->is_trimesh(); | ||||
| } | } | ||||
| //! node count | //! node count | ||||
| SIMD_FORCE_INLINE int getNodeCount() const | SIMD_FORCE_INLINE int getNodeCount() const | ||||
| { | { | ||||
| return m_box_tree.getNodeCount(); | return m_box_tree.getNodeCount(); | ||||
| } | } | ||||
| //! tells if the node is a leaf | //! tells if the node is a leaf | ||||
| SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const | SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const | ||||
| { | { | ||||
| return m_box_tree.isLeafNode(nodeindex); | return m_box_tree.isLeafNode(nodeindex); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getNodeData(int nodeindex) const | SIMD_FORCE_INLINE int getNodeData(int nodeindex) const | ||||
| { | { | ||||
| return m_box_tree.getNodeData(nodeindex); | return m_box_tree.getNodeData(nodeindex); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const | SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const | ||||
| { | { | ||||
| m_box_tree.getNodeBound(nodeindex, bound); | m_box_tree.getNodeBound(nodeindex, bound); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) | SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound) | ||||
| { | { | ||||
| m_box_tree.setNodeBound(nodeindex, bound); | m_box_tree.setNodeBound(nodeindex, bound); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const | SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const | ||||
| { | { | ||||
| return m_box_tree.getLeftNode(nodeindex); | return m_box_tree.getLeftNode(nodeindex); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getRightNode(int nodeindex) const | SIMD_FORCE_INLINE int getRightNode(int nodeindex) const | ||||
| { | { | ||||
| return m_box_tree.getRightNode(nodeindex); | return m_box_tree.getRightNode(nodeindex); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const | SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const | ||||
| { | { | ||||
| return m_box_tree.getEscapeNodeIndex(nodeindex); | return m_box_tree.getEscapeNodeIndex(nodeindex); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const | SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const | ||||
| { | { | ||||
| m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); | m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle); | ||||
| } | } | ||||
| SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const | SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const | ||||
| { | { | ||||
| return m_box_tree.get_node_pointer(index); | return m_box_tree.get_node_pointer(index); | ||||
| } | } | ||||
| #ifdef TRI_COLLISION_PROFILING | #ifdef TRI_COLLISION_PROFILING | ||||
| static float getAverageTreeCollisionTime(); | static float getAverageTreeCollisionTime(); | ||||
| #endif //TRI_COLLISION_PROFILING | #endif //TRI_COLLISION_PROFILING | ||||
| static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1, | static void find_collision(const btGImpactQuantizedBvh* boxset1, const btTransform& trans1, | ||||
| const btGImpactQuantizedBvh * boxset2, const btTransform & trans2, | const btGImpactQuantizedBvh* boxset2, const btTransform& trans2, | ||||
| btPairSet & collision_pairs); | btPairSet& collision_pairs); | ||||
| }; | }; | ||||
| #endif // GIM_BOXPRUNING_H_INCLUDED | #endif // GIM_BOXPRUNING_H_INCLUDED | ||||