2022-05-13 23:42:41 -04:00
/*
bParse
Copyright ( c ) 2006 - 2010 Erwin Coumans http : //gamekit.googlecode.com
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 .
*/
# include "btBulletFile.h"
# include "bDefines.h"
# include "bDNA.h"
2026-06-03 15:08:51 +01:00
# if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
2022-05-13 23:42:41 -04:00
# include <memory.h>
# endif
# include <string.h>
// 32 && 64 bit versions
# ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
# ifdef _WIN64
extern char sBulletDNAstr64 [ ] ;
extern int sBulletDNAlen64 ;
# else
extern char sBulletDNAstr [ ] ;
extern int sBulletDNAlen ;
2026-06-03 15:08:51 +01:00
# endif //_WIN64
# else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
extern char sBulletDNAstr64 [ ] ;
extern int sBulletDNAlen64 ;
extern char sBulletDNAstr [ ] ;
extern int sBulletDNAlen ;
2026-06-03 15:08:51 +01:00
# endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
using namespace bParse ;
btBulletFile : : btBulletFile ( )
2026-06-03 15:08:51 +01:00
: bFile ( " " , " BULLET " )
2022-05-13 23:42:41 -04:00
{
2026-06-03 15:08:51 +01:00
mMemoryDNA = new bDNA ( ) ; //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
2022-05-13 23:42:41 -04:00
m_DnaCopy = 0 ;
# ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
# ifdef _WIN64
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr64 , sBulletDNAlen64 ) ;
mMemoryDNA - > init ( m_DnaCopy , sBulletDNAlen64 ) ;
# else //_WIN64
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr , sBulletDNAlen ) ;
mMemoryDNA - > init ( m_DnaCopy , sBulletDNAlen ) ;
# endif //_WIN64
# else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
if ( VOID_IS_8 )
{
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr64 , sBulletDNAlen64 ) ;
mMemoryDNA - > init ( m_DnaCopy , sBulletDNAlen64 ) ;
2022-05-13 23:42:41 -04:00
}
else
{
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr , sBulletDNAlen ) ;
mMemoryDNA - > init ( m_DnaCopy , sBulletDNAlen ) ;
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
# endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
}
btBulletFile : : btBulletFile ( const char * fileName )
2026-06-03 15:08:51 +01:00
: bFile ( fileName , " BULLET " )
2022-05-13 23:42:41 -04:00
{
m_DnaCopy = 0 ;
}
2026-06-03 15:08:51 +01:00
btBulletFile : : btBulletFile ( char * memoryBuffer , int len )
: bFile ( memoryBuffer , len , " BULLET " )
2022-05-13 23:42:41 -04:00
{
m_DnaCopy = 0 ;
}
btBulletFile : : ~ btBulletFile ( )
{
if ( m_DnaCopy )
btAlignedFree ( m_DnaCopy ) ;
while ( m_dataBlocks . size ( ) )
{
2026-06-03 15:08:51 +01:00
char * dataBlock = m_dataBlocks [ m_dataBlocks . size ( ) - 1 ] ;
2022-05-13 23:42:41 -04:00
delete [ ] dataBlock ;
m_dataBlocks . pop_back ( ) ;
}
}
// ----------------------------------------------------- //
void btBulletFile : : parseData ( )
{
2026-06-03 15:08:51 +01:00
// printf ("Building datablocks");
// printf ("Chunk size = %d",CHUNK_HEADER_LEN);
// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
2022-05-13 23:42:41 -04:00
2026-06-03 15:08:51 +01:00
const bool brokenDNA = ( mFlags & FD_BROKEN_DNA ) ! = 0 ;
2022-05-13 23:42:41 -04:00
//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
int remain = mFileLen ;
mDataStart = 12 ;
2026-06-03 15:08:51 +01:00
remain - = 12 ;
//invalid/empty file?
if ( remain < sizeof ( bChunkInd ) )
return ;
2022-05-13 23:42:41 -04:00
2026-06-03 15:08:51 +01:00
char * dataPtr = mFileBuffer + mDataStart ;
2022-05-13 23:42:41 -04:00
bChunkInd dataChunk ;
dataChunk . code = 0 ;
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
int seek = getNextBlock ( & dataChunk , dataPtr , mFlags ) ;
2026-06-03 15:08:51 +01:00
if ( mFlags & FD_ENDIAN_SWAP )
2022-05-13 23:42:41 -04:00
swapLen ( dataPtr ) ;
//dataPtr += ChunkUtils::getOffset(mFlags);
2026-06-03 15:08:51 +01:00
char * dataPtrHead = 0 ;
2022-05-13 23:42:41 -04:00
while ( dataChunk . code ! = DNA1 )
{
2026-06-03 15:08:51 +01:00
if ( ! brokenDNA | | ( dataChunk . code ! = BT_QUANTIZED_BVH_CODE ) )
2022-05-13 23:42:41 -04:00
{
// one behind
if ( dataChunk . code = = SDNA ) break ;
//if (dataChunk.code == DNA1) break;
// same as (BHEAD+DATA dependency)
2026-06-03 15:08:51 +01:00
dataPtrHead = dataPtr + ChunkUtils : : getOffset ( mFlags ) ;
if ( dataChunk . dna_nr > = 0 )
2022-05-13 23:42:41 -04:00
{
2026-06-03 15:08:51 +01:00
char * id = readStruct ( dataPtrHead , dataChunk ) ;
2022-05-13 23:42:41 -04:00
// lookup maps
if ( id )
{
m_chunkPtrPtrMap . insert ( dataChunk . oldPtr , dataChunk ) ;
mLibPointers . insert ( dataChunk . oldPtr , ( bStructHandle * ) id ) ;
m_chunks . push_back ( dataChunk ) ;
// block it
//bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
//if (listID)
// listID->push_back((bStructHandle*)id);
}
2026-06-03 15:08:51 +01:00
if ( dataChunk . code = = BT_CONTACTMANIFOLD_CODE )
{
m_contactManifolds . push_back ( ( bStructHandle * ) id ) ;
}
2022-05-13 23:42:41 -04:00
if ( dataChunk . code = = BT_MULTIBODY_CODE )
{
m_multiBodies . push_back ( ( bStructHandle * ) id ) ;
}
2026-06-03 15:08:51 +01:00
if ( dataChunk . code = = BT_MB_LINKCOLLIDER_CODE )
{
m_multiBodyLinkColliders . push_back ( ( bStructHandle * ) id ) ;
}
2022-05-13 23:42:41 -04:00
if ( dataChunk . code = = BT_SOFTBODY_CODE )
{
2026-06-03 15:08:51 +01:00
m_softBodies . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
2022-05-13 23:42:41 -04:00
if ( dataChunk . code = = BT_RIGIDBODY_CODE )
{
2026-06-03 15:08:51 +01:00
m_rigidBodies . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_DYNAMICSWORLD_CODE )
{
2026-06-03 15:08:51 +01:00
m_dynamicsWorldInfo . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_CONSTRAINT_CODE )
{
2026-06-03 15:08:51 +01:00
m_constraints . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_QUANTIZED_BVH_CODE )
{
2026-06-03 15:08:51 +01:00
m_bvhs . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_TRIANLGE_INFO_MAP )
{
2026-06-03 15:08:51 +01:00
m_triangleInfoMaps . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_COLLISIONOBJECT_CODE )
{
2026-06-03 15:08:51 +01:00
m_collisionObjects . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
if ( dataChunk . code = = BT_SHAPE_CODE )
{
2026-06-03 15:08:51 +01:00
m_collisionShapes . push_back ( ( bStructHandle * ) id ) ;
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
// if (dataChunk.code == GLOB)
// {
// m_glob = (bStructHandle*) id;
// }
}
else
2022-05-13 23:42:41 -04:00
{
//printf("unknown chunk\n");
mLibPointers . insert ( dataChunk . oldPtr , ( bStructHandle * ) dataPtrHead ) ;
}
2026-06-03 15:08:51 +01:00
}
else
2022-05-13 23:42:41 -04:00
{
printf ( " skipping BT_QUANTIZED_BVH_CODE due to broken DNA \n " ) ;
}
dataPtr + = seek ;
2026-06-03 15:08:51 +01:00
remain - = seek ;
if ( remain < = 0 )
2022-05-13 23:42:41 -04:00
break ;
2026-06-03 15:08:51 +01:00
seek = getNextBlock ( & dataChunk , dataPtr , mFlags ) ;
if ( mFlags & FD_ENDIAN_SWAP )
2022-05-13 23:42:41 -04:00
swapLen ( dataPtr ) ;
if ( seek < 0 )
break ;
}
}
2026-06-03 15:08:51 +01:00
void btBulletFile : : addDataBlock ( char * dataBlock )
2022-05-13 23:42:41 -04:00
{
m_dataBlocks . push_back ( dataBlock ) ;
}
2026-06-03 15:08:51 +01:00
void btBulletFile : : writeDNA ( FILE * fp )
2022-05-13 23:42:41 -04:00
{
bChunkInd dataChunk ;
dataChunk . code = DNA1 ;
dataChunk . dna_nr = 0 ;
dataChunk . nr = 1 ;
2026-06-03 15:08:51 +01:00
# ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
if ( VOID_IS_8 )
{
# ifdef _WIN64
dataChunk . len = sBulletDNAlen64 ;
dataChunk . oldPtr = sBulletDNAstr64 ;
2026-06-03 15:08:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( sBulletDNAstr64 , sBulletDNAlen64 , 1 , fp ) ;
2022-05-13 23:42:41 -04:00
# else
btAssert ( 0 ) ;
# endif
}
else
{
# ifndef _WIN64
dataChunk . len = sBulletDNAlen ;
dataChunk . oldPtr = sBulletDNAstr ;
2026-06-03 15:08:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( sBulletDNAstr , sBulletDNAlen , 1 , fp ) ;
# else //_WIN64
2022-05-13 23:42:41 -04:00
btAssert ( 0 ) ;
2026-06-03 15:08:51 +01:00
# endif //_WIN64
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
# else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
if ( VOID_IS_8 )
{
dataChunk . len = sBulletDNAlen64 ;
dataChunk . oldPtr = sBulletDNAstr64 ;
2026-06-03 15:08:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( sBulletDNAstr64 , sBulletDNAlen64 , 1 , fp ) ;
2022-05-13 23:42:41 -04:00
}
else
{
dataChunk . len = sBulletDNAlen ;
dataChunk . oldPtr = sBulletDNAstr ;
2026-06-03 15:08:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( sBulletDNAstr , sBulletDNAlen , 1 , fp ) ;
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
# endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
void btBulletFile : : parse ( int verboseMode )
2022-05-13 23:42:41 -04:00
{
# ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if ( VOID_IS_8 )
{
# ifdef _WIN64
2026-06-03 15:08:51 +01:00
2022-05-13 23:42:41 -04:00
if ( m_DnaCopy )
delete m_DnaCopy ;
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr64 , sBulletDNAlen64 ) ;
parseInternal ( verboseMode , ( char * ) sBulletDNAstr64 , sBulletDNAlen64 ) ;
2022-05-13 23:42:41 -04:00
# else
btAssert ( 0 ) ;
# endif
}
else
{
# ifndef _WIN64
if ( m_DnaCopy )
delete m_DnaCopy ;
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr , sBulletDNAlen ) ;
parseInternal ( verboseMode , m_DnaCopy , sBulletDNAlen ) ;
2022-05-13 23:42:41 -04:00
# else
btAssert ( 0 ) ;
# endif
}
2026-06-03 15:08:51 +01:00
# else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
if ( VOID_IS_8 )
{
if ( m_DnaCopy )
delete m_DnaCopy ;
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen64 , 16 ) ;
memset ( m_DnaCopy , 0 , sBulletDNAlen64 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr64 , sBulletDNAlen64 ) ;
parseInternal ( verboseMode , m_DnaCopy , sBulletDNAlen64 ) ;
2022-05-13 23:42:41 -04:00
}
else
{
if ( m_DnaCopy )
delete m_DnaCopy ;
2026-06-03 15:08:51 +01:00
m_DnaCopy = ( char * ) btAlignedAlloc ( sBulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , sBulletDNAstr , sBulletDNAlen ) ;
parseInternal ( verboseMode , m_DnaCopy , sBulletDNAlen ) ;
2022-05-13 23:42:41 -04:00
}
2026-06-03 15:08:51 +01:00
# endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2022-05-13 23:42:41 -04:00
//the parsing will convert to cpu endian
2026-06-03 15:08:51 +01:00
mFlags & = ~ FD_ENDIAN_SWAP ;
int littleEndian = 1 ;
littleEndian = ( ( char * ) & littleEndian ) [ 0 ] ;
2022-05-13 23:42:41 -04:00
2026-06-03 15:08:51 +01:00
mFileBuffer [ 8 ] = littleEndian ? ' v ' : ' V ' ;
2022-05-13 23:42:41 -04:00
}
// experimental
2026-06-03 15:08:51 +01:00
int btBulletFile : : write ( const char * fileName , bool fixupPointers )
2022-05-13 23:42:41 -04:00
{
2026-06-03 15:08:51 +01:00
FILE * fp = fopen ( fileName , " wb " ) ;
2022-05-13 23:42:41 -04:00
if ( fp )
{
2026-06-03 15:08:51 +01:00
char header [ SIZEOFBLENDERHEADER ] ;
2022-05-13 23:42:41 -04:00
memcpy ( header , m_headerString , 7 ) ;
2026-06-03 15:08:51 +01:00
int endian = 1 ;
endian = ( ( char * ) & endian ) [ 0 ] ;
2022-05-13 23:42:41 -04:00
if ( endian )
{
header [ 7 ] = ' _ ' ;
2026-06-03 15:08:51 +01:00
}
else
2022-05-13 23:42:41 -04:00
{
header [ 7 ] = ' - ' ;
}
if ( VOID_IS_8 )
{
2026-06-03 15:08:51 +01:00
header [ 8 ] = ' V ' ;
}
else
2022-05-13 23:42:41 -04:00
{
2026-06-03 15:08:51 +01:00
header [ 8 ] = ' v ' ;
2022-05-13 23:42:41 -04:00
}
header [ 9 ] = ' 2 ' ;
header [ 10 ] = ' 7 ' ;
header [ 11 ] = ' 5 ' ;
2026-06-03 15:08:51 +01:00
fwrite ( header , SIZEOFBLENDERHEADER , 1 , fp ) ;
2022-05-13 23:42:41 -04:00
writeChunks ( fp , fixupPointers ) ;
writeDNA ( fp ) ;
fclose ( fp ) ;
2026-06-03 15:08:51 +01:00
}
else
2022-05-13 23:42:41 -04:00
{
2026-06-03 15:08:51 +01:00
printf ( " Error: cannot open file %s for writing \n " , fileName ) ;
2022-05-13 23:42:41 -04:00
return 0 ;
}
return 1 ;
}
2026-06-03 15:08:51 +01:00
void btBulletFile : : addStruct ( const char * structType , void * data , int len , void * oldPtr , int code )
2022-05-13 23:42:41 -04:00
{
bParse : : bChunkInd dataChunk ;
dataChunk . code = code ;
dataChunk . nr = 1 ;
dataChunk . len = len ;
dataChunk . dna_nr = mMemoryDNA - > getReverseType ( structType ) ;
dataChunk . oldPtr = oldPtr ;
///Perform structure size validation
2026-06-03 15:08:51 +01:00
short * structInfo = mMemoryDNA - > getStruct ( dataChunk . dna_nr ) ;
2022-05-13 23:42:41 -04:00
int elemBytes ;
2026-06-03 15:08:51 +01:00
elemBytes = mMemoryDNA - > getLength ( structInfo [ 0 ] ) ;
// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
assert ( len = = elemBytes ) ;
2022-05-13 23:42:41 -04:00
mLibPointers . insert ( dataChunk . oldPtr , ( bStructHandle * ) data ) ;
m_chunks . push_back ( dataChunk ) ;
}