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;long nr=0;
353 intPtr = (int*)data;
354
355 /*
356 SDNA (4 bytes) (magic number)
357 NAME (4 bytes)
358 <nr> (4 bytes) amount of names (int)
359 <string>
360 <string>
361 */
362
363 if (strncmp(data, "SDNA", 4)==0)
364 {
365 // skip ++ NAME
366 intPtr++; intPtr++;
367 }
368
369
370
371 // Parse names
372 if (swap)
373 {
374 *intPtr = ChunkUtils::swapInt(*intPtr);
375 }
376 dataLen = *intPtr;
377 intPtr++;
378
379 cp = (char*)intPtr;
380 int i;
381 for ( i=0; i<dataLen; i++)
382 {
383 bNameInfo info;
384 info.m_name = cp;
385 info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
386 name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
387 m_Names.push_back(info);
388 while (*cp)cp++;
389 cp++;
390 }
391
392
393
394 cp = btAlignPointer(cp,4);
395
396 /*
397 TYPE (4 bytes)
398 <nr> amount of types (int)
399 <string>
400 <string>
401 */
402
403 intPtr = (int*)cp;
404 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
405
406 if (swap)
407 {
408 *intPtr = ChunkUtils::swapInt(*intPtr);
409 }
410 dataLen = *intPtr;
411 intPtr++;
412
413 cp = (char*)intPtr;
414 for ( i=0; i<dataLen; i++)
415 {
416 mTypes.push_back(cp);
417 while (*cp)cp++;
418 cp++;
419 }
420
421 cp = btAlignPointer(cp,4);
422
423 /*
424 TLEN (4 bytes)
425 <len> (short) the lengths of types
426 <len>
427 */
428
429 // Parse type lens
430 intPtr = (int*)cp;
431 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
432
433 dataLen = (int)mTypes.size();
434
435 shtPtr = (short*)intPtr;
436 for ( i=0; i<dataLen; i++, shtPtr++)
437 {
438 if (swap)
439 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
440 mTlens.push_back(shtPtr[0]);
441 }
442
443 if (dataLen & 1) shtPtr++;
444
445 /*
446 STRC (4 bytes)
447 <nr> amount of structs (int)
448 <typenr>
449 <nr_of_elems>
450 <typenr>
451 <namenr>
452 <typenr>
453 <namenr>
454 */
455
456 intPtr = (int*)shtPtr;
457 cp = (char*)intPtr;
458 assert(strncmp(cp, "STRC", 4)==0); intPtr++;
459
460 if (swap)
461 {
462 *intPtr = ChunkUtils::swapInt(*intPtr);
463 }
464 dataLen = *intPtr;
465 intPtr++;
466
467
468 shtPtr = (short*)intPtr;
469 for ( i=0; i<dataLen; i++)
470 {
471 mStructs.push_back (shtPtr);
472 if (swap)
473 {
474 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
475 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
476
477 int len = shtPtr[1];
478 shtPtr+= 2;
479
480 for (int a=0; a<len; a++, shtPtr+=2)
481 {
482 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
483 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
484 }
485 }
486 else
487 shtPtr+= (2*shtPtr[1])+2;
488 }
489
490
491 // build reverse lookups
492 for ( i=0; i<(int)mStructs.size(); i++)
493 {
494 short *strc = mStructs.at(i);
495 if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
496 {
497 mPtrLen = mTlens[strc[0]]/2;
498 }
499
500 mStructReverse.insert(strc[0], i);
501 mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
502 }
503 }
504
505
506 // ----------------------------------------------------- //
507 int bDNA::getArraySize(char* string)
508 {
509 int ret = 1;
510 int len = strlen(string);
511
512
513 char* next = 0;
514 for (int i=0; i<len; i++)
515 {
516 char c = string[i];
517
518 if (c == '[')
519 next = &string[i+1];
520 else if (c==']')
521 if (next)
522 ret *= atoi(next);
523 }
524
525 // print (string << ' ' << ret);
526 return ret;
527 }
528
529
530 void bDNA::dumpTypeDefinitions()
531 {
532 int i;
533
534 int numTypes = mTypes.size();
535
536 for (i=0;i<numTypes;i++)
537 {
538
539 }
540
541 for ( i=0; i<(int)mStructs.size(); i++)
542 {
543 int totalBytes=0;
544 short *oldStruct = mStructs[i];
545
546 int oldLookup = getReverseType(oldStruct[0]);
547 if (oldLookup == -1)
548 {
549 mCMPFlags[i] = FDF_NONE;
550 continue;
551 }
552
553 short* newStruct = mStructs[oldLookup];
554 char* typeName = mTypes[newStruct[0]];
555 printf("%3d: %s ",i,typeName);
556
557 //char *name = mNames[oldStruct[1]];
558 int len = oldStruct[1];
559 printf(" (%d fields) ",len);
560 oldStruct+=2;
561
562 printf("{");
563 int j;
564 for (j=0; j<len; ++j,oldStruct+=2) {
565 const char* name = m_Names[oldStruct[1]].m_name;
566 printf("%s %s", mTypes[oldStruct[0]],name);
567 int elemNumBytes= 0;
568 int arrayDimensions = getArraySizeNew(oldStruct[1]);
569
570 if (m_Names[oldStruct[1]].m_isPointer)
571 {
572 elemNumBytes = VOID_IS_8 ? 8 : 4;
573 } else
574 {
575 elemNumBytes = getLength(oldStruct[0]);
576 }
577 printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
578
579 if (j == len-1) {
580 printf(";}");
581 } else {
582 printf("; ");
583 }
584 totalBytes+=elemNumBytes*arrayDimensions;
585 }
586 printf("\ntotalBytes=%d\n\n",totalBytes);
587
588 }
589
590
591
592 #if 0
593 /* dump out display of types and their sizes */
594 for (i=0; i<bf->types_count; ++i) {
595 /* if (!bf->types[i].is_struct)*/
596 {
597 printf("%3d: sizeof(%s%s)=%d",
598 i,
599 bf->types[i].is_struct ? "struct " : "atomic ",
600 bf->types[i].name, bf->types[i].size);
601 if (bf->types[i].is_struct) {
602 int j;
603 printf(", %d fields: { ", bf->types[i].fieldtypes_count);
604 for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
605 printf("%s %s",
606 bf->types[bf->types[i].fieldtypes[j]].name,
607 bf->names[bf->types[i].fieldnames[j]]);
608 if (j == bf->types[i].fieldtypes_count-1) {
609 printf(";}");
610 } else {
611 printf("; ");
612 }
613 }
614 }
615 printf("\n\n");
616
617 }
618 }
619 #endif
620
621 }
622
623
624
625
626 //eof
627
628
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:419
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:530
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:269
bParse::bDNA::getArraySize
int getArraySize(char *str)
Definition: bDNA.cpp:507
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:761
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