diff options
author | dan miller | 2007-10-19 05:15:33 +0000 |
---|---|---|
committer | dan miller | 2007-10-19 05:15:33 +0000 |
commit | 79eca25c945a535a7a0325999034bae17da92412 (patch) | |
tree | 40ff433d94859d629aac933d5ec73b382f62ba1a /libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp | |
parent | adding ode source to /libraries (diff) | |
download | opensim-SC_OLD-79eca25c945a535a7a0325999034bae17da92412.zip opensim-SC_OLD-79eca25c945a535a7a0325999034bae17da92412.tar.gz opensim-SC_OLD-79eca25c945a535a7a0325999034bae17da92412.tar.bz2 opensim-SC_OLD-79eca25c945a535a7a0325999034bae17da92412.tar.xz |
resubmitting ode
Diffstat (limited to 'libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp')
-rw-r--r-- | libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp new file mode 100644 index 0000000..b962764 --- /dev/null +++ b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp | |||
@@ -0,0 +1,303 @@ | |||
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 | |||
121 | using namespace Opcode; | ||
122 | |||
123 | Point MeshInterface::VertexCache[3]; | ||
124 | |||
125 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
126 | /** | ||
127 | * Constructor. | ||
128 | */ | ||
129 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
130 | MeshInterface::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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
154 | MeshInterface::~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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
164 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
182 | udword 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
215 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
232 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
249 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
269 | bool 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 | } | ||