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