Make .bullet serialization mode robust:
Deal with broken DNA serialization. Bullet 2.76 release revision 2035 - 2046 was broken, and this includes the Maya Dynamica plugin. Added some workaround to deal with the broken .bullet files, instead of crashing.
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include "bullet_btPositionAndRadius.h"
|
||||
#include "bullet_btMultiSphereShapeData.h"
|
||||
#include "bullet_btIntIndexData.h"
|
||||
#include "bullet_btShortIntIndexData.h"
|
||||
#include "bullet_btShortIntIndexTripletData.h"
|
||||
#include "bullet_btMeshPartData.h"
|
||||
#include "bullet_btStridingMeshInterfaceData.h"
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Bullet {
|
||||
class btPositionAndRadius;
|
||||
class btMultiSphereShapeData;
|
||||
class btIntIndexData;
|
||||
class btShortIntIndexData;
|
||||
class btShortIntIndexTripletData;
|
||||
class btMeshPartData;
|
||||
class btStridingMeshInterfaceData;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Bullet {
|
||||
btVector3DoubleData *m_vertices3d;
|
||||
btIntIndexData *m_indices32;
|
||||
btShortIntIndexTripletData *m_3indices16;
|
||||
btShortIntIndexData *m_indices16;
|
||||
int m_numTriangles;
|
||||
int m_numVertices;
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Bullet {
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
char m_pad[4];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Bullet {
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
char m_pad[4];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ namespace Bullet {
|
||||
int m_numQuantizedContiguousNodes;
|
||||
btOptimizedBvhNodeFloatData *m_contiguousNodesPtr;
|
||||
btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
|
||||
btBvhSubtreeInfoData *m_subTreeInfoPtr;
|
||||
int m_traversalMode;
|
||||
int m_numSubtreeHeaders;
|
||||
btBvhSubtreeInfoData *m_subTreeInfoPtr;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Copyright (C) 2006-2009 Erwin Coumans & Charlie C
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 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.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// Auto generated from makesdna dna.c
|
||||
#ifndef __BULLET_BTSHORTINTINDEXDATA__H__
|
||||
#define __BULLET_BTSHORTINTINDEXDATA__H__
|
||||
|
||||
|
||||
// -------------------------------------------------- //
|
||||
#include "bullet_Common.h"
|
||||
|
||||
namespace Bullet {
|
||||
|
||||
|
||||
// ---------------------------------------------- //
|
||||
class btShortIntIndexData
|
||||
{
|
||||
public:
|
||||
short m_value;
|
||||
char m_pad[2];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif//__BULLET_BTSHORTINTINDEXDATA__H__
|
||||
@@ -99,6 +99,7 @@ namespace bParse {
|
||||
btHashMap<btHashString,int> mTypeLookup;
|
||||
|
||||
int mPtrLen;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -200,6 +200,24 @@ void bFile::parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLengt
|
||||
mFileDNA = new bDNA();
|
||||
mFileDNA->init(blenderData+sdnaPos, mFileLen-sdnaPos, (mFlags & FD_ENDIAN_SWAP)!=0);
|
||||
|
||||
if (mVersion==276)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<mFileDNA->getNumNames();i++)
|
||||
{
|
||||
if (strcmp(mFileDNA->getName(i),"int")==0)
|
||||
{
|
||||
mFlags |= FD_BROKEN_DNA;
|
||||
}
|
||||
}
|
||||
if ((mFlags&FD_BROKEN_DNA)!=0)
|
||||
{
|
||||
printf("warning: fixing some broken DNA version\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (verboseDumpAllTypes)
|
||||
{
|
||||
mFileDNA->dumpTypeDefinitions();
|
||||
@@ -211,7 +229,7 @@ void bFile::parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLengt
|
||||
|
||||
mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
|
||||
@@ -276,6 +294,34 @@ char* bFile::readStruct(char *head, bChunkInd& dataChunk)
|
||||
oldType = mFileDNA->getType(oldStruct[0]);
|
||||
oldLen = mFileDNA->getLength(oldStruct[0]);
|
||||
|
||||
if ((mFlags&FD_BROKEN_DNA)!=0)
|
||||
{
|
||||
if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((strcmp(oldType,"btShortIntIndexData")==0))
|
||||
{
|
||||
int allocLen = 2;
|
||||
char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
|
||||
memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
|
||||
short* dest = (short*) dataAlloc;
|
||||
const short* src = (short*) head;
|
||||
for (int i=0;i<dataChunk.nr;i++)
|
||||
{
|
||||
dest[i] = src[i];
|
||||
if (mFlags &FD_ENDIAN_SWAP)
|
||||
{
|
||||
SWITCH_SHORT(dest[i]);
|
||||
}
|
||||
}
|
||||
addDataBlock(dataAlloc);
|
||||
return dataAlloc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///don't try to convert Link block data, just memcpy it. Other data can be converted.
|
||||
if (strcmp("Link",oldType)!=0)
|
||||
{
|
||||
@@ -507,7 +553,7 @@ void bFile::swapData(char *data, short type, int arraySize)
|
||||
|
||||
|
||||
|
||||
void bFile::safeSwapPtr(char *dst, char *src)
|
||||
void bFile::safeSwapPtr(char *dst, const char *src)
|
||||
{
|
||||
int ptrFile = mFileDNA->getPointerSize();
|
||||
int ptrMem = mMemoryDNA->getPointerSize();
|
||||
@@ -535,8 +581,12 @@ void bFile::safeSwapPtr(char *dst, char *src)
|
||||
//deal with pointers the Blender .blend style way, see
|
||||
//readfile.c in the Blender source tree
|
||||
long64 longValue = *((long64*)src);
|
||||
//endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
|
||||
if (mFlags & FD_ENDIAN_SWAP)
|
||||
SWITCH_LONGINT(longValue);
|
||||
*((int*)dst) = (int)(longValue>>3);
|
||||
}
|
||||
|
||||
}
|
||||
else if (ptrMem==8 && ptrFile==4)
|
||||
{
|
||||
@@ -576,9 +626,18 @@ void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const c
|
||||
const char* type = mFileDNA->getType(dna_addr[0]);
|
||||
const char* name = mFileDNA->getName(dna_addr[1]);
|
||||
|
||||
int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
|
||||
|
||||
|
||||
int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
|
||||
|
||||
if ((mFlags&FD_BROKEN_DNA)!=0)
|
||||
{
|
||||
if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
|
||||
{
|
||||
eleLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(lookupName, name)==0)
|
||||
{
|
||||
//int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
|
||||
@@ -739,7 +798,7 @@ void bFile::resolvePointersMismatch()
|
||||
// printf("pointer not found: %x\n",cur);
|
||||
}
|
||||
}
|
||||
for (i=0;i< m_pointerPtrFixupArray.size();i++)
|
||||
for (i=0;i< m_pointerPtrFixupArray.size();i++)
|
||||
{
|
||||
char* cur= m_pointerPtrFixupArray.at(i);
|
||||
void** ptrptr = (void**)cur;
|
||||
@@ -751,30 +810,32 @@ void bFile::resolvePointersMismatch()
|
||||
void **array= (void**)(*(ptrptr));
|
||||
int ptrMem = mMemoryDNA->getPointerSize();
|
||||
int ptrFile = mFileDNA->getPointerSize();
|
||||
|
||||
|
||||
int n=0, n2=0;
|
||||
int swapoffs = 2;
|
||||
void *np = array[n];
|
||||
while(np)
|
||||
int n=0;
|
||||
void *lookup = array[n];
|
||||
|
||||
if (lookup)
|
||||
{
|
||||
if (ptrMem > ptrFile)
|
||||
char *oldPtr = (char*)array;
|
||||
btAlignedObjectArray<btPointerUid> pointers;
|
||||
|
||||
while(lookup)
|
||||
{
|
||||
safeSwapPtr((char*)&array[n2], (char*)&array[n]);
|
||||
np = findLibPointer(array[n2]);
|
||||
btPointerUid dp = {0};
|
||||
safeSwapPtr((char*)dp.m_uniqueIds, (char*)(oldPtr + (n * ptrFile)));
|
||||
|
||||
lookup = findLibPointer(dp.m_ptr);
|
||||
if (!lookup) break;
|
||||
|
||||
pointers.push_back(dp);
|
||||
++n;
|
||||
}
|
||||
else if (ptrMem < ptrFile)
|
||||
{
|
||||
safeSwapPtr((char*)&array[n], (char*)&array[n2]);
|
||||
np = findLibPointer(array[n]);
|
||||
}
|
||||
else
|
||||
np = findLibPointer(array[n]);
|
||||
|
||||
if (np)
|
||||
array[n] = np;
|
||||
++n;
|
||||
n2 += swapoffs;
|
||||
for (int j=0; j<n; ++j)
|
||||
{
|
||||
array[j] = findLibPointer(pointers[j].m_ptr);
|
||||
assert(array[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1202,8 +1263,11 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
|
||||
{
|
||||
long64 oldPtr =0;
|
||||
memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
|
||||
if (swap)
|
||||
SWITCH_LONGINT(oldPtr);
|
||||
chunk.m_uniqueInt = (int)(oldPtr >> 3);
|
||||
}
|
||||
|
||||
|
||||
chunk.dna_nr = head.dna_nr;
|
||||
chunk.nr = head.nr;
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace bParse {
|
||||
FD_FILE_64 =8,
|
||||
FD_BITS_VARIES =16,
|
||||
FD_VERSION_VARIES = 32,
|
||||
FD_DOUBLE_PRECISION =64
|
||||
FD_DOUBLE_PRECISION =64,
|
||||
FD_BROKEN_DNA = 128
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +72,7 @@ namespace bParse {
|
||||
|
||||
// buffer offset util
|
||||
int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
|
||||
void safeSwapPtr(char *dst, char *src);
|
||||
void safeSwapPtr(char *dst, const char *src);
|
||||
|
||||
virtual void parseHeader();
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ void btBulletFile::parseData()
|
||||
printf ("Chunk size = %d",CHUNK_HEADER_LEN);
|
||||
printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
|
||||
|
||||
const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
|
||||
|
||||
//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
|
||||
|
||||
|
||||
@@ -126,71 +128,74 @@ void btBulletFile::parseData()
|
||||
|
||||
while (dataChunk.code != DNA1)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
// one behind
|
||||
if (dataChunk.code == SDNA) break;
|
||||
//if (dataChunk.code == DNA1) break;
|
||||
|
||||
// same as (BHEAD+DATA dependency)
|
||||
dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
|
||||
if (dataChunk.dna_nr>=0)
|
||||
if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) )
|
||||
{
|
||||
char *id = readStruct(dataPtrHead, dataChunk);
|
||||
|
||||
// lookup maps
|
||||
if (id)
|
||||
// one behind
|
||||
if (dataChunk.code == SDNA) break;
|
||||
//if (dataChunk.code == DNA1) break;
|
||||
|
||||
// same as (BHEAD+DATA dependency)
|
||||
dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
|
||||
if (dataChunk.dna_nr>=0)
|
||||
{
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
|
||||
char *id = readStruct(dataPtrHead, dataChunk);
|
||||
|
||||
m_chunks.push_back(dataChunk);
|
||||
// block it
|
||||
//bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
|
||||
//if (listID)
|
||||
// listID->push_back((bStructHandle*)id);
|
||||
}
|
||||
// lookup maps
|
||||
if (id)
|
||||
{
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
|
||||
|
||||
if (dataChunk.code == BT_RIGIDBODY_CODE)
|
||||
m_chunks.push_back(dataChunk);
|
||||
// block it
|
||||
//bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
|
||||
//if (listID)
|
||||
// listID->push_back((bStructHandle*)id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_RIGIDBODY_CODE)
|
||||
{
|
||||
m_rigidBodies.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_CONSTRAINT_CODE)
|
||||
{
|
||||
m_constraints.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_QUANTIZED_BVH_CODE)
|
||||
{
|
||||
m_bvhs.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_TRIANLGE_INFO_MAP)
|
||||
{
|
||||
m_triangleInfoMaps.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_COLLISIONOBJECT_CODE)
|
||||
{
|
||||
m_collisionObjects.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_SHAPE_CODE)
|
||||
{
|
||||
m_collisionShapes.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
// if (dataChunk.code == GLOB)
|
||||
// {
|
||||
// m_glob = (bStructHandle*) id;
|
||||
// }
|
||||
} else
|
||||
{
|
||||
m_rigidBodies.push_back((bStructHandle*) id);
|
||||
}
|
||||
printf("unknown chunk\n");
|
||||
|
||||
if (dataChunk.code == BT_CONSTRAINT_CODE)
|
||||
{
|
||||
m_constraints.push_back((bStructHandle*) id);
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_QUANTIZED_BVH_CODE)
|
||||
{
|
||||
m_bvhs.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_TRIANLGE_INFO_MAP)
|
||||
{
|
||||
m_triangleInfoMaps.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_COLLISIONOBJECT_CODE)
|
||||
{
|
||||
m_collisionObjects.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == BT_SHAPE_CODE)
|
||||
{
|
||||
m_collisionShapes.push_back((bStructHandle*) id);
|
||||
}
|
||||
|
||||
// if (dataChunk.code == GLOB)
|
||||
// {
|
||||
// m_glob = (bStructHandle*) id;
|
||||
// }
|
||||
} else
|
||||
{
|
||||
printf("unknown chunk\n");
|
||||
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
|
||||
printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n");
|
||||
}
|
||||
|
||||
// next please!
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "BulletCollision/Gimpact/btGImpactShape.h"
|
||||
|
||||
|
||||
//#define USE_INTERNAL_EDGE_UTILITY
|
||||
#ifdef USE_INTERNAL_EDGE_UTILITY
|
||||
#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
|
||||
@@ -106,8 +107,17 @@ btTriangleIndexVertexArray* btBulletWorldImporter::createMeshInterface(btStridin
|
||||
} else
|
||||
{
|
||||
meshPart.m_indexType = PHY_SHORT;
|
||||
meshPart.m_triangleIndexStride = sizeof(btShortIntIndexTripletData);
|
||||
meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_3indices16;
|
||||
if (meshData.m_meshPartsPtr[i].m_3indices16)
|
||||
{
|
||||
meshPart.m_triangleIndexStride = sizeof(btShortIntIndexTripletData);
|
||||
meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_3indices16;
|
||||
}
|
||||
if (meshData.m_meshPartsPtr[i].m_indices16)
|
||||
{
|
||||
meshPart.m_triangleIndexStride = 3*sizeof(short int);
|
||||
meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_indices16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (meshData.m_meshPartsPtr[i].m_vertices3f)
|
||||
@@ -124,8 +134,10 @@ btTriangleIndexVertexArray* btBulletWorldImporter::createMeshInterface(btStridin
|
||||
meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
|
||||
meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
|
||||
|
||||
|
||||
meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
|
||||
if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
|
||||
{
|
||||
meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
|
||||
}
|
||||
}
|
||||
|
||||
return meshInterface;
|
||||
@@ -338,13 +350,17 @@ btCollisionShape* btBulletWorldImporter::convertCollisionShape( btCollisionShap
|
||||
{
|
||||
btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
|
||||
btTriangleIndexVertexArray* meshInterface = createMeshInterface(trimesh->m_meshInterface);
|
||||
if (!meshInterface->getNumSubParts())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
|
||||
meshInterface->setScaling(scaling);
|
||||
|
||||
|
||||
btOptimizedBvh* bvh = 0;
|
||||
#if 1
|
||||
#if 0
|
||||
if (trimesh->m_quantizedFloatBvh)
|
||||
{
|
||||
btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh);
|
||||
@@ -512,6 +528,11 @@ bool btBulletWorldImporter::loadFileFromMemory( bParse::btBulletFile* bulletFil
|
||||
startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform);
|
||||
// startTransform.setBasis(btMatrix3x3::getIdentity());
|
||||
btCollisionShape* shape = (btCollisionShape*)*shapePtr;
|
||||
if (shape->isNonMoving())
|
||||
{
|
||||
mass = 0.f;
|
||||
}
|
||||
|
||||
if (mass)
|
||||
{
|
||||
shape->calculateLocalInertia(mass,localInertia);
|
||||
@@ -548,6 +569,10 @@ bool btBulletWorldImporter::loadFileFromMemory( bParse::btBulletFile* bulletFil
|
||||
startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform);
|
||||
// startTransform.setBasis(btMatrix3x3::getIdentity());
|
||||
btCollisionShape* shape = (btCollisionShape*)*shapePtr;
|
||||
if (shape->isNonMoving())
|
||||
{
|
||||
mass = 0.f;
|
||||
}
|
||||
if (mass)
|
||||
{
|
||||
shape->calculateLocalInertia(mass,localInertia);
|
||||
|
||||
Reference in New Issue
Block a user