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 "b3StridingMeshInterface.h"
17 
~b3StridingMeshInterface()18 b3StridingMeshInterface::~b3StridingMeshInterface()
19 {
20 }
21 
InternalProcessAllTriangles(b3InternalTriangleIndexCallback * callback,const b3Vector3 & aabbMin,const b3Vector3 & aabbMax) const22 void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
23 {
24 	(void)aabbMin;
25 	(void)aabbMax;
26 	int numtotalphysicsverts = 0;
27 	int part, graphicssubparts = getNumSubParts();
28 	const unsigned char* vertexbase;
29 	const unsigned char* indexbase;
30 	int indexstride;
31 	PHY_ScalarType type;
32 	PHY_ScalarType gfxindextype;
33 	int stride, numverts, numtriangles;
34 	int gfxindex;
35 	b3Vector3 triangle[3];
36 
37 	b3Vector3 meshScaling = getScaling();
38 
39 	///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
40 	for (part = 0; part < graphicssubparts; part++)
41 	{
42 		getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
43 		numtotalphysicsverts += numtriangles * 3;  //upper bound
44 
45 		///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
46 		///so disable this feature by default
47 		///see patch http://code.google.com/p/bullet/issues/detail?id=213
48 
49 		switch (type)
50 		{
51 			case PHY_FLOAT:
52 			{
53 				float* graphicsbase;
54 
55 				switch (gfxindextype)
56 				{
57 					case PHY_INTEGER:
58 					{
59 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
60 						{
61 							unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
62 							graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
63 							triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
64 							graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
65 							triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
66 							graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
67 							triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
68 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
69 						}
70 						break;
71 					}
72 					case PHY_SHORT:
73 					{
74 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
75 						{
76 							unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
77 							graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
78 							triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
79 							graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
80 							triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
81 							graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
82 							triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
83 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
84 						}
85 						break;
86 					}
87 					case PHY_UCHAR:
88 					{
89 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
90 						{
91 							unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
92 							graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
93 							triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
94 							graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
95 							triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
96 							graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
97 							triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
98 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
99 						}
100 						break;
101 					}
102 					default:
103 						b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
104 				}
105 				break;
106 			}
107 
108 			case PHY_DOUBLE:
109 			{
110 				double* graphicsbase;
111 
112 				switch (gfxindextype)
113 				{
114 					case PHY_INTEGER:
115 					{
116 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
117 						{
118 							unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
119 							graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
120 							triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
121 							graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
122 							triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
123 							graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
124 							triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
125 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
126 						}
127 						break;
128 					}
129 					case PHY_SHORT:
130 					{
131 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
132 						{
133 							unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
134 							graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
135 							triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
136 							graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
137 							triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
138 							graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
139 							triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
140 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
141 						}
142 						break;
143 					}
144 					case PHY_UCHAR:
145 					{
146 						for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
147 						{
148 							unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
149 							graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
150 							triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
151 							graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
152 							triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
153 							graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
154 							triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
155 							callback->internalProcessTriangleIndex(triangle, part, gfxindex);
156 						}
157 						break;
158 					}
159 					default:
160 						b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
161 				}
162 				break;
163 			}
164 			default:
165 				b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
166 		}
167 
168 		unLockReadOnlyVertexBase(part);
169 	}
170 }
171 
calculateAabbBruteForce(b3Vector3 & aabbMin,b3Vector3 & aabbMax)172 void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin, b3Vector3& aabbMax)
173 {
174 	struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
175 	{
176 		b3Vector3 m_aabbMin;
177 		b3Vector3 m_aabbMax;
178 
179 		AabbCalculationCallback()
180 		{
181 			m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
182 			m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
183 		}
184 
185 		virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
186 		{
187 			(void)partId;
188 			(void)triangleIndex;
189 
190 			m_aabbMin.setMin(triangle[0]);
191 			m_aabbMax.setMax(triangle[0]);
192 			m_aabbMin.setMin(triangle[1]);
193 			m_aabbMax.setMax(triangle[1]);
194 			m_aabbMin.setMin(triangle[2]);
195 			m_aabbMax.setMax(triangle[2]);
196 		}
197 	};
198 
199 	//first calculate the total aabb for all triangles
200 	AabbCalculationCallback aabbCallback;
201 	aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
202 	aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
203 	InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
204 
205 	aabbMin = aabbCallback.m_aabbMin;
206 	aabbMax = aabbCallback.m_aabbMax;
207 }
208