1 /* 2 bParse 3 Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com 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 "btBulletFile.h" 17 #include "bDefines.h" 18 #include "bDNA.h" 19 20 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) 21 #include <memory.h> 22 #endif 23 #include <string.h> 24 25 26 // 32 && 64 bit versions 27 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 28 #ifdef _WIN64 29 extern char sBulletDNAstr64[]; 30 extern int sBulletDNAlen64; 31 #else 32 extern char sBulletDNAstr[]; 33 extern int sBulletDNAlen; 34 #endif //_WIN64 35 #else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 36 37 extern char sBulletDNAstr64[]; 38 extern int sBulletDNAlen64; 39 extern char sBulletDNAstr[]; 40 extern int sBulletDNAlen; 41 42 #endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 43 44 using namespace bParse; 45 46 btBulletFile::btBulletFile() 47 :bFile("", "BULLET ") 48 { 49 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" 50 51 m_DnaCopy = 0; 52 53 54 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 55 #ifdef _WIN64 56 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); 57 memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); 58 mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); 59 #else//_WIN64 60 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); 61 memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); 62 mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); 63 #endif//_WIN64 64 #else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 65 if (VOID_IS_8) 66 { 67 m_DnaCopy = (char*) btAlignedAlloc(sBulletDNAlen64,16); 68 memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); 69 mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); 70 } 71 else 72 { 73 m_DnaCopy =(char*) btAlignedAlloc(sBulletDNAlen,16); 74 memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); 75 mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); 76 } 77 #endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 78 } 79 80 81 82 btBulletFile::btBulletFile(const char* fileName) 83 :bFile(fileName, "BULLET ") 84 { 85 m_DnaCopy = 0; 86 } 87 88 89 90 btBulletFile::btBulletFile(char *memoryBuffer, int len) 91 :bFile(memoryBuffer,len, "BULLET ") 92 { 93 m_DnaCopy = 0; 94 } 95 96 97 btBulletFile::~btBulletFile() 98 { 99 if (m_DnaCopy) 100 btAlignedFree(m_DnaCopy); 101 102 103 while (m_dataBlocks.size()) 104 { 105 char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1]; 106 delete[] dataBlock; 107 m_dataBlocks.pop_back(); 108 } 109 110 } 111 112 113 114 // ----------------------------------------------------- // 115 void btBulletFile::parseData() 116 { 117 // printf ("Building datablocks"); 118 // printf ("Chunk size = %d",CHUNK_HEADER_LEN); 119 // printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags)); 120 121 const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0; 122 123 //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0; 124 125 126 int remain = mFileLen; 127 128 mDataStart = 12; 129 remain-=12; 130 131 132 char *dataPtr = mFileBuffer+mDataStart; 133 134 bChunkInd dataChunk; 135 dataChunk.code = 0; 136 137 138 //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); 139 int seek = getNextBlock(&dataChunk, dataPtr, mFlags); 140 141 142 if (mFlags &FD_ENDIAN_SWAP) 143 swapLen(dataPtr); 144 145 //dataPtr += ChunkUtils::getOffset(mFlags); 146 char *dataPtrHead = 0; 147 148 while (dataChunk.code != DNA1) 149 { 150 if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) ) 151 { 152 153 // one behind 154 if (dataChunk.code == SDNA) break; 155 //if (dataChunk.code == DNA1) break; 156 157 // same as (BHEAD+DATA dependency) 158 dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags); 159 if (dataChunk.dna_nr>=0) 160 { 161 char *id = readStruct(dataPtrHead, dataChunk); 162 163 // lookup maps 164 if (id) 165 { 166 m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk); 167 mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id); 168 169 m_chunks.push_back(dataChunk); 170 // block it 171 //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code); 172 //if (listID) 173 // listID->push_back((bStructHandle*)id); 174 } 175 176 if (dataChunk.code == BT_MULTIBODY_CODE) 177 { 178 m_multiBodies.push_back((bStructHandle*)id); 179 } 180 181 if (dataChunk.code == BT_SOFTBODY_CODE) 182 { 183 m_softBodies.push_back((bStructHandle*) id); 184 } 185 186 if (dataChunk.code == BT_RIGIDBODY_CODE) 187 { 188 m_rigidBodies.push_back((bStructHandle*) id); 189 } 190 191 if (dataChunk.code == BT_DYNAMICSWORLD_CODE) 192 { 193 m_dynamicsWorldInfo.push_back((bStructHandle*) id); 194 } 195 196 if (dataChunk.code == BT_CONSTRAINT_CODE) 197 { 198 m_constraints.push_back((bStructHandle*) id); 199 } 200 201 if (dataChunk.code == BT_QUANTIZED_BVH_CODE) 202 { 203 m_bvhs.push_back((bStructHandle*) id); 204 } 205 206 if (dataChunk.code == BT_TRIANLGE_INFO_MAP) 207 { 208 m_triangleInfoMaps.push_back((bStructHandle*) id); 209 } 210 211 if (dataChunk.code == BT_COLLISIONOBJECT_CODE) 212 { 213 m_collisionObjects.push_back((bStructHandle*) id); 214 } 215 216 if (dataChunk.code == BT_SHAPE_CODE) 217 { 218 m_collisionShapes.push_back((bStructHandle*) id); 219 } 220 221 // if (dataChunk.code == GLOB) 222 // { 223 // m_glob = (bStructHandle*) id; 224 // } 225 } else 226 { 227 printf("unknown chunk\n"); 228 229 mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead); 230 } 231 } else 232 { 233 printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n"); 234 } 235 236 237 dataPtr += seek; 238 remain-=seek; 239 if (remain<=0) 240 break; 241 242 seek = getNextBlock(&dataChunk, dataPtr, mFlags); 243 if (mFlags &FD_ENDIAN_SWAP) 244 swapLen(dataPtr); 245 246 if (seek < 0) 247 break; 248 } 249 250 } 251 252 void btBulletFile::addDataBlock(char* dataBlock) 253 { 254 m_dataBlocks.push_back(dataBlock); 255 256 } 257 258 259 260 261 void btBulletFile::writeDNA(FILE* fp) 262 { 263 264 bChunkInd dataChunk; 265 dataChunk.code = DNA1; 266 dataChunk.dna_nr = 0; 267 dataChunk.nr = 1; 268 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 269 if (VOID_IS_8) 270 { 271 #ifdef _WIN64 272 dataChunk.len = sBulletDNAlen64; 273 dataChunk.oldPtr = sBulletDNAstr64; 274 fwrite(&dataChunk,sizeof(bChunkInd),1,fp); 275 fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); 276 #else 277 btAssert(0); 278 #endif 279 } 280 else 281 { 282 #ifndef _WIN64 283 dataChunk.len = sBulletDNAlen; 284 dataChunk.oldPtr = sBulletDNAstr; 285 fwrite(&dataChunk,sizeof(bChunkInd),1,fp); 286 fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); 287 #else//_WIN64 288 btAssert(0); 289 #endif//_WIN64 290 } 291 #else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 292 if (VOID_IS_8) 293 { 294 dataChunk.len = sBulletDNAlen64; 295 dataChunk.oldPtr = sBulletDNAstr64; 296 fwrite(&dataChunk,sizeof(bChunkInd),1,fp); 297 fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); 298 } 299 else 300 { 301 dataChunk.len = sBulletDNAlen; 302 dataChunk.oldPtr = sBulletDNAstr; 303 fwrite(&dataChunk,sizeof(bChunkInd),1,fp); 304 fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); 305 } 306 #endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 307 } 308 309 310 void btBulletFile::parse(int verboseMode) 311 { 312 #ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 313 if (VOID_IS_8) 314 { 315 #ifdef _WIN64 316 317 if (m_DnaCopy) 318 delete m_DnaCopy; 319 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); 320 memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); 321 parseInternal(verboseMode,(char*)sBulletDNAstr64,sBulletDNAlen64); 322 #else 323 btAssert(0); 324 #endif 325 } 326 else 327 { 328 #ifndef _WIN64 329 330 if (m_DnaCopy) 331 delete m_DnaCopy; 332 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); 333 memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); 334 parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen); 335 #else 336 btAssert(0); 337 #endif 338 } 339 #else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 340 if (VOID_IS_8) 341 { 342 if (m_DnaCopy) 343 delete m_DnaCopy; 344 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); 345 memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); 346 parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen64); 347 } 348 else 349 { 350 if (m_DnaCopy) 351 delete m_DnaCopy; 352 m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); 353 memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); 354 parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen); 355 } 356 #endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES 357 358 //the parsing will convert to cpu endian 359 mFlags &=~FD_ENDIAN_SWAP; 360 361 int littleEndian= 1; 362 littleEndian= ((char*)&littleEndian)[0]; 363 364 mFileBuffer[8] = littleEndian?'v':'V'; 365 366 } 367 368 // experimental 369 int btBulletFile::write(const char* fileName, bool fixupPointers) 370 { 371 FILE *fp = fopen(fileName, "wb"); 372 if (fp) 373 { 374 char header[SIZEOFBLENDERHEADER] ; 375 memcpy(header, m_headerString, 7); 376 int endian= 1; 377 endian= ((char*)&endian)[0]; 378 379 if (endian) 380 { 381 header[7] = '_'; 382 } else 383 { 384 header[7] = '-'; 385 } 386 if (VOID_IS_8) 387 { 388 header[8]='V'; 389 } else 390 { 391 header[8]='v'; 392 } 393 394 header[9] = '2'; 395 header[10] = '7'; 396 header[11] = '5'; 397 398 fwrite(header,SIZEOFBLENDERHEADER,1,fp); 399 400 writeChunks(fp, fixupPointers); 401 402 writeDNA(fp); 403 404 fclose(fp); 405 406 } else 407 { 408 printf("Error: cannot open file %s for writing\n",fileName); 409 return 0; 410 } 411 return 1; 412 } 413 414 415 416 void btBulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code) 417 { 418 419 bParse::bChunkInd dataChunk; 420 dataChunk.code = code; 421 dataChunk.nr = 1; 422 dataChunk.len = len; 423 dataChunk.dna_nr = mMemoryDNA->getReverseType(structType); 424 dataChunk.oldPtr = oldPtr; 425 426 ///Perform structure size validation 427 short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr); 428 int elemBytes; 429 elemBytes= mMemoryDNA->getLength(structInfo[0]); 430 // int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]); 431 assert(len==elemBytes); 432 433 mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data); 434 m_chunks.push_back(dataChunk); 435 } 436 437