Bullet Collision Detection & Physics Library: bDNA.cpp Source File

Bullet Collision Detection & Physics Library

bDNA.cpp
Go to the documentation of this file.
1 /*
2 bParse
3 Copyright (c) 2006-2009 Charlie C & 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 #include <assert.h>
16
17 #include "bDNA.h"
18 #include "bChunk.h"
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 //this define will force traversal of structures, to check backward (and forward) compatibility
24 //#define TEST_BACKWARD_FORWARD_COMPATIBILITY
25
26
27 using namespace bParse;
28
29
30 // ----------------------------------------------------- //
31 bDNA::bDNA()
32 : mPtrLen(0)
33 {
34 // --
35 }
36
37 // ----------------------------------------------------- //
38 bDNA::~bDNA()
39 {
40 // --
41 }
42
43 // ----------------------------------------------------- //
44 bool bDNA::lessThan(bDNA *file)
45 {
46 return ( m_Names.size() < file->m_Names.size());
47 }
48
49 // ----------------------------------------------------- //
50 char *bDNA::getName(int ind)
51 {
52 assert(ind <= (int)m_Names.size());
53 return m_Names[ind].m_name;
54 }
55
56
57 // ----------------------------------------------------- //
58 char *bDNA::getType(int ind)
59 {
60 assert(ind<= (int)mTypes.size());
61 return mTypes[ind];
62 }
63
64
65 // ----------------------------------------------------- //
66 short *bDNA::getStruct(int ind)
67 {
68 assert(ind <= (int)mStructs.size());
69 return mStructs[ind];
70 }
71
72
73 // ----------------------------------------------------- //
74 short bDNA::getLength(int ind)
75 {
76 assert(ind <= (int)mTlens.size());
77 return mTlens[ind];
78 }
79
80
81 // ----------------------------------------------------- //
82 int bDNA::getReverseType(short type)
83 {
84
85 int* intPtr = mStructReverse.find(type);
86 if (intPtr)
87 return *intPtr;
88
89 return -1;
90 }
91
92 // ----------------------------------------------------- //
93 int bDNA::getReverseType(const char *type)
94 {
95
96 btHashString key(type);
97 int* valuePtr = mTypeLookup.find(key);
98 if (valuePtr)
99 return *valuePtr;
100
101 return -1;
102 }
103
104 // ----------------------------------------------------- //
105 int bDNA::getNumStructs()
106 {
107 return (int)mStructs.size();
108 }
109
110 // ----------------------------------------------------- //
111 bool bDNA::flagNotEqual(int dna_nr)
112 {
113 assert(dna_nr <= (int)mCMPFlags.size());
114 return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
115 }
116
117 // ----------------------------------------------------- //
118 bool bDNA::flagEqual(int dna_nr)
119 {
120 assert(dna_nr <= (int)mCMPFlags.size());
121 int flag = mCMPFlags[dna_nr];
122 return flag == FDF_STRUCT_EQU;
123 }
124
125 // ----------------------------------------------------- //
126 bool bDNA::flagNone(int dna_nr)
127 {
128 assert(dna_nr <= (int)mCMPFlags.size());
129 return mCMPFlags[dna_nr] == FDF_NONE;
130 }
131
132 // ----------------------------------------------------- //
133 int bDNA::getPointerSize()
134 {
135 return mPtrLen;
136 }
137
138 // ----------------------------------------------------- //
139 void bDNA::initRecurseCmpFlags(int iter)
140 {
141 // iter is FDF_STRUCT_NEQU
142
143 short *oldStrc = mStructs[iter];
144 short type = oldStrc[0];
145
146 for (int i=0; i<(int)mStructs.size(); i++)
147 {
148 if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
149 {
150 short *curStruct = mStructs[i];
151 int eleLen = curStruct[1];
152 curStruct+=2;
153
154 for (int j=0; j<eleLen; j++, curStruct+=2)
155 {
156 if (curStruct[0] == type)
157 {
158 //char *name = m_Names[curStruct[1]].m_name;
159 //if (name[0] != '*')
160 if (m_Names[curStruct[1]].m_isPointer)
161 {
162 mCMPFlags[i] = FDF_STRUCT_NEQU;
163 initRecurseCmpFlags(i);
164 }
165 }
166 }
167 }
168 }
169 }
170
171 // ----------------------------------------------------- //
172 void bDNA::initCmpFlags(bDNA *memDNA)
173 {
174
175 // compare the file to memory
176 // this ptr should be the file data
177
178
179 assert(!(m_Names.size() == 0));//DNA empty!
180
181 mCMPFlags.resize(mStructs.size(), FDF_NONE);
182
183
184
185 int i;
186 for ( i=0; i<(int)mStructs.size(); i++)
187 {
188 short *oldStruct = mStructs[i];
189
190 int oldLookup = getReverseType(oldStruct[0]);
191 if (oldLookup == -1)
192 {
193 mCMPFlags[i] = FDF_NONE;
194 continue;
195 }
196 //char* typeName = mTypes[oldStruct[0]];
197
198 //#define SLOW_FORWARD_COMPATIBLE 1
199 #ifdef SLOW_FORWARD_COMPATIBLE
200 char* typeName = mTypes[oldLookup];
201 int newLookup = memDNA->getReverseType(typeName);
202 if (newLookup == -1)
203 {
204 mCMPFlags[i] = FDF_NONE;
205 continue;
206 }
207 short *curStruct = memDNA->mStructs[newLookup];
208 #else
209 // memory for file
210
211 if (oldLookup < memDNA->mStructs.size())
212 {
213 short *curStruct = memDNA->mStructs[oldLookup];
214 #endif
215
216
217
218 // rebuild...
219 mCMPFlags[i] = FDF_STRUCT_NEQU;
220
221 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
222
223 if (curStruct[1] == oldStruct[1])
224 {
225 // type len same ...
226 if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
227 {
228 bool isSame = true;
229 int elementLength = oldStruct[1];
230
231
232 curStruct+=2;
233 oldStruct+=2;
234
235
236 for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
237 {
238 // type the same
239 //const char* typeFileDNA = mTypes[oldStruct[0]];
240 //const char* typeMemDNA = mTypes[curStruct[0]];
241 if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
242 {
243 isSame=false;
244 break;
245 }
246
247 // name the same
248 if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
249 {
250 isSame=false;
251 break;
252 }
253 }
254 // flag valid ==
255 if (isSame)
256 mCMPFlags[i] = FDF_STRUCT_EQU;
257 }
258 }
259 #endif
260 }
261 }
262
263
264
265
266
267 // recurse in
268 for ( i=0; i<(int)mStructs.size(); i++)
269 {
270 if (mCMPFlags[i] == FDF_STRUCT_NEQU)
271 initRecurseCmpFlags(i);
272 }
273 }
274
275
276
277
278 static int name_is_array(char* name, int* dim1, int* dim2) {
279 int len = strlen(name);
280 /*fprintf(stderr,"[%s]",name);*/
281 /*if (len >= 1) {
282 if (name[len-1] != ']')
283 return 1;
284 }
285 return 0;*/
286 char *bp;
287 int num;
288 if (dim1) {
289 *dim1 = 1;
290 }
291 if (dim2) {
292 *dim2 = 1;
293 }
294 bp = strchr(name, '[');
295 if (!bp) {
296 return 0;
297 }
298 num = 0;
299 while (++bp < name+len-1) {
300 const char c = *bp;
301 if (c == ']') {
302 break;
303 }
304 if (c <= '9' && c >= '0') {
305 num *= 10;
306 num += (c - '0');
307 } else {
308 printf("array parse error.\n");
309 return 0;
310 }
311 }
312 if (dim2) {
313 *dim2 = num;
314 }
315
316 /* find second dim, if any. */
317 bp = strchr(bp, '[');
318 if (!bp) {
319 return 1; /* at least we got the first dim. */
320 }
321 num = 0;
322 while (++bp < name+len-1) {
323 const char c = *bp;
324 if (c == ']') {
325 break;
326 }
327 if (c <= '9' && c >= '0') {
328 num *= 10;
329 num += (c - '0');
330 } else {
331 printf("array2 parse error.\n");
332 return 1;
333 }
334 }
335 if (dim1) {
336 if (dim2) {
337 *dim1 = *dim2;
338 *dim2 = num;
339 } else {
340 *dim1 = num;
341 }
342 }
343
344 return 1;
345 }
346
347
348 // ----------------------------------------------------- //
349 void bDNA::init(char *data, int len, bool swap)
350 {
351 int *intPtr=0;short *shtPtr=0;
352 char *cp = 0;int dataLen =0;
353 //long nr=0;
354 intPtr = (int*)data;
355
356 /*
357 SDNA (4 bytes) (magic number)
358 NAME (4 bytes)
359 <nr> (4 bytes) amount of names (int)
360 <string>
361 <string>
362 */
363
364 if (strncmp(data, "SDNA", 4)==0)
365 {
366 // skip ++ NAME
367 intPtr++; intPtr++;
368 }
369
370
371
372 // Parse names
373 if (swap)
374 {
375 *intPtr = ChunkUtils::swapInt(*intPtr);
376 }
377 dataLen = *intPtr;
378 intPtr++;
379
380 cp = (char*)intPtr;
381 int i;
382 for ( i=0; i<dataLen; i++)
383 {
384 bNameInfo info;
385 info.m_name = cp;
386 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
387 name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
388 m_Names.push_back(info);
389 while (*cp)cp++;
390 cp++;
391 }
392
393
394
395 cp = btAlignPointer(cp,4);
396
397 /*
398 TYPE (4 bytes)
399 <nr> amount of types (int)
400 <string>
401 <string>
402 */
403
404 intPtr = (int*)cp;
405 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
406
407 if (swap)
408 {
409 *intPtr = ChunkUtils::swapInt(*intPtr);
410 }
411 dataLen = *intPtr;
412 intPtr++;
413
414 cp = (char*)intPtr;
415 for ( i=0; i<dataLen; i++)
416 {
417 mTypes.push_back(cp);
418 while (*cp)cp++;
419 cp++;
420 }
421
422 cp = btAlignPointer(cp,4);
423
424 /*
425 TLEN (4 bytes)
426 <len> (short) the lengths of types
427 <len>
428 */
429
430 // Parse type lens
431 intPtr = (int*)cp;
432 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
433
434 dataLen = (int)mTypes.size();
435
436 shtPtr = (short*)intPtr;
437 for ( i=0; i<dataLen; i++, shtPtr++)
438 {
439 if (swap)
440 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
441 mTlens.push_back(shtPtr[0]);
442 }
443
444 if (dataLen & 1) shtPtr++;
445
446 /*
447 STRC (4 bytes)
448 <nr> amount of structs (int)
449 <typenr>
450 <nr_of_elems>
451 <typenr>
452 <namenr>
453 <typenr>
454 <namenr>
455 */
456
457 intPtr = (int*)shtPtr;
458 cp = (char*)intPtr;
459 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
460
461 if (swap)
462 {
463 *intPtr = ChunkUtils::swapInt(*intPtr);
464 }
465 dataLen = *intPtr;
466 intPtr++;
467
468
469 shtPtr = (short*)intPtr;
470 for ( i=0; i<dataLen; i++)
471 {
472 mStructs.push_back (shtPtr);
473 if (swap)
474 {
475 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
476 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
477
478 int len = shtPtr[1];
479 shtPtr+= 2;
480
481 for (int a=0; a<len; a++, shtPtr+=2)
482 {
483 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
484 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
485 }
486 }
487 else
488 shtPtr+= (2*shtPtr[1])+2;
489 }
490
491
492 // build reverse lookups
493 for ( i=0; i<(int)mStructs.size(); i++)
494 {
495 short *strc = mStructs.at(i);
496 if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
497 {
498 mPtrLen = mTlens[strc[0]]/2;
499 }
500
501 mStructReverse.insert(strc[0], i);
502 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
503 }
504 }
505
506
507 // ----------------------------------------------------- //
508 int bDNA::getArraySize(char* string)
509 {
510 int ret = 1;
511 int len = strlen(string);
512
513
514 char* next = 0;
515 for (int i=0; i<len; i++)
516 {
517 char c = string[i];
518
519 if (c == '[')
520 next = &string[i+1];
521 else if (c==']')
522 if (next)
523 ret *= atoi(next);
524 }
525
526 // print (string << ' ' << ret);
527 return ret;
528 }
529
530
531 void bDNA::dumpTypeDefinitions()
532 {
533 int i;
534
535 int numTypes = mTypes.size();
536
537 for (i=0;i<numTypes;i++)
538 {
539
540 }
541
542 for ( i=0; i<(int)mStructs.size(); i++)
543 {
544 int totalBytes=0;
545 short *oldStruct = mStructs[i];
546
547 int oldLookup = getReverseType(oldStruct[0]);
548 if (oldLookup == -1)
549 {
550 mCMPFlags[i] = FDF_NONE;
551 continue;
552 }
553
554 short* newStruct = mStructs[oldLookup];
555 char* typeName = mTypes[newStruct[0]];
556 printf("%3d: %s ",i,typeName);
557
558 //char *name = mNames[oldStruct[1]];
559 int len = oldStruct[1];
560 printf(" (%d fields) ",len);
561 oldStruct+=2;
562
563 printf("{");
564 int j;
565 for (j=0; j<len; ++j,oldStruct+=2) {
566 const char* name = m_Names[oldStruct[1]].m_name;
567 printf("%s %s", mTypes[oldStruct[0]],name);
568 int elemNumBytes= 0;
569 int arrayDimensions = getArraySizeNew(oldStruct[1]);
570
571 if (m_Names[oldStruct[1]].m_isPointer)
572 {
573 elemNumBytes = VOID_IS_8 ? 8 : 4;
574 } else
575 {
576 elemNumBytes = getLength(oldStruct[0]);
577 }
578 printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
579
580 if (j == len-1) {
581 printf(";}");
582 } else {
583 printf("; ");
584 }
585 totalBytes+=elemNumBytes*arrayDimensions;
586 }
587 printf("\ntotalBytes=%d\n\n",totalBytes);
588
589 }
590
591
592
593 #if 0
594 /* dump out display of types and their sizes */
595 for (i=0; i<bf->types_count; ++i) {
596 /* if (!bf->types[i].is_struct)*/
597 {
598 printf("%3d: sizeof(%s%s)=%d",
599 i,
600 bf->types[i].is_struct ? "struct " : "atomic ",
601 bf->types[i].name, bf->types[i].size);
602 if (bf->types[i].is_struct) {
603 int j;
604 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
605 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
606 printf("%s %s",
607 bf->types[bf->types[i].fieldtypes[j]].name,
608 bf->names[bf->types[i].fieldnames[j]]);
609 if (j == bf->types[i].fieldtypes_count-1) {
610 printf(";}");
611 } else {
612 printf("; ");
613 }
614 }
615 }
616 printf("\n\n");
617
618 }
619 }
620 #endif
621
622 }
623
624
625
626
627 //eof
628
629
bParse::bDNA::bDNA
bDNA()
Definition: bDNA.cpp:31
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:274
bParse::bDNA::mCMPFlags
btAlignedObjectArray< int > mCMPFlags
Definition: bDNA.h:92
bParse::bDNA::FDF_NONE
Definition: bDNA.h:85
bDNA.h
bParse::bDNA::getArraySizeNew
int getArraySizeNew(short name)
Definition: bDNA.h:41
bParse::bDNA::mPtrLen
int mPtrLen
Definition: bDNA.h:101
bParse::bDNA::mStructs
btAlignedObjectArray< short * > mStructs
Definition: bDNA.h:96
bParse::bNameInfo
Definition: bDNA.h:24
bParse::bDNA::lessThan
bool lessThan(bDNA *other)
Definition: bDNA.cpp:44
btHashMap::find
const Value * find(const Key &key) const
Definition: btHashMap.h:434
bParse::bDNA::getNumStructs
int getNumStructs()
Definition: bDNA.cpp:105
btAlignedObjectArray::at
const T & at(int n) const
Definition: btAlignedObjectArray.h:160
bParse::bDNA::getName
char * getName(int ind)
Definition: bDNA.cpp:50
bParse::bDNA::dumpTypeDefinitions
void dumpTypeDefinitions()
Definition: bDNA.cpp:531
bParse::bDNA::FDF_STRUCT_EQU
Definition: bDNA.h:87
bParse::bNameInfo::m_dim0
int m_dim0
Definition: bDNA.h:28
bParse::bNameInfo::m_isPointer
bool m_isPointer
Definition: bDNA.h:27
bParse::bDNA::initCmpFlags
void initCmpFlags(bDNA *memDNA)
Definition: bDNA.cpp:172
bParse::bDNA::mTlens
btAlignedObjectArray< short > mTlens
Definition: bDNA.h:97
bParse::bDNA::m_Names
btAlignedObjectArray< bNameInfo > m_Names
Definition: bDNA.h:94
bParse::ChunkUtils::swapInt
static int swapInt(int inte)
Definition: bChunk.cpp:37
bParse::VOID_IS_8
const bool VOID_IS_8
Definition: bChunk.h:89
bParse::bDNA::mStructReverse
btHashMap< btHashInt, int > mStructReverse
Definition: bDNA.h:98
bParse::bDNA::getPointerSize
int getPointerSize()
Definition: bDNA.cpp:133
name_is_array
static int name_is_array(char *name, int *dim1, int *dim2)
Definition: bDNA.cpp:278
bParse::bNameInfo::m_name
char * m_name
Definition: bDNA.h:26
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:274
bParse::bDNA::getArraySize
int getArraySize(char *str)
Definition: bDNA.cpp:508
bChunk.h
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:155
bParse::bDNA::~bDNA
~bDNA()
Definition: bDNA.cpp:38
bParse::bDNA::flagNotEqual
bool flagNotEqual(int dna_nr)
Definition: bDNA.cpp:111
btHashString
very basic hashable string implementation, compatible with btHashMap
Definition: btHashMap.h:23
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:218
bParse
Definition: btBulletWorldImporter.h:29
bParse::bDNA
Definition: bDNA.h:32
bParse::bDNA::getStruct
short * getStruct(int ind)
Definition: bDNA.cpp:66
bParse::bDNA::FDF_STRUCT_NEQU
Definition: bDNA.h:86
bParse::bDNA::init
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:349
bParse::bDNA::flagEqual
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
btAlignPointer
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:792
bParse::ChunkUtils::swapShort
static short swapShort(short sht)
Definition: bChunk.cpp:30
bParse::bNameInfo::m_dim1
int m_dim1
Definition: bDNA.h:29
bParse::bDNA::initRecurseCmpFlags
void initRecurseCmpFlags(int i)
Definition: bDNA.cpp:139
bParse::bDNA::mTypes
btAlignedObjectArray< char * > mTypes
Definition: bDNA.h:95
bParse::bDNA::mTypeLookup
btHashMap< btHashString, int > mTypeLookup
Definition: bDNA.h:99
bParse::bDNA::getReverseType
int getReverseType(short type)
Definition: bDNA.cpp:82
bParse::bDNA::getLength
short getLength(int ind)
Definition: bDNA.cpp:74
bParse::bDNA::flagNone
bool flagNone(int dna_nr)
Definition: bDNA.cpp:126
bParse::bDNA::getType
char * getType(int ind)
Definition: bDNA.cpp:58