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

Bullet Collision Detection & Physics Library

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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 && "SDNA empty!");
180 mCMPFlags.resize(mStructs.size(), FDF_NONE);
181
182
183
184 int i;
185 for ( i=0; i<(int)mStructs.size(); i++)
186 {
187 short *oldStruct = mStructs[i];
188
189 int oldLookup = getReverseType(oldStruct[0]);
190 if (oldLookup == -1)
191 {
192 mCMPFlags[i] = FDF_NONE;
193 continue;
194 }
195 //char* typeName = mTypes[oldStruct[0]];
196
197 //#define SLOW_FORWARD_COMPATIBLE 1
198 #ifdef SLOW_FORWARD_COMPATIBLE
199 char* typeName = mTypes[oldLookup];
200 int newLookup = memDNA->getReverseType(typeName);
201 if (newLookup == -1)
202 {
203 mCMPFlags[i] = FDF_NONE;
204 continue;
205 }
206 short *curStruct = memDNA->mStructs[newLookup];
207 #else
208 // memory for file
209
210 if (oldLookup < memDNA->mStructs.size())
211 {
212 short *curStruct = memDNA->mStructs[oldLookup];
213 #endif
214
215
216
217 // rebuild...
218 mCMPFlags[i] = FDF_STRUCT_NEQU;
219
220 #ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
221
222 if (curStruct[1] == oldStruct[1])
223 {
224 // type len same ...
225 if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
226 {
227 bool isSame = true;
228 int elementLength = oldStruct[1];
229
230
231 curStruct+=2;
232 oldStruct+=2;
233
234
235 for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
236 {
237 // type the same
238 //const char* typeFileDNA = mTypes[oldStruct[0]];
239 //const char* typeMemDNA = mTypes[curStruct[0]];
240 if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
241 {
242 isSame=false;
243 break;
244 }
245
246 // name the same
247 if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
248 {
249 isSame=false;
250 break;
251 }
252 }
253 // flag valid ==
254 if (isSame)
255 mCMPFlags[i] = FDF_STRUCT_EQU;
256 }
257 }
258 #endif
259 }
260 }
261
262
263
264
265
266 // recurse in
267 for ( i=0; i<(int)mStructs.size(); i++)
268 {
269 if (mCMPFlags[i] == FDF_STRUCT_NEQU)
270 initRecurseCmpFlags(i);
271 }
272 }
273
274
275
276
277 static int name_is_array(char* name, int* dim1, int* dim2) {
278 int len = strlen(name);
279 /*fprintf(stderr,"[%s]",name);*/
280 /*if (len >= 1) {
281 if (name[len-1] != ']')
282 return 1;
283 }
284 return 0;*/
285 char *bp;
286 int num;
287 if (dim1) {
288 *dim1 = 1;
289 }
290 if (dim2) {
291 *dim2 = 1;
292 }
293 bp = strchr(name, '[');
294 if (!bp) {
295 return 0;
296 }
297 num = 0;
298 while (++bp < name+len-1) {
299 const char c = *bp;
300 if (c == ']') {
301 break;
302 }
303 if (c <= '9' && c >= '0') {
304 num *= 10;
305 num += (c - '0');
306 } else {
307 printf("array parse error.\n");
308 return 0;
309 }
310 }
311 if (dim2) {
312 *dim2 = num;
313 }
314
315 /* find second dim, if any. */
316 bp = strchr(bp, '[');
317 if (!bp) {
318 return 1; /* at least we got the first dim. */
319 }
320 num = 0;
321 while (++bp < name+len-1) {
322 const char c = *bp;
323 if (c == ']') {
324 break;
325 }
326 if (c <= '9' && c >= '0') {
327 num *= 10;
328 num += (c - '0');
329 } else {
330 printf("array2 parse error.\n");
331 return 1;
332 }
333 }
334 if (dim1) {
335 if (dim2) {
336 *dim1 = *dim2;
337 *dim2 = num;
338 } else {
339 *dim1 = num;
340 }
341 }
342
343 return 1;
344 }
345
346
347 // ----------------------------------------------------- //
348 void bDNA::init(char *data, int len, bool swap)
349 {
350 int *intPtr=0;short *shtPtr=0;
351 char *cp = 0;int dataLen =0;long nr=0;
352 intPtr = (int*)data;
353
354 /*
355 SDNA (4 bytes) (magic number)
356 NAME (4 bytes)
357 <nr> (4 bytes) amount of names (int)
358 <string>
359 <string>
360 */
361
362 if (strncmp(data, "SDNA", 4)==0)
363 {
364 // skip ++ NAME
365 intPtr++; intPtr++;
366 }
367
368
369
370 // Parse names
371 if (swap)
372 {
373 *intPtr = ChunkUtils::swapInt(*intPtr);
374 }
375 dataLen = *intPtr;
376 intPtr++;
377
378 cp = (char*)intPtr;
379 int i;
380 for ( i=0; i<dataLen; i++)
381 {
382 bNameInfo info;
383 info.m_name = cp;
384 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
385 name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
386 m_Names.push_back(info);
387 while (*cp)cp++;
388 cp++;
389 }
390
391
392 {
393 nr= (long)cp;
394 //long mask=3;
395 nr= ((nr+3)&~3)-nr;
396 while (nr--)
397 {
398 cp++;
399 }
400 }
401
402
403 /*
404 TYPE (4 bytes)
405 <nr> amount of types (int)
406 <string>
407 <string>
408 */
409
410 intPtr = (int*)cp;
411 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
412
413 if (swap)
414 {
415 *intPtr = ChunkUtils::swapInt(*intPtr);
416 }
417 dataLen = *intPtr;
418 intPtr++;
419
420 cp = (char*)intPtr;
421 for ( i=0; i<dataLen; i++)
422 {
423 mTypes.push_back(cp);
424 while (*cp)cp++;
425 cp++;
426 }
427
428 {
429 nr= (long)cp;
430 // long mask=3;
431 nr= ((nr+3)&~3)-nr;
432 while (nr--)
433 {
434 cp++;
435 }
436 }
437
438
439 /*
440 TLEN (4 bytes)
441 <len> (short) the lengths of types
442 <len>
443 */
444
445 // Parse type lens
446 intPtr = (int*)cp;
447 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
448
449 dataLen = (int)mTypes.size();
450
451 shtPtr = (short*)intPtr;
452 for ( i=0; i<dataLen; i++, shtPtr++)
453 {
454 if (swap)
455 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
456 mTlens.push_back(shtPtr[0]);
457 }
458
459 if (dataLen & 1) shtPtr++;
460
461 /*
462 STRC (4 bytes)
463 <nr> amount of structs (int)
464 <typenr>
465 <nr_of_elems>
466 <typenr>
467 <namenr>
468 <typenr>
469 <namenr>
470 */
471
472 intPtr = (int*)shtPtr;
473 cp = (char*)intPtr;
474 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
475
476 if (swap)
477 {
478 *intPtr = ChunkUtils::swapInt(*intPtr);
479 }
480 dataLen = *intPtr;
481 intPtr++;
482
483
484 shtPtr = (short*)intPtr;
485 for ( i=0; i<dataLen; i++)
486 {
487 mStructs.push_back (shtPtr);
488 if (swap)
489 {
490 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
491 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
492
493 int len = shtPtr[1];
494 shtPtr+= 2;
495
496 for (int a=0; a<len; a++, shtPtr+=2)
497 {
498 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
499 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
500 }
501 }
502 else
503 shtPtr+= (2*shtPtr[1])+2;
504 }
505
506
507 // build reverse lookups
508 for ( i=0; i<(int)mStructs.size(); i++)
509 {
510 short *strc = mStructs.at(i);
511 if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
512 {
513 mPtrLen = mTlens[strc[0]]/2;
514 }
515
516 mStructReverse.insert(strc[0], i);
517 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
518 }
519 }
520
521
522 // ----------------------------------------------------- //
523 int bDNA::getArraySize(char* string)
524 {
525 int ret = 1;
526 int len = strlen(string);
527
528
529 char* next = 0;
530 for (int i=0; i<len; i++)
531 {
532 char c = string[i];
533
534 if (c == '[')
535 next = &string[i+1];
536 else if (c==']')
537 if (next)
538 ret *= atoi(next);
539 }
540
541 // print (string << ' ' << ret);
542 return ret;
543 }
544
545
546 void bDNA::dumpTypeDefinitions()
547 {
548 int i;
549
550 int numTypes = mTypes.size();
551
552 for (i=0;i<numTypes;i++)
553 {
554
555 }
556
557 for ( i=0; i<(int)mStructs.size(); i++)
558 {
559 int totalBytes=0;
560 short *oldStruct = mStructs[i];
561
562 int oldLookup = getReverseType(oldStruct[0]);
563 if (oldLookup == -1)
564 {
565 mCMPFlags[i] = FDF_NONE;
566 continue;
567 }
568
569 short* newStruct = mStructs[oldLookup];
570 char* typeName = mTypes[newStruct[0]];
571 printf("%3d: %s ",i,typeName);
572
573 //char *name = mNames[oldStruct[1]];
574 int len = oldStruct[1];
575 printf(" (%d fields) ",len);
576 oldStruct+=2;
577
578 printf("{");
579 int j;
580 for (j=0; j<len; ++j,oldStruct+=2) {
581 const char* name = m_Names[oldStruct[1]].m_name;
582 printf("%s %s", mTypes[oldStruct[0]],name);
583 int elemNumBytes= 0;
584 int arrayDimensions = getArraySizeNew(oldStruct[1]);
585
586 if (m_Names[oldStruct[1]].m_isPointer)
587 {
588 elemNumBytes = VOID_IS_8 ? 8 : 4;
589 } else
590 {
591 elemNumBytes = getLength(oldStruct[0]);
592 }
593 printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
594
595 if (j == len-1) {
596 printf(";}");
597 } else {
598 printf("; ");
599 }
600 totalBytes+=elemNumBytes*arrayDimensions;
601 }
602 printf("\ntotalBytes=%d\n\n",totalBytes);
603
604 }
605
606
607
608 #if 0
609 /* dump out display of types and their sizes */
610 for (i=0; i<bf->types_count; ++i) {
611 /* if (!bf->types[i].is_struct)*/
612 {
613 printf("%3d: sizeof(%s%s)=%d",
614 i,
615 bf->types[i].is_struct ? "struct " : "atomic ",
616 bf->types[i].name, bf->types[i].size);
617 if (bf->types[i].is_struct) {
618 int j;
619 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
620 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
621 printf("%s %s",
622 bf->types[bf->types[i].fieldtypes[j]].name,
623 bf->names[bf->types[i].fieldnames[j]]);
624 if (j == bf->types[i].fieldtypes_count-1) {
625 printf(";}");
626 } else {
627 printf("; ");
628 }
629 }
630 }
631 printf("\n\n");
632
633 }
634 }
635 #endif
636
637 }
638
639
640
641
642 //eof
643
644
bParse::bDNA::bDNA
bDNA()
Definition: bDNA.cpp:31
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:268
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
btAlignedObjectArray::at
const T & at(int n) const
Definition: btAlignedObjectArray.h:154
bParse::bDNA::getNumStructs
int getNumStructs()
Definition: bDNA.cpp:105
bParse::bDNA::getName
char * getName(int ind)
Definition: bDNA.cpp:50
bParse::bDNA::dumpTypeDefinitions
void dumpTypeDefinitions()
Definition: bDNA.cpp:546
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
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:149
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:277
bParse::bNameInfo::m_name
char * m_name
Definition: bDNA.h:26
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:269
bParse::bDNA::getArraySize
int getArraySize(char *str)
Definition: bDNA.cpp:523
bChunk.h
btHashMap::find
const Value * find(const Key &key) const
Definition: btHashMap.h:402
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:212
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:348
bParse::bDNA::flagEqual
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
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