2017-08-01 14:30:58 +02: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 "b3BulletFile.h"
# include "b3Defines.h"
# include "b3DNA.h"
2019-01-03 14:26:51 +01:00
# if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
2017-08-01 14:30:58 +02:00
# include <memory.h>
# endif
# include <string.h>
// 32 && 64 bit versions
# ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
# ifdef _WIN64
extern char b3s_bulletDNAstr64 [ ] ;
extern int b3s_bulletDNAlen64 ;
# else
extern char b3s_bulletDNAstr [ ] ;
extern int b3s_bulletDNAlen ;
2019-01-03 14:26:51 +01:00
# endif //_WIN64
# else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
extern char b3s_bulletDNAstr64 [ ] ;
extern int b3s_bulletDNAlen64 ;
extern char b3s_bulletDNAstr [ ] ;
extern int b3s_bulletDNAlen ;
2019-01-03 14:26:51 +01:00
# endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
using namespace bParse ;
b3BulletFile : : b3BulletFile ( )
2019-01-03 14:26:51 +01:00
: bFile ( " " , " BULLET " )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26: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"
2017-08-01 14:30:58 +02:00
m_DnaCopy = 0 ;
# ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
# ifdef _WIN64
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr64 , b3s_bulletDNAlen64 ) ;
mMemoryDNA - > init ( m_DnaCopy , b3s_bulletDNAlen64 ) ;
# else //_WIN64
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr , b3s_bulletDNAlen ) ;
mMemoryDNA - > init ( m_DnaCopy , b3s_bulletDNAlen ) ;
# endif //_WIN64
# else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
if ( VOID_IS_8 )
{
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr64 , b3s_bulletDNAlen64 ) ;
mMemoryDNA - > init ( m_DnaCopy , b3s_bulletDNAlen64 ) ;
2017-08-01 14:30:58 +02:00
}
else
{
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr , b3s_bulletDNAlen ) ;
mMemoryDNA - > init ( m_DnaCopy , b3s_bulletDNAlen ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
# endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
}
b3BulletFile : : b3BulletFile ( const char * fileName )
2019-01-03 14:26:51 +01:00
: bFile ( fileName , " BULLET " )
2017-08-01 14:30:58 +02:00
{
m_DnaCopy = 0 ;
}
2019-01-03 14:26:51 +01:00
b3BulletFile : : b3BulletFile ( char * memoryBuffer , int len )
: bFile ( memoryBuffer , len , " BULLET " )
2017-08-01 14:30:58 +02:00
{
m_DnaCopy = 0 ;
}
b3BulletFile : : ~ b3BulletFile ( )
{
if ( m_DnaCopy )
b3AlignedFree ( m_DnaCopy ) ;
while ( m_dataBlocks . size ( ) )
{
2019-01-03 14:26:51 +01:00
char * dataBlock = m_dataBlocks [ m_dataBlocks . size ( ) - 1 ] ;
2017-08-01 14:30:58 +02:00
delete [ ] dataBlock ;
m_dataBlocks . pop_back ( ) ;
}
}
// ----------------------------------------------------- //
void b3BulletFile : : parseData ( )
{
2019-01-03 14:26:51 +01:00
// printf ("Building datablocks");
// printf ("Chunk size = %d",CHUNK_HEADER_LEN);
// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const bool brokenDNA = ( mFlags & FD_BROKEN_DNA ) ! = 0 ;
2017-08-01 14:30:58 +02:00
//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
mDataStart = 12 ;
2019-01-03 14:26:51 +01:00
char * dataPtr = mFileBuffer + mDataStart ;
2017-08-01 14:30:58 +02:00
bChunkInd dataChunk ;
dataChunk . code = 0 ;
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
int seek = getNextBlock ( & dataChunk , dataPtr , mFlags ) ;
2019-01-03 14:26:51 +01:00
if ( mFlags & FD_ENDIAN_SWAP )
2017-08-01 14:30:58 +02:00
swapLen ( dataPtr ) ;
//dataPtr += ChunkUtils::getOffset(mFlags);
2019-01-03 14:26:51 +01:00
char * dataPtrHead = 0 ;
2017-08-01 14:30:58 +02:00
while ( dataChunk . code ! = B3_DNA1 )
{
2019-01-03 14:26:51 +01:00
if ( ! brokenDNA | | ( dataChunk . code ! = B3_QUANTIZED_BVH_CODE ) )
2017-08-01 14:30:58 +02:00
{
// one behind
if ( dataChunk . code = = B3_SDNA ) break ;
//if (dataChunk.code == DNA1) break;
// same as (BHEAD+DATA dependency)
2019-01-03 14:26:51 +01:00
dataPtrHead = dataPtr + ChunkUtils : : getOffset ( mFlags ) ;
if ( dataChunk . dna_nr > = 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
char * id = readStruct ( dataPtrHead , dataChunk ) ;
2017-08-01 14:30:58 +02: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);
}
if ( dataChunk . code = = B3_SOFTBODY_CODE )
{
2019-01-03 14:26:51 +01:00
m_softBodies . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
if ( dataChunk . code = = B3_RIGIDBODY_CODE )
{
2019-01-03 14:26:51 +01:00
m_rigidBodies . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_DYNAMICSWORLD_CODE )
{
2019-01-03 14:26:51 +01:00
m_dynamicsWorldInfo . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_CONSTRAINT_CODE )
{
2019-01-03 14:26:51 +01:00
m_constraints . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_QUANTIZED_BVH_CODE )
{
2019-01-03 14:26:51 +01:00
m_bvhs . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_TRIANLGE_INFO_MAP )
{
2019-01-03 14:26:51 +01:00
m_triangleInfoMaps . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_COLLISIONOBJECT_CODE )
{
2019-01-03 14:26:51 +01:00
m_collisionObjects . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
if ( dataChunk . code = = B3_SHAPE_CODE )
{
2019-01-03 14:26:51 +01:00
m_collisionShapes . push_back ( ( bStructHandle * ) id ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
// if (dataChunk.code == GLOB)
// {
// m_glob = (bStructHandle*) id;
// }
}
else
2017-08-01 14:30:58 +02:00
{
//printf("unknown chunk\n");
mLibPointers . insert ( dataChunk . oldPtr , ( bStructHandle * ) dataPtrHead ) ;
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
printf ( " skipping B3_QUANTIZED_BVH_CODE due to broken DNA \n " ) ;
}
dataPtr + = seek ;
2019-01-03 14:26:51 +01:00
seek = getNextBlock ( & dataChunk , dataPtr , mFlags ) ;
if ( mFlags & FD_ENDIAN_SWAP )
2017-08-01 14:30:58 +02:00
swapLen ( dataPtr ) ;
if ( seek < 0 )
break ;
}
}
2019-01-03 14:26:51 +01:00
void b3BulletFile : : addDataBlock ( char * dataBlock )
2017-08-01 14:30:58 +02:00
{
m_dataBlocks . push_back ( dataBlock ) ;
}
2019-01-03 14:26:51 +01:00
void b3BulletFile : : writeDNA ( FILE * fp )
2017-08-01 14:30:58 +02:00
{
bChunkInd dataChunk ;
dataChunk . code = B3_DNA1 ;
dataChunk . dna_nr = 0 ;
dataChunk . nr = 1 ;
2019-01-03 14:26:51 +01:00
# ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
if ( VOID_IS_8 )
{
# ifdef _WIN64
dataChunk . len = b3s_bulletDNAlen64 ;
dataChunk . oldPtr = b3s_bulletDNAstr64 ;
2019-01-03 14:26:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( b3s_bulletDNAstr64 , b3s_bulletDNAlen64 , 1 , fp ) ;
2017-08-01 14:30:58 +02:00
# else
b3Assert ( 0 ) ;
# endif
}
else
{
# ifndef _WIN64
dataChunk . len = b3s_bulletDNAlen ;
dataChunk . oldPtr = b3s_bulletDNAstr ;
2019-01-03 14:26:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( b3s_bulletDNAstr , b3s_bulletDNAlen , 1 , fp ) ;
# else //_WIN64
2017-08-01 14:30:58 +02:00
b3Assert ( 0 ) ;
2019-01-03 14:26:51 +01:00
# endif //_WIN64
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
# else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
if ( VOID_IS_8 )
{
dataChunk . len = b3s_bulletDNAlen64 ;
dataChunk . oldPtr = b3s_bulletDNAstr64 ;
2019-01-03 14:26:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( b3s_bulletDNAstr64 , b3s_bulletDNAlen64 , 1 , fp ) ;
2017-08-01 14:30:58 +02:00
}
else
{
dataChunk . len = b3s_bulletDNAlen ;
dataChunk . oldPtr = b3s_bulletDNAstr ;
2019-01-03 14:26:51 +01:00
fwrite ( & dataChunk , sizeof ( bChunkInd ) , 1 , fp ) ;
fwrite ( b3s_bulletDNAstr , b3s_bulletDNAlen , 1 , fp ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
# endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
void b3BulletFile : : parse ( int verboseMode )
2017-08-01 14:30:58 +02:00
{
# ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if ( VOID_IS_8 )
{
# ifdef _WIN64
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
if ( m_DnaCopy )
delete m_DnaCopy ;
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr64 , b3s_bulletDNAlen64 ) ;
parseInternal ( verboseMode , ( char * ) b3s_bulletDNAstr64 , b3s_bulletDNAlen64 ) ;
2017-08-01 14:30:58 +02:00
# else
b3Assert ( 0 ) ;
# endif
}
else
{
# ifndef _WIN64
if ( m_DnaCopy )
delete m_DnaCopy ;
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr , b3s_bulletDNAlen ) ;
parseInternal ( verboseMode , m_DnaCopy , b3s_bulletDNAlen ) ;
2017-08-01 14:30:58 +02:00
# else
b3Assert ( 0 ) ;
# endif
}
2019-01-03 14:26:51 +01:00
# else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
if ( VOID_IS_8 )
{
if ( m_DnaCopy )
delete m_DnaCopy ;
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen64 , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr64 , b3s_bulletDNAlen64 ) ;
parseInternal ( verboseMode , m_DnaCopy , b3s_bulletDNAlen64 ) ;
2017-08-01 14:30:58 +02:00
}
else
{
if ( m_DnaCopy )
delete m_DnaCopy ;
2019-01-03 14:26:51 +01:00
m_DnaCopy = ( char * ) b3AlignedAlloc ( b3s_bulletDNAlen , 16 ) ;
memcpy ( m_DnaCopy , b3s_bulletDNAstr , b3s_bulletDNAlen ) ;
parseInternal ( verboseMode , m_DnaCopy , b3s_bulletDNAlen ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
# endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
2017-08-01 14:30:58 +02:00
//the parsing will convert to cpu endian
2019-01-03 14:26:51 +01:00
mFlags & = ~ FD_ENDIAN_SWAP ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
int littleEndian = 1 ;
littleEndian = ( ( char * ) & littleEndian ) [ 0 ] ;
mFileBuffer [ 8 ] = littleEndian ? ' v ' : ' V ' ;
2017-08-01 14:30:58 +02:00
}
// experimental
2019-01-03 14:26:51 +01:00
int b3BulletFile : : write ( const char * fileName , bool fixupPointers )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
FILE * fp = fopen ( fileName , " wb " ) ;
2017-08-01 14:30:58 +02:00
if ( fp )
{
2019-01-03 14:26:51 +01:00
char header [ B3_SIZEOFBLENDERHEADER ] ;
2017-08-01 14:30:58 +02:00
memcpy ( header , m_headerString , 7 ) ;
2019-01-03 14:26:51 +01:00
int endian = 1 ;
endian = ( ( char * ) & endian ) [ 0 ] ;
2017-08-01 14:30:58 +02:00
if ( endian )
{
header [ 7 ] = ' _ ' ;
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
header [ 7 ] = ' - ' ;
}
if ( VOID_IS_8 )
{
2019-01-03 14:26:51 +01:00
header [ 8 ] = ' V ' ;
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
header [ 8 ] = ' v ' ;
2017-08-01 14:30:58 +02:00
}
header [ 9 ] = ' 2 ' ;
header [ 10 ] = ' 7 ' ;
header [ 11 ] = ' 5 ' ;
2019-01-03 14:26:51 +01:00
fwrite ( header , B3_SIZEOFBLENDERHEADER , 1 , fp ) ;
2017-08-01 14:30:58 +02:00
writeChunks ( fp , fixupPointers ) ;
writeDNA ( fp ) ;
fclose ( fp ) ;
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
printf ( " Error: cannot open file %s for writing \n " , fileName ) ;
2017-08-01 14:30:58 +02:00
return 0 ;
}
return 1 ;
}
2019-01-03 14:26:51 +01:00
void b3BulletFile : : addStruct ( const char * structType , void * data , int len , void * oldPtr , int code )
2017-08-01 14:30:58 +02: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
2019-01-03 14:26:51 +01:00
short * structInfo = mMemoryDNA - > getStruct ( dataChunk . dna_nr ) ;
2017-08-01 14:30:58 +02:00
int elemBytes ;
2019-01-03 14:26:51 +01:00
elemBytes = mMemoryDNA - > getLength ( structInfo [ 0 ] ) ;
// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
assert ( len = = elemBytes ) ;
2017-08-01 14:30:58 +02:00
mLibPointers . insert ( dataChunk . oldPtr , ( bStructHandle * ) data ) ;
m_chunks . push_back ( dataChunk ) ;
}