1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 #include "btStridingMeshInterface.h"
17 #include "LinearMath/btSerializer.h"
18
~btStridingMeshInterface()19 btStridingMeshInterface::~btStridingMeshInterface()
20 {
21
22 }
23
24
InternalProcessAllTriangles(btInternalTriangleIndexCallback * callback,const btVector3 & aabbMin,const btVector3 & aabbMax) const25 void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
26 {
27 (void)aabbMin;
28 (void)aabbMax;
29 int numtotalphysicsverts = 0;
30 int part,graphicssubparts = getNumSubParts();
31 const unsigned char * vertexbase;
32 const unsigned char * indexbase;
33 int indexstride;
34 PHY_ScalarType type;
35 PHY_ScalarType gfxindextype;
36 int stride,numverts,numtriangles;
37 int gfxindex;
38 btVector3 triangle[3];
39
40 btVector3 meshScaling = getScaling();
41
42 ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
43 for (part=0;part<graphicssubparts ;part++)
44 {
45 getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
46 numtotalphysicsverts+=numtriangles*3; //upper bound
47
48 ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
49 ///so disable this feature by default
50 ///see patch http://code.google.com/p/bullet/issues/detail?id=213
51
52 switch (type)
53 {
54 case PHY_FLOAT:
55 {
56
57 float* graphicsbase;
58
59 switch (gfxindextype)
60 {
61 case PHY_INTEGER:
62 {
63 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
64 {
65 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
66 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
67 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
68 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
69 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
70 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
71 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
72 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
73 }
74 break;
75 }
76 case PHY_SHORT:
77 {
78 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
79 {
80 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
81 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
82 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
83 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
84 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
85 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
86 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
87 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
88 }
89 break;
90 }
91 case PHY_UCHAR:
92 {
93 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
94 {
95 unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
96 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
97 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
98 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
99 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
100 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
101 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
102 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
103 }
104 break;
105 }
106 default:
107 btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
108 }
109 break;
110 }
111
112 case PHY_DOUBLE:
113 {
114 double* graphicsbase;
115
116 switch (gfxindextype)
117 {
118 case PHY_INTEGER:
119 {
120 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
121 {
122 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
123 graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
124 triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
125 graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
126 triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
127 graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
128 triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
129 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
130 }
131 break;
132 }
133 case PHY_SHORT:
134 {
135 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
136 {
137 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
138 graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
139 triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
140 graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
141 triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
142 graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
143 triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
144 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
145 }
146 break;
147 }
148 case PHY_UCHAR:
149 {
150 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
151 {
152 unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
153 graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
154 triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
155 graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
156 triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
157 graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
158 triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(), (btScalar)graphicsbase[2]*meshScaling.getZ());
159 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
160 }
161 break;
162 }
163 default:
164 btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
165 }
166 break;
167 }
168 default:
169 btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
170 }
171
172 unLockReadOnlyVertexBase(part);
173 }
174 }
175
calculateAabbBruteForce(btVector3 & aabbMin,btVector3 & aabbMax)176 void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
177 {
178
179 struct AabbCalculationCallback : public btInternalTriangleIndexCallback
180 {
181 btVector3 m_aabbMin;
182 btVector3 m_aabbMax;
183
184 AabbCalculationCallback()
185 {
186 m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
187 m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
188 }
189
190 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
191 {
192 (void)partId;
193 (void)triangleIndex;
194
195 m_aabbMin.setMin(triangle[0]);
196 m_aabbMax.setMax(triangle[0]);
197 m_aabbMin.setMin(triangle[1]);
198 m_aabbMax.setMax(triangle[1]);
199 m_aabbMin.setMin(triangle[2]);
200 m_aabbMax.setMax(triangle[2]);
201 }
202 };
203
204 //first calculate the total aabb for all triangles
205 AabbCalculationCallback aabbCallback;
206 aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
207 aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
208 InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
209
210 aabbMin = aabbCallback.m_aabbMin;
211 aabbMax = aabbCallback.m_aabbMax;
212 }
213
214
215
216 ///fills the dataBuffer and returns the struct name (and 0 on failure)
serialize(void * dataBuffer,btSerializer * serializer) const217 const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
218 {
219 btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer;
220
221 trimeshData->m_numMeshParts = getNumSubParts();
222
223 //void* uniquePtr = 0;
224
225 trimeshData->m_meshPartsPtr = 0;
226
227 if (trimeshData->m_numMeshParts)
228 {
229 btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts);
230 btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
231 trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr);
232
233
234 // int numtotalphysicsverts = 0;
235 int part,graphicssubparts = getNumSubParts();
236 const unsigned char * vertexbase;
237 const unsigned char * indexbase;
238 int indexstride;
239 PHY_ScalarType type;
240 PHY_ScalarType gfxindextype;
241 int stride,numverts,numtriangles;
242 int gfxindex;
243 // btVector3 triangle[3];
244
245 btVector3 meshScaling = getScaling();
246
247 ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
248 for (part=0;part<graphicssubparts ;part++,memPtr++)
249 {
250 getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
251 memPtr->m_numTriangles = numtriangles;//indices = 3*numtriangles
252 memPtr->m_numVertices = numverts;
253 memPtr->m_indices16 = 0;
254 memPtr->m_indices32 = 0;
255 memPtr->m_3indices16 = 0;
256 memPtr->m_vertices3f = 0;
257 memPtr->m_vertices3d = 0;
258
259 switch (gfxindextype)
260 {
261 case PHY_INTEGER:
262 {
263 int numindices = numtriangles*3;
264
265 if (numindices)
266 {
267 btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices);
268 btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
269 memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
270 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
271 {
272 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
273 tmpIndices[gfxindex*3].m_value = tri_indices[0];
274 tmpIndices[gfxindex*3+1].m_value = tri_indices[1];
275 tmpIndices[gfxindex*3+2].m_value = tri_indices[2];
276 }
277 serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
278 }
279 break;
280 }
281 case PHY_SHORT:
282 {
283 if (numtriangles)
284 {
285 btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles);
286 btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
287 memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices);
288 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
289 {
290 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
291 tmpIndices[gfxindex].m_values[0] = tri_indices[0];
292 tmpIndices[gfxindex].m_values[1] = tri_indices[1];
293 tmpIndices[gfxindex].m_values[2] = tri_indices[2];
294 }
295 serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
296 }
297 break;
298 }
299 case PHY_UCHAR:
300 {
301 if (numtriangles)
302 {
303 btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles);
304 btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
305 memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices);
306 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
307 {
308 unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
309 tmpIndices[gfxindex].m_values[0] = tri_indices[0];
310 tmpIndices[gfxindex].m_values[1] = tri_indices[1];
311 tmpIndices[gfxindex].m_values[2] = tri_indices[2];
312 }
313 serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
314 }
315 break;
316 }
317 default:
318 {
319 btAssert(0);
320 //unknown index type
321 }
322 }
323
324 switch (type)
325 {
326 case PHY_FLOAT:
327 {
328 float* graphicsbase;
329
330 if (numverts)
331 {
332 btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts);
333 btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr;
334 memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices);
335 for (int i=0;i<numverts;i++)
336 {
337 graphicsbase = (float*)(vertexbase+i*stride);
338 tmpVertices[i].m_floats[0] = graphicsbase[0];
339 tmpVertices[i].m_floats[1] = graphicsbase[1];
340 tmpVertices[i].m_floats[2] = graphicsbase[2];
341 }
342 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
343 }
344 break;
345 }
346
347 case PHY_DOUBLE:
348 {
349 if (numverts)
350 {
351 btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts);
352 btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr;
353 memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices);
354 for (int i=0;i<numverts;i++)
355 {
356 double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double
357 tmpVertices[i].m_floats[0] = graphicsbase[0];
358 tmpVertices[i].m_floats[1] = graphicsbase[1];
359 tmpVertices[i].m_floats[2] = graphicsbase[2];
360 }
361 serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
362 }
363 break;
364 }
365
366 default:
367 btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
368 }
369
370 unLockReadOnlyVertexBase(part);
371 }
372
373 serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
374 }
375
376
377 m_scaling.serializeFloat(trimeshData->m_scaling);
378 return "btStridingMeshInterfaceData";
379 }
380