OPC_OptimizedTree.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /*
  3. * OPCODE - Optimized Collision Detection
  4. * Copyright (C) 2001 Pierre Terdiman
  5. * Homepage: http://www.codercorner.com/Opcode.htm
  6. */
  7. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. /**
  10. * Contains code for optimized trees.
  11. * \file OPC_OptimizedTree.h
  12. * \author Pierre Terdiman
  13. * \date March, 20, 2001
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // Include Guard
  18. #ifndef __OPC_OPTIMIZEDTREE_H__
  19. #define __OPC_OPTIMIZEDTREE_H__
  20. //! Common interface for a node of an implicit tree
  21. #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \
  22. public: \
  23. /* Constructor / Destructor */ \
  24. inline_ base_class() : mData(0) {} \
  25. inline_ ~base_class() {} \
  26. /* Leaf test */ \
  27. inline_ BOOL IsLeaf() const { return mData&1; } \
  28. /* Data access */ \
  29. inline_ const base_class* GetPos() const { return (base_class*)mData; } \
  30. inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \
  31. inline_ udword GetPrimitive() const { return (mData>>1); } \
  32. /* Stats */ \
  33. inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
  34. \
  35. volume mAABB; \
  36. size_t mData;
  37. //! Common interface for a node of a no-leaf tree
  38. #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \
  39. public: \
  40. /* Constructor / Destructor */ \
  41. inline_ base_class() : mPosData(0), mNegData(0) {} \
  42. inline_ ~base_class() {} \
  43. /* Leaf tests */ \
  44. inline_ BOOL HasPosLeaf() const { return mPosData&1; } \
  45. inline_ BOOL HasNegLeaf() const { return mNegData&1; } \
  46. /* Data access */ \
  47. inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \
  48. inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \
  49. inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \
  50. inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \
  51. /* Stats */ \
  52. inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
  53. \
  54. volume mAABB; \
  55. size_t mPosData; \
  56. size_t mNegData;
  57. class OPCODE_API AABBCollisionNode
  58. {
  59. IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB)
  60. inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; }
  61. inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); }
  62. inline_ udword GetRadius() const
  63. {
  64. udword* Bits = (udword*)&mAABB.mExtents.x;
  65. udword Max = Bits[0];
  66. if(Bits[1]>Max) Max = Bits[1];
  67. if(Bits[2]>Max) Max = Bits[2];
  68. return Max;
  69. }
  70. // NB: using the square-magnitude or the true volume of the box, seems to yield better results
  71. // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size"
  72. // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's
  73. // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is
  74. // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices
  75. // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very
  76. // good strategy.
  77. };
  78. class OPCODE_API AABBQuantizedNode
  79. {
  80. IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB)
  81. inline_ uword GetSize() const
  82. {
  83. const uword* Bits = mAABB.mExtents;
  84. uword Max = Bits[0];
  85. if(Bits[1]>Max) Max = Bits[1];
  86. if(Bits[2]>Max) Max = Bits[2];
  87. return Max;
  88. }
  89. // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all
  90. // over the place.......!
  91. };
  92. class OPCODE_API AABBNoLeafNode
  93. {
  94. IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB)
  95. };
  96. class OPCODE_API AABBQuantizedNoLeafNode
  97. {
  98. IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB)
  99. };
  100. //! Common interface for a collision tree
  101. #define IMPLEMENT_COLLISION_TREE(base_class, node) \
  102. public: \
  103. /* Constructor / Destructor */ \
  104. base_class(); \
  105. virtual ~base_class(); \
  106. /* Builds from a standard tree */ \
  107. override(AABBOptimizedTree) bool Build(AABBTree* tree); \
  108. /* Refits the tree */ \
  109. override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \
  110. /* Walks the tree */ \
  111. override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \
  112. /* Data access */ \
  113. inline_ const node* GetNodes() const { return mNodes; } \
  114. /* Stats */ \
  115. override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \
  116. private: \
  117. node* mNodes;
  118. typedef bool (*GenericWalkingCallback) (const void* current, void* user_data);
  119. class OPCODE_API AABBOptimizedTree
  120. {
  121. public:
  122. // Constructor / Destructor
  123. AABBOptimizedTree() :
  124. mNbNodes (0)
  125. {}
  126. virtual ~AABBOptimizedTree() {}
  127. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. /**
  129. * Builds the collision tree from a generic AABB tree.
  130. * \param tree [in] generic AABB tree
  131. * \return true if success
  132. */
  133. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. virtual bool Build(AABBTree* tree) = 0;
  135. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. /**
  137. * Refits the collision tree after vertices have been modified.
  138. * \param mesh_interface [in] mesh interface for current model
  139. * \return true if success
  140. */
  141. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. virtual bool Refit(const MeshInterface* mesh_interface) = 0;
  143. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  144. /**
  145. * Walks the tree and call the user back for each node.
  146. * \param callback [in] walking callback
  147. * \param user_data [in] callback's user data
  148. * \return true if success
  149. */
  150. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0;
  152. // Data access
  153. virtual udword GetUsedBytes() const = 0;
  154. inline_ udword GetNbNodes() const { return mNbNodes; }
  155. protected:
  156. udword mNbNodes;
  157. };
  158. class OPCODE_API AABBCollisionTree : public AABBOptimizedTree
  159. {
  160. IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode)
  161. };
  162. class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree
  163. {
  164. IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode)
  165. };
  166. class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree
  167. {
  168. IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode)
  169. public:
  170. Point mCenterCoeff;
  171. Point mExtentsCoeff;
  172. };
  173. class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree
  174. {
  175. IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode)
  176. public:
  177. Point mCenterCoeff;
  178. Point mExtentsCoeff;
  179. };
  180. #endif // __OPC_OPTIMIZEDTREE_H__