OPC_MeshInterface.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 a mesh interface.
  11. * \file OPC_MeshInterface.cpp
  12. * \author Pierre Terdiman
  13. * \date November, 27, 2002
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. /**
  18. * This structure holds 3 vertex-pointers. It's mainly used by collision callbacks so that the app doesn't have
  19. * to return 3 vertices to OPCODE (36 bytes) but only 3 pointers (12 bytes). It seems better but I never profiled
  20. * the alternative.
  21. *
  22. * \class VertexPointers
  23. * \author Pierre Terdiman
  24. * \version 1.3
  25. * \date March, 20, 2001
  26. */
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. /**
  30. * This class is an interface between us and user-defined meshes. Meshes can be defined in a lot of ways, and here we
  31. * try to support most of them.
  32. *
  33. * Basically you have two options:
  34. * - callbacks, if OPC_USE_CALLBACKS is defined in OPC_Settings.h.
  35. * - else pointers.
  36. *
  37. * If using pointers, you can also use strides or not. Strides are used when OPC_USE_STRIDE is defined.
  38. *
  39. *
  40. * CALLBACKS:
  41. *
  42. * Using callbacks is the most generic way to feed OPCODE with your meshes. Indeed, you just have to give
  43. * access to three vertices at the end of the day. It's up to you to fetch them from your database, using
  44. * whatever method you want. Hence your meshes can lie in system memory or AGP, be indexed or not, use 16
  45. * or 32-bits indices, you can decompress them on-the-fly if needed, etc. On the other hand, a callback is
  46. * called each time OPCODE needs access to a particular triangle, so there might be a slight overhead.
  47. *
  48. * To make things clear: geometry & topology are NOT stored in the collision system,
  49. * in order to save some ram. So, when the system needs them to perform accurate intersection
  50. * tests, you're requested to provide the triangle-vertices corresponding to a given face index.
  51. *
  52. * Ex:
  53. *
  54. * \code
  55. * static void ColCallback(udword triangle_index, VertexPointers& triangle, udword user_data)
  56. * {
  57. * // Get back Mesh0 or Mesh1 (you also can use 2 different callbacks)
  58. * Mesh* MyMesh = (Mesh*)user_data;
  59. * // Get correct triangle in the app-controlled database
  60. * const Triangle* Tri = MyMesh->GetTriangle(triangle_index);
  61. * // Setup pointers to vertices for the collision system
  62. * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]);
  63. * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]);
  64. * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]);
  65. * }
  66. *
  67. * // Setup callbacks
  68. * MeshInterface0->SetCallback(ColCallback, udword(Mesh0));
  69. * MeshInterface1->SetCallback(ColCallback, udword(Mesh1));
  70. * \endcode
  71. *
  72. * Of course, you should make this callback as fast as possible. And you're also not supposed
  73. * to modify the geometry *after* the collision trees have been built. The alternative was to
  74. * store the geometry & topology in the collision system as well (as in RAPID) but we have found
  75. * this approach to waste a lot of ram in many cases.
  76. *
  77. *
  78. * POINTERS:
  79. *
  80. * If you're internally using the following canonical structures:
  81. * - a vertex made of three 32-bits floating point values
  82. * - a triangle made of three 32-bits integer vertex references
  83. * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly
  84. * use provided pointers to access the topology and geometry, without using a callback. It might be faster,
  85. * but probably not as safe. Pointers have been introduced in OPCODE 1.2.
  86. *
  87. * Ex:
  88. *
  89. * \code
  90. * // Setup pointers
  91. * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts());
  92. * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts());
  93. * \endcode
  94. *
  95. *
  96. * STRIDES:
  97. *
  98. * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates
  99. * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE
  100. * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase
  101. * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers !
  102. *
  103. *
  104. * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so
  105. * choose what's best for your application. All of this has been wrapped into this MeshInterface.
  106. *
  107. * \class MeshInterface
  108. * \author Pierre Terdiman
  109. * \version 1.3
  110. * \date November, 27, 2002
  111. */
  112. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  113. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  114. #include "Opcode.h"
  115. using namespace Opcode;
  116. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. /**
  118. * Constructor.
  119. */
  120. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  121. MeshInterface::MeshInterface() :
  122. #ifdef OPC_USE_CALLBACKS
  123. mUserData (null),
  124. mObjCallback (null),
  125. #else
  126. mTris (null),
  127. mVerts (null),
  128. #ifdef OPC_USE_STRIDE
  129. mTriStride (sizeof(IndexedTriangle)),
  130. mVertexStride (sizeof(Point)),
  131. #endif
  132. #endif
  133. mNbTris (0),
  134. mNbVerts (0)
  135. {
  136. }
  137. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  138. /**
  139. * Destructor.
  140. */
  141. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. MeshInterface::~MeshInterface()
  143. {
  144. }
  145. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. /**
  147. * Checks the mesh interface is valid, i.e. things have been setup correctly.
  148. * \return true if valid
  149. */
  150. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. bool MeshInterface::IsValid() const
  152. {
  153. if(!mNbTris || !mNbVerts) return false;
  154. #ifdef OPC_USE_CALLBACKS
  155. if(!mObjCallback) return false;
  156. #else
  157. if(!mTris || !mVerts) return false;
  158. #endif
  159. return true;
  160. }
  161. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. /**
  163. * Checks the mesh itself is valid.
  164. * Currently we only look for degenerate faces.
  165. * \return number of degenerate faces
  166. */
  167. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  168. udword MeshInterface::CheckTopology() const
  169. {
  170. // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases.
  171. // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner
  172. // you can try this: www.codercorner.com/Consolidation.zip
  173. udword NbDegenerate = 0;
  174. VertexPointers VP;
  175. // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for
  176. // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides).
  177. for(udword i=0;i<mNbTris;i++)
  178. {
  179. GetTriangle(VP, i);
  180. if( (VP.Vertex[0]==VP.Vertex[1])
  181. || (VP.Vertex[1]==VP.Vertex[2])
  182. || (VP.Vertex[2]==VP.Vertex[0])) NbDegenerate++;
  183. }
  184. return NbDegenerate;
  185. }
  186. #ifdef OPC_USE_CALLBACKS
  187. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. /**
  189. * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
  190. * \param callback [in] user-defined callback
  191. * \param user_data [in] user-defined data
  192. * \return true if success
  193. */
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. bool MeshInterface::SetCallback(RequestCallback callback, void* user_data)
  196. {
  197. if(!callback) return SetIceError("MeshInterface::SetCallback: callback pointer is null");
  198. mObjCallback = callback;
  199. mUserData = user_data;
  200. return true;
  201. }
  202. #else
  203. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. /**
  205. * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
  206. * \param tris [in] pointer to triangles
  207. * \param verts [in] pointer to vertices
  208. * \return true if success
  209. */
  210. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. bool MeshInterface::SetPointers(const IndexedTriangle* tris, const Point* verts)
  212. {
  213. if(!tris || !verts) return SetIceError("MeshInterface::SetPointers: pointer is null", null);
  214. mTris = tris;
  215. mVerts = verts;
  216. return true;
  217. }
  218. #ifdef OPC_USE_STRIDE
  219. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. /**
  221. * Strides control
  222. * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
  223. * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
  224. * \return true if success
  225. */
  226. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. bool MeshInterface::SetStrides(udword tri_stride, udword vertex_stride)
  228. {
  229. if(tri_stride<sizeof(IndexedTriangle)) return SetIceError("MeshInterface::SetStrides: invalid triangle stride", null);
  230. if(vertex_stride<sizeof(Point)) return SetIceError("MeshInterface::SetStrides: invalid vertex stride", null);
  231. mTriStride = tri_stride;
  232. mVertexStride = vertex_stride;
  233. return true;
  234. }
  235. #endif
  236. #endif
  237. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  238. /**
  239. * Remaps client's mesh according to a permutation.
  240. * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles)
  241. * \param permutation [in] list of triangle indices
  242. * \return true if success
  243. */
  244. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. bool MeshInterface::RemapClient(udword nb_indices, const udword* permutation) const
  246. {
  247. // Checkings
  248. if(!nb_indices || !permutation) return false;
  249. if(nb_indices!=mNbTris) return false;
  250. #ifdef OPC_USE_CALLBACKS
  251. // We can't really do that using callbacks
  252. return false;
  253. #else
  254. IndexedTriangle* Tmp = new IndexedTriangle[mNbTris];
  255. CHECKALLOC(Tmp);
  256. #ifdef OPC_USE_STRIDE
  257. udword Stride = mTriStride;
  258. #else
  259. udword Stride = sizeof(IndexedTriangle);
  260. #endif
  261. for(udword i=0;i<mNbTris;i++)
  262. {
  263. const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
  264. Tmp[i] = *T;
  265. }
  266. for(udword i=0;i<mNbTris;i++)
  267. {
  268. IndexedTriangle* T = (IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
  269. *T = Tmp[permutation[i]];
  270. }
  271. DELETEARRAY(Tmp);
  272. #endif
  273. return true;
  274. }