Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.cpp @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

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