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