OPC_MeshInterface.cpp 17 KB

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