OPC_Model.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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 OPCODE models.
  11. * \file OPC_Model.cpp
  12. * \author Pierre Terdiman
  13. * \date March, 20, 2001
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. /**
  18. * The main collision wrapper, for all trees. Supported trees are:
  19. * - Normal trees (2*N-1 nodes, full size)
  20. * - No-leaf trees (N-1 nodes, full size)
  21. * - Quantized trees (2*N-1 nodes, half size)
  22. * - Quantized no-leaf trees (N-1 nodes, half size)
  23. *
  24. * Usage:
  25. *
  26. * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp).
  27. * Keep it around in your app, since a pointer to this interface is saved internally and
  28. * used until you release the collision structures.
  29. *
  30. * 2) Build a Model using a creation structure:
  31. *
  32. * \code
  33. * Model Sample;
  34. *
  35. * OPCODECREATE OPCC;
  36. * OPCC.IMesh = ...;
  37. * OPCC.Rules = ...;
  38. * OPCC.NoLeaf = ...;
  39. * OPCC.Quantized = ...;
  40. * OPCC.KeepOriginal = ...;
  41. * bool Status = Sample.Build(OPCC);
  42. * \endcode
  43. *
  44. * 3) Create a tree collider and set it up:
  45. *
  46. * \code
  47. * AABBTreeCollider TC;
  48. * TC.SetFirstContact(...);
  49. * TC.SetFullBoxBoxTest(...);
  50. * TC.SetFullPrimBoxTest(...);
  51. * TC.SetTemporalCoherence(...);
  52. * \endcode
  53. *
  54. * 4) Perform a collision query
  55. *
  56. * \code
  57. * // Setup cache
  58. * static BVTCache ColCache;
  59. * ColCache.Model0 = &Model0;
  60. * ColCache.Model1 = &Model1;
  61. *
  62. * // Collision query
  63. * bool IsOk = TC.Collide(ColCache, World0, World1);
  64. *
  65. * // Get collision status => if true, objects overlap
  66. * BOOL Status = TC.GetContactStatus();
  67. *
  68. * // Number of colliding pairs and list of pairs
  69. * udword NbPairs = TC.GetNbPairs();
  70. * const Pair* p = TC.GetPairs()
  71. * \endcode
  72. *
  73. * 5) Stats
  74. *
  75. * \code
  76. * Model0.GetUsedBytes() = number of bytes used for this collision tree
  77. * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query
  78. * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query
  79. * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query
  80. * \endcode
  81. *
  82. * \class Model
  83. * \author Pierre Terdiman
  84. * \version 1.3
  85. * \date March, 20, 2001
  86. */
  87. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. #include "Opcode.h"
  90. using namespace Opcode;
  91. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  92. /**
  93. * Constructor.
  94. */
  95. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. Model::Model()
  97. {
  98. #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
  99. mHull = null;
  100. #endif // __MESHMERIZER_H__
  101. }
  102. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. /**
  104. * Destructor.
  105. */
  106. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. Model::~Model()
  108. {
  109. Release();
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  112. /**
  113. * Releases the model.
  114. */
  115. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. void Model::Release()
  117. {
  118. ReleaseBase();
  119. #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
  120. DELETESINGLE(mHull);
  121. #endif // __MESHMERIZER_H__
  122. }
  123. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  124. /**
  125. * Builds a collision model.
  126. * \param create [in] model creation structure
  127. * \return true if success
  128. */
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. bool Model::Build(const OPCODECREATE& create)
  131. {
  132. // 1) Checkings
  133. if(!create.mIMesh || !create.mIMesh->IsValid()) return false;
  134. // For this model, we only support complete trees
  135. if(create.mSettings.mLimit!=1) return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null);
  136. // Look for degenerate faces.
  137. udword NbDegenerate = create.mIMesh->CheckTopology();
  138. if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
  139. // We continue nonetheless....
  140. Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam]
  141. // 1-1) Setup mesh interface automatically [Opcode 1.3]
  142. SetMeshInterface(create.mIMesh);
  143. // Special case for 1-triangle meshes [Opcode 1.3]
  144. udword NbTris = create.mIMesh->GetNbTriangles();
  145. if(NbTris==1)
  146. {
  147. // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway.
  148. // It's a waste to use a "model" for this but at least it will work.
  149. mModelCode |= OPC_SINGLE_NODE;
  150. return true;
  151. }
  152. // 2) Build a generic AABB Tree.
  153. mSource = new AABBTree;
  154. CHECKALLOC(mSource);
  155. // 2-1) Setup a builder. Our primitives here are triangles from input mesh,
  156. // so we use an AABBTreeOfTrianglesBuilder.....
  157. {
  158. AABBTreeOfTrianglesBuilder TB;
  159. TB.mIMesh = create.mIMesh;
  160. TB.mSettings = create.mSettings;
  161. TB.mNbPrimitives = NbTris;
  162. if(!mSource->Build(&TB)) return false;
  163. }
  164. // 3) Create an optimized tree according to user-settings
  165. if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false;
  166. // 3-2) Create optimized tree
  167. if(!mTree->Build(mSource)) return false;
  168. // 3-3) Delete generic tree if needed
  169. if(!create.mKeepOriginal) DELETESINGLE(mSource);
  170. #ifdef __MESHMERIZER_H__
  171. // 4) Convex hull
  172. if(create.mCollisionHull)
  173. {
  174. // Create hull
  175. mHull = new CollisionHull;
  176. CHECKALLOC(mHull);
  177. CONVEXHULLCREATE CHC;
  178. // ### doesn't work with strides
  179. CHC.NbVerts = create.mIMesh->GetNbVertices();
  180. CHC.Vertices = create.mIMesh->GetVerts();
  181. CHC.UnifyNormals = true;
  182. CHC.ReduceVertices = true;
  183. CHC.WordFaces = false;
  184. mHull->Compute(CHC);
  185. }
  186. #endif // __MESHMERIZER_H__
  187. return true;
  188. }
  189. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. /**
  191. * Gets the number of bytes used by the tree.
  192. * \return amount of bytes used
  193. */
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. udword Model::GetUsedBytes() const
  196. {
  197. if(!mTree) return 0;
  198. return mTree->GetUsedBytes();
  199. }