allow the Bullet world importer to save a copy with swapped endianness

See http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=8191
This commit is contained in:
erwin.coumans
2012-10-31 07:25:54 +00:00
parent ff38230704
commit 595dab2337
5 changed files with 315 additions and 21 deletions

View File

@@ -765,7 +765,7 @@ void SerializeDemo::initPhysics()
if (!m_fileLoader->loadFile("testFile.bullet"))
if (!m_fileLoader->loadFile("testFile.bullet", "testFileSwappedEndianness.bullet"))
// if (!m_fileLoader->loadFile("../SoftDemo/testFile.bullet"))
{
///create a few basic rigid bodies and save them to testFile.bullet

View File

@@ -300,7 +300,7 @@ void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
// ----------------------------------------------------- //
void bFile::swap(char *head, bChunkInd& dataChunk)
void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag)
{
char *data = head;
short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
@@ -308,18 +308,302 @@ void bFile::swap(char *head, bChunkInd& dataChunk)
for (int i=0; i<dataChunk.nr; i++)
{
swapStruct(dataChunk.dna_nr, data);
swapStruct(dataChunk.dna_nr, data,ignoreEndianFlag);
data+=len;
}
}
void bFile::swapLen(char *dataPtr)
{
const bool VOID_IS_8 = ((sizeof(void*)==8));
if (VOID_IS_8)
{
if (mFlags &FD_BITS_VARIES)
{
bChunkPtr4*c = (bChunkPtr4*) dataPtr;
if ((c->code & 0xFFFF)==0)
c->code >>=16;
SWITCH_INT(c->len);
SWITCH_INT(c->dna_nr);
SWITCH_INT(c->nr);
} else
{
bChunkPtr8* c = (bChunkPtr8*) dataPtr;
if ((c->code & 0xFFFF)==0)
c->code >>=16;
SWITCH_INT(c->len);
SWITCH_INT(c->dna_nr);
SWITCH_INT(c->nr);
}
} else
{
if (mFlags &FD_BITS_VARIES)
{
bChunkPtr8*c = (bChunkPtr8*) dataPtr;
if ((c->code & 0xFFFF)==0)
c->code >>=16;
SWITCH_INT(c->len);
SWITCH_INT(c->dna_nr);
SWITCH_INT(c->nr);
} else
{
bChunkPtr4* c = (bChunkPtr4*) dataPtr;
if ((c->code & 0xFFFF)==0)
c->code >>=16;
SWITCH_INT(c->len);
SWITCH_INT(c->dna_nr);
SWITCH_INT(c->nr);
}
}
}
void bFile::swapDNA(char* ptr)
{
bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0);
char* data = &ptr[20];
// void bDNA::init(char *data, int len, bool swap)
int *intPtr=0;short *shtPtr=0;
char *cp = 0;int dataLen =0;long nr=0;
intPtr = (int*)data;
/*
SDNA (4 bytes) (magic number)
NAME (4 bytes)
<nr> (4 bytes) amount of names (int)
<string>
<string>
*/
if (strncmp(data, "SDNA", 4)==0)
{
// skip ++ NAME
intPtr++; intPtr++;
}
// Parse names
if (swap)
dataLen = ChunkUtils::swapInt(*intPtr);
else
dataLen = *intPtr;
*intPtr = ChunkUtils::swapInt(*intPtr);
intPtr++;
cp = (char*)intPtr;
int i;
for ( i=0; i<dataLen; i++)
{
while (*cp)cp++;
cp++;
}
{
nr= (long)cp;
//long mask=3;
nr= ((nr+3)&~3)-nr;
while (nr--)
{
cp++;
}
}
/*
TYPE (4 bytes)
<nr> amount of types (int)
<string>
<string>
*/
intPtr = (int*)cp;
assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
if (swap)
dataLen = ChunkUtils::swapInt(*intPtr);
else
dataLen = *intPtr;
*intPtr = ChunkUtils::swapInt(*intPtr);
intPtr++;
cp = (char*)intPtr;
for ( i=0; i<dataLen; i++)
{
while (*cp)cp++;
cp++;
}
{
nr= (long)cp;
// long mask=3;
nr= ((nr+3)&~3)-nr;
while (nr--)
{
cp++;
}
}
/*
TLEN (4 bytes)
<len> (short) the lengths of types
<len>
*/
// Parse type lens
intPtr = (int*)cp;
assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
shtPtr = (short*)intPtr;
for ( i=0; i<dataLen; i++, shtPtr++)
{
//??????if (swap)
shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
}
if (dataLen & 1)
shtPtr++;
/*
STRC (4 bytes)
<nr> amount of structs (int)
<typenr>
<nr_of_elems>
<typenr>
<namenr>
<typenr>
<namenr>
*/
intPtr = (int*)shtPtr;
cp = (char*)intPtr;
assert(strncmp(cp, "STRC", 4)==0);
intPtr++;
if (swap)
dataLen = ChunkUtils::swapInt(*intPtr);
else
dataLen = *intPtr;
*intPtr = ChunkUtils::swapInt(*intPtr);
intPtr++;
shtPtr = (short*)intPtr;
for ( i=0; i<dataLen; i++)
{
//if (swap)
{
int len = shtPtr[1];
shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
shtPtr+= 2;
for (int a=0; a<len; a++, shtPtr+=2)
{
shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
}
}
// else
// shtPtr+= (2*shtPtr[1])+2;
}
}
void bFile::preSwap(const char* fileName)
{
const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
//FD_ENDIAN_SWAP
//byte 8 determines the endianness of the file, little (v) versus big (V)
if (mFileBuffer[8]=='V')
mFileBuffer[8]='v';
else
mFileBuffer[8]='V';
mDataStart = 12;
char *dataPtr = mFileBuffer+mDataStart;
bChunkInd dataChunk;
dataChunk.code = 0;
bool ignoreEndianFlag = true;
int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
//dataPtr += ChunkUtils::getOffset(mFlags);
char *dataPtrHead = 0;
while (1)
{
// one behind
if (dataChunk.code == SDNA || dataChunk.code==DNA1 || dataChunk.code == TYPE || dataChunk.code == TLEN || dataChunk.code==STRC)
{
swapDNA(dataPtr);
break;
} else
{
//if (dataChunk.code == DNA1) break;
dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
swapLen(dataPtr);
if (dataChunk.dna_nr>=0)
{
swap(dataPtrHead, dataChunk,ignoreEndianFlag);
} else
{
printf("unknown chunk\n");
}
}
// next please!
dataPtr += seek;
seek = getNextBlock(&dataChunk, dataPtr, mFlags);
if (seek < 0)
break;
}
if (mFlags & FD_ENDIAN_SWAP)
{
mFlags &= ~FD_ENDIAN_SWAP;
} else
{
mFlags |= FD_ENDIAN_SWAP;
}
FILE* f = fopen(fileName,"wb");
fwrite(mFileBuffer,1,mFileLen,f);
fclose(f);
}
// ----------------------------------------------------- //
char* bFile::readStruct(char *head, bChunkInd& dataChunk)
{
bool ignoreEndianFlag = false;
if (mFlags & FD_ENDIAN_SWAP)
swap(head, dataChunk);
swap(head, dataChunk, ignoreEndianFlag);
@@ -562,9 +846,9 @@ static void getElement(int arrayLen, const char *cur, const char *old, char *old
// ----------------------------------------------------- //
void bFile::swapData(char *data, short type, int arraySize)
void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
{
if (mFlags &FD_ENDIAN_SWAP)
if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
{
if (type == 2 || type == 3)
{
@@ -770,7 +1054,7 @@ char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupTy
// ----------------------------------------------------- //
void bFile::swapStruct(int dna_nr, char *data)
void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
{
if (dna_nr == -1) return;
@@ -795,13 +1079,13 @@ void bFile::swapStruct(int dna_nr, char *data)
int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
if (arrayLen==1)
{
swapStruct(old_nr,buf);
swapStruct(old_nr,buf,ignoreEndianFlag);
} else
{
char* tmpBuf = buf;
for (int i=0;i<arrayLen;i++)
{
swapStruct(old_nr,tmpBuf);
swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
tmpBuf+=size/arrayLen;
}
}
@@ -811,7 +1095,7 @@ void bFile::swapStruct(int dna_nr, char *data)
//int arrayLenOld = mFileDNA->getArraySize(name);
int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
//assert(arrayLenOld == arrayLen);
swapData(buf, strc[0], arrayLen);
swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
}
buf+=size;
}
@@ -1301,8 +1585,10 @@ int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int fl
bool swap = false;
bool varies = false;
if (flags &FD_ENDIAN_SWAP) swap = true;
if (flags &FD_BITS_VARIES) varies = true;
if (flags &FD_ENDIAN_SWAP)
swap = true;
if (flags &FD_BITS_VARIES)
varies = true;
if (VOID_IS_8)
{

View File

@@ -96,12 +96,11 @@ namespace bParse {
char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
void swap(char *head, class bChunkInd& ch);
void swapData(char *data, short type, int arraySize);
void swapStruct(int dna_nr, char *data);
void swap(char *head, class bChunkInd& ch, bool ignoreEndianFlag);
void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
void swapLen(char *dataPtr);
void swapDNA(char* ptr);
char* readStruct(char *head, class bChunkInd& chunk);
@@ -155,8 +154,9 @@ namespace bParse {
{
return mVersion;
}
//pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
void preSwap(const char* fileName);
};
}

View File

@@ -37,12 +37,18 @@ btBulletWorldImporter::~btBulletWorldImporter()
}
bool btBulletWorldImporter::loadFile( const char* fileName)
bool btBulletWorldImporter::loadFile( const char* fileName, const char* preSwapFilenameOut)
{
bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName);
bool result = loadFileFromMemory(bulletFile2);
if (preSwapFilenameOut)
bulletFile2->preSwap(preSwapFilenameOut);
delete bulletFile2;
return result;

View File

@@ -47,7 +47,9 @@ public:
virtual ~btBulletWorldImporter();
bool loadFile(const char* fileName);
///if you pass a valid preSwapFilenameOut, it will save a new file with a different endianness
///this pre-swapped file can be loaded without swapping on a target platform of different endianness
bool loadFile(const char* fileName, const char* preSwapFilenameOut=0);
///the memoryBuffer might be modified (for example if endian swaps are necessary)
bool loadFileFromMemory(char *memoryBuffer, int len);