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 19 btStridingMeshInterface::~btStridingMeshInterface() 20 { 21 22 } 23 24 25 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 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) 217 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_3indices8 = 0; 257 memPtr->m_vertices3f = 0; 258 memPtr->m_vertices3d = 0; 259 260 261 switch (gfxindextype) 262 { 263 case PHY_INTEGER: 264 { 265 int numindices = numtriangles*3; 266 267 if (numindices) 268 { 269 btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices); 270 btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr; 271 memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices); 272 for (gfxindex=0;gfxindex<numtriangles;gfxindex++) 273 { 274 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride); 275 tmpIndices[gfxindex*3].m_value = tri_indices[0]; 276 tmpIndices[gfxindex*3+1].m_value = tri_indices[1]; 277 tmpIndices[gfxindex*3+2].m_value = tri_indices[2]; 278 } 279 serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); 280 } 281 break; 282 } 283 case PHY_SHORT: 284 { 285 if (numtriangles) 286 { 287 btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles); 288 btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr; 289 memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices); 290 for (gfxindex=0;gfxindex<numtriangles;gfxindex++) 291 { 292 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride); 293 tmpIndices[gfxindex].m_values[0] = tri_indices[0]; 294 tmpIndices[gfxindex].m_values[1] = tri_indices[1]; 295 tmpIndices[gfxindex].m_values[2] = tri_indices[2]; 296 } 297 serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); 298 } 299 break; 300 } 301 case PHY_UCHAR: 302 { 303 if (numtriangles) 304 { 305 btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles); 306 btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr; 307 memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices); 308 for (gfxindex=0;gfxindex<numtriangles;gfxindex++) 309 { 310 unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride); 311 tmpIndices[gfxindex].m_values[0] = tri_indices[0]; 312 tmpIndices[gfxindex].m_values[1] = tri_indices[1]; 313 tmpIndices[gfxindex].m_values[2] = tri_indices[2]; 314 } 315 serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); 316 } 317 break; 318 } 319 default: 320 { 321 btAssert(0); 322 //unknown index type 323 } 324 } 325 326 switch (type) 327 { 328 case PHY_FLOAT: 329 { 330 float* graphicsbase; 331 332 if (numverts) 333 { 334 btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts); 335 btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr; 336 memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices); 337 for (int i=0;i<numverts;i++) 338 { 339 graphicsbase = (float*)(vertexbase+i*stride); 340 tmpVertices[i].m_floats[0] = graphicsbase[0]; 341 tmpVertices[i].m_floats[1] = graphicsbase[1]; 342 tmpVertices[i].m_floats[2] = graphicsbase[2]; 343 } 344 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); 345 } 346 break; 347 } 348 349 case PHY_DOUBLE: 350 { 351 if (numverts) 352 { 353 btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts); 354 btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr; 355 memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices); 356 for (int i=0;i<numverts;i++) 357 { 358 double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double 359 tmpVertices[i].m_floats[0] = graphicsbase[0]; 360 tmpVertices[i].m_floats[1] = graphicsbase[1]; 361 tmpVertices[i].m_floats[2] = graphicsbase[2]; 362 } 363 serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); 364 } 365 break; 366 } 367 368 default: 369 btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE)); 370 } 371 372 unLockReadOnlyVertexBase(part); 373 } 374 375 serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr); 376 } 377 378 379 m_scaling.serializeFloat(trimeshData->m_scaling); 380 return "btStridingMeshInterfaceData"; 381 } 382