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