OPC_MeshInterface.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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. // Precompiled Header
  115. #include "Stdafx.h"
  116. using namespace Opcode;
  117. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. /**
  119. * Constructor.
  120. */
  121. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. MeshInterface::MeshInterface() :
  123. mNbTris (0),
  124. mNbVerts (0),
  125. #ifdef OPC_USE_CALLBACKS
  126. mUserData (null),
  127. mObjCallback (null)
  128. #else
  129. #ifdef OPC_USE_STRIDE
  130. mTriStride (sizeof(IndexedTriangle)),
  131. mVertexStride (sizeof(Point)),
  132. mFetchTriangle (&MeshInterface::FetchTriangleFromSingles),
  133. #endif
  134. mTris (null),
  135. mVerts (null)
  136. #endif
  137. {
  138. }
  139. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. /**
  141. * Destructor.
  142. */
  143. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  144. MeshInterface::~MeshInterface()
  145. {
  146. }
  147. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. /**
  149. * Checks the mesh interface is valid, i.e. things have been setup correctly.
  150. * \return true if valid
  151. */
  152. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. bool MeshInterface::IsValid() const
  154. {
  155. if(!mNbTris || !mNbVerts) return false;
  156. #ifdef OPC_USE_CALLBACKS
  157. if(!mObjCallback) return false;
  158. #else
  159. if(!mTris || !mVerts) return false;
  160. #endif
  161. return true;
  162. }
  163. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. /**
  165. * Checks the mesh itself is valid.
  166. * Currently we only look for degenerate faces.
  167. * \return number of degenerate faces
  168. */
  169. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. udword MeshInterface::CheckTopology() const
  171. {
  172. // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases.
  173. // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner
  174. // you can try this: www.codercorner.com/Consolidation.zip
  175. udword NbDegenerate = 0;
  176. VertexPointers VP;
  177. ConversionArea VC;
  178. // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for
  179. // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides).
  180. for(udword i=0;i<mNbTris;i++)
  181. {
  182. GetTriangle(VP, i, VC);
  183. if( (VP.Vertex[0]==VP.Vertex[1])
  184. || (VP.Vertex[1]==VP.Vertex[2])
  185. || (VP.Vertex[2]==VP.Vertex[0])) NbDegenerate++;
  186. }
  187. return NbDegenerate;
  188. }
  189. #ifdef OPC_USE_CALLBACKS
  190. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  191. /**
  192. * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
  193. * \param callback [in] user-defined callback
  194. * \param user_data [in] user-defined data
  195. * \return true if success
  196. */
  197. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  198. bool MeshInterface::SetCallback(RequestCallback callback, void* user_data)
  199. {
  200. if(!callback) return SetIceError("MeshInterface::SetCallback: callback pointer is null");
  201. mObjCallback = callback;
  202. mUserData = user_data;
  203. return true;
  204. }
  205. #else
  206. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207. /**
  208. * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
  209. * \param tris [in] pointer to triangles
  210. * \param verts [in] pointer to vertices
  211. * \return true if success
  212. */
  213. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. bool MeshInterface::SetPointers(const IndexedTriangle* tris, const Point* verts)
  215. {
  216. if(!tris || !verts) return SetIceError("MeshInterface::SetPointers: pointer is null", null);
  217. mTris = tris;
  218. mVerts = verts;
  219. return true;
  220. }
  221. #ifdef OPC_USE_STRIDE
  222. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  223. /**
  224. * Strides control
  225. * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
  226. * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
  227. * \return true if success
  228. */
  229. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  230. bool MeshInterface::SetStrides(udword tri_stride, udword vertex_stride)
  231. {
  232. if(tri_stride<sizeof(IndexedTriangle)) return SetIceError("MeshInterface::SetStrides: invalid triangle stride", null);
  233. if(vertex_stride<sizeof(Point)) return SetIceError("MeshInterface::SetStrides: invalid vertex stride", null);
  234. mTriStride = tri_stride;
  235. mVertexStride = vertex_stride;
  236. return true;
  237. }
  238. #endif
  239. #endif
  240. #ifndef OPC_USE_CALLBACKS
  241. #ifdef OPC_USE_STRIDE
  242. void MeshInterface::FetchTriangleFromSingles(VertexPointers& vp, udword index, ConversionArea vc) const
  243. {
  244. const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride);
  245. vp.Vertex[0] = (const Point*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride);
  246. vp.Vertex[1] = (const Point*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride);
  247. vp.Vertex[2] = (const Point*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride);
  248. }
  249. void MeshInterface::FetchTriangleFromDoubles(VertexPointers& vp, udword index, ConversionArea vc) const
  250. {
  251. const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride);
  252. for (int i = 0; i < 3; i++){
  253. const double* v = (const double*)(((ubyte*)mVerts) + T->mVRef[i] * mVertexStride);
  254. vc[i].x = (float)v[0];
  255. vc[i].y = (float)v[1];
  256. vc[i].z = (float)v[2];
  257. vp.Vertex[i] = &vc[i];
  258. }
  259. }
  260. #endif
  261. #endif
  262. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  263. /**
  264. * Remaps client's mesh according to a permutation.
  265. * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles)
  266. * \param permutation [in] list of triangle indices
  267. * \return true if success
  268. */
  269. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  270. bool MeshInterface::RemapClient(udword nb_indices, const dTriIndex* permutation) const
  271. {
  272. // Checkings
  273. if(!nb_indices || !permutation) return false;
  274. if(nb_indices!=mNbTris) return false;
  275. #ifdef OPC_USE_CALLBACKS
  276. // We can't really do that using callbacks
  277. return false;
  278. #else
  279. IndexedTriangle* Tmp = new IndexedTriangle[mNbTris];
  280. CHECKALLOC(Tmp);
  281. #ifdef OPC_USE_STRIDE
  282. udword Stride = mTriStride;
  283. #else
  284. udword Stride = sizeof(IndexedTriangle);
  285. #endif
  286. for(udword i=0;i<mNbTris;i++)
  287. {
  288. const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
  289. Tmp[i] = *T;
  290. }
  291. for(udword i=0;i<mNbTris;i++)
  292. {
  293. IndexedTriangle* T = (IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
  294. *T = Tmp[permutation[i]];
  295. }
  296. DELETEARRAY(Tmp);
  297. #endif
  298. return true;
  299. }