diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index abe0bd466..5e3cf576c 100644 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -1,4 +1,4 @@ -SUBDIRS( OpenGL BasicDemo Benchmarks Box2dDemo) +SUBDIRS( OpenGL BasicDemo Benchmarks Box2dDemo SerializeDemo ) #todo: re-enable the rest of the demos again diff --git a/Demos/OpenGL/GL_DialogWindow.cpp b/Demos/OpenGL/GL_DialogWindow.cpp index 94c7c45f1..5de8d4ce9 100644 --- a/Demos/OpenGL/GL_DialogWindow.cpp +++ b/Demos/OpenGL/GL_DialogWindow.cpp @@ -133,9 +133,9 @@ void GL_DialogWindow::draw(btScalar deltaTime) if (!m_screenWidth || !m_screenHeight) return; - m_dialogHorPos = m_collisionObject->getWorldTransform().getOrigin()[0]+m_screenWidth/2-m_dialogWidth/2; + m_dialogHorPos = int(m_collisionObject->getWorldTransform().getOrigin()[0]+m_screenWidth/2.f-m_dialogWidth/2.f); - m_dialogVertPos = m_collisionObject->getWorldTransform().getOrigin()[1]+m_screenHeight/2-m_dialogHeight/2; + m_dialogVertPos = int(m_collisionObject->getWorldTransform().getOrigin()[1]+m_screenHeight/2.f-m_dialogHeight/2.f); saveOpenGLState(); //drawRect(m_dialogHorPos,m_dialogVertPos,m_dialogHorPos+m_dialogWidth,m_dialogVertPos+m_dialogHeight,0xa6000000); @@ -273,8 +273,8 @@ void GL_TextControl::draw(int& parentHorPos,int& parentVertPos,btScalar deltaTim void GL_ToggleControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime) { - int controlHorPos = m_toggleBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2;//-m_parentWindow->getDialogWidth()/2; - int controlVertPos = m_toggleBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2;//-m_parentWindow->getDialogHeight()/2; + int controlHorPos = int(m_toggleBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2); + int controlVertPos = int(m_toggleBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2); int parentHorPos = controlHorPos-8; int parentVertPos = controlVertPos-8; @@ -308,8 +308,8 @@ void GL_ToggleControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar delt void GL_SliderControl::draw(int& parentHorPos2,int& parentVertPos2,btScalar deltaTime) { - int controlHorPos = m_sliderBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2; - int controlVertPos = m_sliderBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2; + int controlHorPos = int(m_sliderBody->getWorldTransform().getOrigin()[0]+m_parentWindow->getScreenWidth()/2); + int controlVertPos = int(m_sliderBody->getWorldTransform().getOrigin()[1]+m_parentWindow->getScreenHeight()/2); int parentHorPos = controlHorPos-8; int parentVertPos = controlVertPos-8; diff --git a/Demos/OpenGL/GL_ShapeDrawer.cpp b/Demos/OpenGL/GL_ShapeDrawer.cpp index 262dd9e37..e05a47373 100644 --- a/Demos/OpenGL/GL_ShapeDrawer.cpp +++ b/Demos/OpenGL/GL_ShapeDrawer.cpp @@ -337,9 +337,9 @@ void GL_ShapeDrawer::drawCylinder(float radius,float halfHeight, int upAxis) gluDisk(quadObj,0,radius,15, 10); gluCylinder(quadObj, radius, radius, 2.f*halfHeight, 15, 10); - glTranslatef(0.0, 0.0, 2.*halfHeight); - glRotatef(-180.0, 0.0, 1.0, 0.0); - gluDisk(quadObj,0,radius,15, 10); + glTranslatef(0.0f, 0.0f, 2.f*halfHeight); + glRotatef(-180.0f, 0.0f, 1.0f, 0.0f); + gluDisk(quadObj,0.f,radius,15, 10); glPopMatrix(); gluDeleteQuadric(quadObj); @@ -392,9 +392,9 @@ void renderSquareA(float x, float y, float z) { glBegin(GL_LINE_LOOP); glVertex3f(x, y, z); - glVertex3f(x + 10., y, z); - glVertex3f(x + 10., y + 10., z); - glVertex3f(x, y + 10., z); + glVertex3f(x + 10.f, y, z); + glVertex3f(x + 10.f, y + 10.f, z); + glVertex3f(x, y + 10.f, z); glEnd(); } @@ -523,7 +523,7 @@ void GL_ShapeDrawer::drawOpenGL(btScalar* m, const btCollisionShape* shape, cons glMatrixMode(GL_TEXTURE); glLoadIdentity(); - glScalef(0.025,0.025,0.025); + glScalef(0.025f,0.025f,0.025f); } diff --git a/Demos/OpenGL/Win32AppMain.cpp b/Demos/OpenGL/Win32AppMain.cpp index 7c5340284..89c028d1c 100644 --- a/Demos/OpenGL/Win32AppMain.cpp +++ b/Demos/OpenGL/Win32AppMain.cpp @@ -1,7 +1,7 @@ #ifdef _WINDOWS /* Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/Demos/SerializeDemo/CMakeLists.txt b/Demos/SerializeDemo/CMakeLists.txt new file mode 100644 index 000000000..9702daf82 --- /dev/null +++ b/Demos/SerializeDemo/CMakeLists.txt @@ -0,0 +1,57 @@ +# This is basically the overall name of the project in Visual Studio this is the name of the Solution File + + +# For every executable you have with a main method you should have an add_executable line below. +# For every add executable line you should list every .cpp and .h file you have associated with that executable. + + +# This is the variable for Windows. I use this to define the root of my directory structure. +SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut) + +# You shouldn't have to modify anything below this line +######################################################## + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL +) + + +SET(SERIALIZE_FILES + bChunk.cpp + bChunk.h + bCommon.h + bDefines.h + bDNA.cpp + bDNA.h + bFile.cpp + bFile.h + btBulletFile.cpp + btBulletFile.h +) + +IF (USE_GLUT) + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppSerializeDemo + main.cpp + $(SERIALIZE_FILES) + SerializeDemo.cpp + SerializeDemo.h + ) +ELSE (USE_GLUT) + + LINK_LIBRARIES( + OpenGLSupport BulletDynamics BulletCollision LinearMath ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} + ) + + ADD_EXECUTABLE(AppSerializeDemo + WIN32 + ../OpenGL/Win32AppMain.cpp + Win32SerializeDemo.cpp + ${SERIALIZE_FILES} + SerializeDemo.cpp + SerializeDemo.h + ) +ENDIF (USE_GLUT) \ No newline at end of file diff --git a/Demos/SerializeDemo/SerializeDemo.cpp b/Demos/SerializeDemo/SerializeDemo.cpp new file mode 100644 index 000000000..0674abeac --- /dev/null +++ b/Demos/SerializeDemo/SerializeDemo.cpp @@ -0,0 +1,298 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#define TEST_SERIALIZATION 1 + +///create 125 (5x5x5) dynamic object +#define ARRAY_SIZE_X 5 +#define ARRAY_SIZE_Y 5 +#define ARRAY_SIZE_Z 5 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X -5 +#define START_POS_Y -5 +#define START_POS_Z -3 + +#include "SerializeDemo.h" +#include "GlutStuff.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#ifdef TEST_SERIALIZATION +#include "LinearMath/btSerializer.h" +#include "btBulletFile.h" + +#endif //TEST_SERIALIZATION + +#include //printf debugging + + +void SerializeDemo::clientMoveAndDisplay() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //simple dynamics world doesn't handle fixed-time-stepping + float ms = getDeltaTimeMicroseconds(); + + ///step the simulation + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(ms / 1000000.f); + //optional but useful: debug drawing + m_dynamicsWorld->debugDrawWorld(); + } + + renderme(); + + glFlush(); + + swapBuffers(); + +} + + + +void SerializeDemo::displayCallback(void) { + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderme(); + + //optional but useful: debug drawing to detect problems + if (m_dynamicsWorld) + m_dynamicsWorld->debugDrawWorld(); + + glFlush(); + swapBuffers(); +} + + + +void SerializeDemo::setupEmptyDynamicsWorld() +{ + ///collision configuration contains default setup for memory, collision setup + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + +} + +void SerializeDemo::initPhysics() +{ + setTexturing(true); + setShadows(true); + + setCameraDistance(btScalar(SCALING*50.)); + + setupEmptyDynamicsWorld(); + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); +// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + { + btScalar mass(0.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance + + btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1)); + //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); + m_collisionShapes.push_back(colShape); + + /// Create Dynamic Objects + btTransform startTransform; + startTransform.setIdentity(); + + btScalar mass(1.f); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + colShape->calculateLocalInertia(mass,localInertia); + + float start_x = START_POS_X - ARRAY_SIZE_X/2; + float start_y = START_POS_Y; + float start_z = START_POS_Z - ARRAY_SIZE_Z/2; + + for (int k=0;ksetActivationState(ISLAND_SLEEPING); + + m_dynamicsWorld->addRigidBody(body); + body->setActivationState(ISLAND_SLEEPING); + } + } + } + } + + + clientResetScene(); + + +#ifdef TEST_SERIALIZATION + //test serializing this + + int maxSerializeBufferSize = 1024*1024*5; + + btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize); + m_dynamicsWorld->serialize(serializer); + + FILE* f2 = fopen("testFile.bullet","wb"); + fwrite(serializer->m_buffer,serializer->m_currentSize,1,f2); + fclose(f2); + + exitPhysics(); + + //now try again from the loaded file + setupEmptyDynamicsWorld(); + + bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile("testFile.bullet"); + bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0; + bool verboseDumpAllTypes = true; + if (ok) + bulletFile2->parse(verboseDumpAllTypes); + + if (verboseDumpAllTypes) + { + bulletFile2->dumpChunks(bulletFile2->getFileDNA()); + } + + int i; + + for (i=0;im_collisionShapes.size();i++) + { + btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i]; + printf("bla"); + } + for (i=0;im_rigidBodies.size();i++) + { + btRigidBodyData* colObjData = (btRigidBodyData*)bulletFile2->m_rigidBodies[i]; + printf("bla"); + } + + for (i=0;im_collisionObjects.size();i++) + { + btCollisionObjectData* colObjData = (btCollisionObjectData*)bulletFile2->m_collisionObjects[i]; + printf("bla"); + } + + +#endif //TEST_SERIALIZATION + +} + + +void SerializeDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;j m_collisionShapes; + + btBroadphaseInterface* m_broadphase; + + btCollisionDispatcher* m_dispatcher; + + btConstraintSolver* m_solver; + + btDefaultCollisionConfiguration* m_collisionConfiguration; + + public: + + SerializeDemo() + { + } + virtual ~SerializeDemo() + { + exitPhysics(); + } + void initPhysics(); + + void setupEmptyDynamicsWorld(); + + void exitPhysics(); + + virtual void clientMoveAndDisplay(); + + virtual void displayCallback(); + + static DemoApplication* Create() + { + SerializeDemo* demo = new SerializeDemo; + demo->myinit(); + demo->initPhysics(); + return demo; + } + + +}; + +#endif //SERIALIZE_DEMO_H + diff --git a/Demos/SerializeDemo/Win32SerializeDemo.cpp b/Demos/SerializeDemo/Win32SerializeDemo.cpp new file mode 100644 index 000000000..e9f539c54 --- /dev/null +++ b/Demos/SerializeDemo/Win32SerializeDemo.cpp @@ -0,0 +1,25 @@ +#ifdef _WINDOWS +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SerializeDemo.h" + +///The 'createDemo' function is called from Bullet/Demos/OpenGL/Win32AppMain.cpp to instantiate this particular demo +DemoApplication* createDemo() +{ + return new SerializeDemo(); +} + +#endif diff --git a/Demos/SerializeDemo/bChunk.cpp b/Demos/SerializeDemo/bChunk.cpp new file mode 100644 index 000000000..df6771a21 --- /dev/null +++ b/Demos/SerializeDemo/bChunk.cpp @@ -0,0 +1,188 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include +#include "bChunk.h" +#include "bDefines.h" +#include "bFile.h" + +using namespace bParse; + + +// ----------------------------------------------------- // +short ChunkUtils::swapShort(short sht) +{ + SWITCH_SHORT(sht); + return sht; +} + +// ----------------------------------------------------- // +int ChunkUtils::swapInt(int inte) +{ + SWITCH_INT(inte); + return inte; +} + +// ----------------------------------------------------- // +long64 ChunkUtils::swapLong64(long64 lng) +{ + SWITCH_LONGINT(lng); + return lng; +} + +// ----------------------------------------------------- // +int ChunkUtils::getOffset(int flags) +{ + // if the file is saved in a + // different format, get the + // file's chunk size + int res = CHUNK_HEADER_LEN; + + if (VOID_IS_8) + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr4); + } + else + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr8); + } + return res; +} + + +// ----------------------------------------------------- // +int ChunkUtils::getNextBlock(bChunkInd *dataChunk, char *dataPtr, const int flags) +{ + bool swap = false; + bool varies = false; + + if (flags &FD_ENDIAN_SWAP) swap = true; + if (flags &FD_BITS_VARIES) varies = true; + + if (VOID_IS_8) + { + if (varies) + { + bChunkPtr4 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr4)); + + + bChunkPtr8 chunk; + + chunk.code = head.code; + chunk.len = head.len; + chunk.old = head.old; + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr8 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr8)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + else + { + if (varies) + { + bChunkPtr8 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr8)); + + + bChunkPtr4 chunk; + chunk.code = head.code; + chunk.len = head.len; + + long64 oldPtr =0; + + memcpy(&oldPtr, &head.old, 8); + chunk.old = (int)(oldPtr >> 3); + + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr4 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr4)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + + if (dataChunk->len < 0) + return -1; + +#if 0 + print ("----------"); + print (dataChunk->code); + print (dataChunk->len); + print (dataChunk->old); + print (dataChunk->dna_nr); + print (dataChunk->nr); +#endif + return (dataChunk->len+getOffset(flags)); +} + + + +//eof diff --git a/Demos/SerializeDemo/bChunk.h b/Demos/SerializeDemo/bChunk.h new file mode 100644 index 000000000..7fe621e7c --- /dev/null +++ b/Demos/SerializeDemo/bChunk.h @@ -0,0 +1,85 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BCHUNK_H__ +#define __BCHUNK_H__ + + +#ifdef WIN32 + #define long64 __int64 +#else + #define long64 long long +#endif + + +namespace bParse { + + + // ----------------------------------------------------- // + class bChunkPtr4 + { + public: + bChunkPtr4(){} + int code; + int len; + int old; + int dna_nr; + int nr; + }; + + // ----------------------------------------------------- // + class bChunkPtr8 + { + public: + bChunkPtr8(){} + int code, len; + long64 old; + int dna_nr, nr; + }; + + // ----------------------------------------------------- // + class bChunkInd + { + public: + bChunkInd(){} + int code, len; + void *oldPtr; + int dna_nr, nr; + }; + + + // ----------------------------------------------------- // + class ChunkUtils + { + public: + // buffer offset util + static int getNextBlock(bChunkInd *dataChunk, char *dataPtr, const int flags); + + // file chunk offset + static int getOffset(int flags); + + // endian utils + static short swapShort(short sht); + static int swapInt(int inte); + static long64 swapLong64(long64 lng); + + }; + + + const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd))); + const bool VOID_IS_8 = ((sizeof(void*)==8)); +} + +#endif//__BCHUNK_H__ diff --git a/Demos/SerializeDemo/bCommon.h b/Demos/SerializeDemo/bCommon.h new file mode 100644 index 000000000..4b9dfc4ab --- /dev/null +++ b/Demos/SerializeDemo/bCommon.h @@ -0,0 +1,39 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BCOMMON_H__ +#define __BCOMMON_H__ + + +#include +//#include "bLog.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btHashMap.h" + +namespace bParse { + + class bMain; + class bFileData; + class bFile; + class bDNA; + + // delete void* undefined + typedef struct bStructHandle {int unused;}bStructHandle; + typedef btAlignedObjectArray bListBasePtr; + typedef btHashMap bPtrMap; +} + + +#endif//__BCOMMON_H__ diff --git a/Demos/SerializeDemo/bDNA.cpp b/Demos/SerializeDemo/bDNA.cpp new file mode 100644 index 000000000..dffc76bac --- /dev/null +++ b/Demos/SerializeDemo/bDNA.cpp @@ -0,0 +1,624 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include + +#include "bDNA.h" +#include "bChunk.h" +#include +#include +#include + +using namespace bParse; + + +// ----------------------------------------------------- // +bDNA::bDNA() + : mPtrLen(0) +{ + // -- +} + +// ----------------------------------------------------- // +bDNA::~bDNA() +{ + // -- +} + +// ----------------------------------------------------- // +bool bDNA::lessThan(bDNA *file) +{ + return ( m_Names.size() < file->m_Names.size()); +} + +// ----------------------------------------------------- // +char *bDNA::getName(int ind) +{ + assert(ind <= (int)m_Names.size()); + return m_Names[ind].m_name; +} + + +// ----------------------------------------------------- // +char *bDNA::getType(int ind) +{ + assert(ind<= (int)mTypes.size()); + return mTypes[ind]; +} + + +// ----------------------------------------------------- // +short *bDNA::getStruct(int ind) +{ + assert(ind <= (int)mStructs.size()); + return mStructs[ind]; +} + + +// ----------------------------------------------------- // +short bDNA::getLength(int ind) +{ + assert(ind <= (int)mTlens.size()); + return mTlens[ind]; +} + + +// ----------------------------------------------------- // +int bDNA::getReverseType(short type) +{ + + int* intPtr = mStructReverse.find(type); + if (intPtr) + return *intPtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getReverseType(const char *type) +{ + + btHashString key(type); + int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getNumStructs() +{ + return (int)mStructs.size(); +} + +// ----------------------------------------------------- // +bool bDNA::flagNotEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + int flag = mCMPFlags[dna_nr]; + return flag == FDF_STRUCT_EQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagNone(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_NONE; +} + +// ----------------------------------------------------- // +int bDNA::getPointerSize() +{ + return mPtrLen; +} + +// ----------------------------------------------------- // +void bDNA::initRecurseCmpFlags(int iter) +{ + // iter is FDF_STRUCT_NEQU + + short *oldStrc = mStructs[iter]; + short type = oldStrc[0]; + + for (int i=0; i<(int)mStructs.size(); i++) + { + if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU ) + { + short *curStruct = mStructs[i]; + int eleLen = curStruct[1]; + curStruct+=2; + + for (int j=0; jgetReverseType(typeName); + if (newLookup == -1) + { + mCMPFlags[i] = FDF_NONE; + continue; + } + short *curStruct = memDNA->mStructs[newLookup]; +#else + // memory for file + + if (oldLookup < memDNA->mStructs.size()) + { + short *curStruct = memDNA->mStructs[oldLookup]; +#endif + + + + // rebuild... + mCMPFlags[i] = FDF_STRUCT_NEQU; + +#if 1 + if (curStruct[1] == oldStruct[1]) + { + // type len same ... + if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]]) + { + bool isSame = true; + int elementLength = oldStruct[1]; + + + curStruct+=2; + oldStruct+=2; + + + for (int j=0; jmTypes[curStruct[0]])!=0) + { + isSame=false; + break; + } + + // name the same + if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0) + { + isSame=false; + break; + } + } + // flag valid == + if (isSame) + mCMPFlags[i] = FDF_STRUCT_EQU; + } + } +#endif + } + } + + + + + + // recurse in + for (int i=0; i<(int)mStructs.size(); i++) + { + if (mCMPFlags[i] == FDF_STRUCT_NEQU) + initRecurseCmpFlags(i); + } +} + + + + +static int name_is_array(char* name, int* dim1, int* dim2) { + int len = strlen(name); + /*fprintf(stderr,"[%s]",name);*/ + /*if (len >= 1) { + if (name[len-1] != ']') + return 1; + } + return 0;*/ + char *bp; + int num; + if (dim1) { + *dim1 = 1; + } + if (dim2) { + *dim2 = 1; + } + bp = strchr(name, '['); + if (!bp) { + return 0; + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array parse error.\n"); + return 0; + } + } + if (dim2) { + *dim2 = num; + } + + /* find second dim, if any. */ + bp = strchr(bp, '['); + if (!bp) { + return 1; /* at least we got the first dim. */ + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array2 parse error.\n"); + return 1; + } + } + if (dim1) { + if (dim2) { + *dim1 = *dim2; + *dim2 = num; + } else { + *dim1 = num; + } + } + + return 1; +} + + +// ----------------------------------------------------- // +void bDNA::init(char *data, int len, bool swap) +{ + int *intPtr=0;short *shtPtr=0; + char *cp = 0;int dataLen =0;long nr=0; + intPtr = (int*)data; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp(data, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + + + // Parse names + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + for (int i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + for (int i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for (int i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + assert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (swap) dataLen = ChunkUtils::swapInt(*intPtr); + else dataLen = *intPtr; + intPtr++; + + + shtPtr = (short*)intPtr; + for (int i=0; itypes_count; ++i) { + /* if (!bf->types[i].is_struct)*/ + { + printf("%3d: sizeof(%s%s)=%d", + i, + bf->types[i].is_struct ? "struct " : "atomic ", + bf->types[i].name, bf->types[i].size); + if (bf->types[i].is_struct) { + int j; + printf(", %d fields: { ", bf->types[i].fieldtypes_count); + for (j=0; jtypes[i].fieldtypes_count; ++j) { + printf("%s %s", + bf->types[bf->types[i].fieldtypes[j]].name, + bf->names[bf->types[i].fieldnames[j]]); + if (j == bf->types[i].fieldtypes_count-1) { + printf(";}"); + } else { + printf("; "); + } + } + } + printf("\n\n"); + + } + } +#endif + +} + + + + +//eof + + diff --git a/Demos/SerializeDemo/bDNA.h b/Demos/SerializeDemo/bDNA.h new file mode 100644 index 000000000..e2191d4e4 --- /dev/null +++ b/Demos/SerializeDemo/bDNA.h @@ -0,0 +1,109 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BDNA_H__ +#define __BDNA_H__ + + +#include "bCommon.h" + +namespace bParse { + + struct bNameInfo + { + char* m_name; + bool m_isPointer; + int m_dim0; + int m_dim1; + }; + + class bDNA + { + public: + bDNA(); + ~bDNA(); + + void init(char *data, int len, bool swap=false); + + int getArraySize(char* str); + int getArraySizeNew(short name) + { + const bNameInfo& nameInfo = m_Names[name]; + return nameInfo.m_dim0*nameInfo.m_dim1; + } + int getElementSize(short type, short name) + { + const bNameInfo& nameInfo = m_Names[name]; + int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1; + return size; + } + + int getNumNames() const + { + return m_Names.size(); + } + + char *getName(int ind); + char *getType(int ind); + short *getStruct(int ind); + short getLength(int ind); + int getReverseType(short type); + int getReverseType(const char *type); + + + int getNumStructs(); + + // + bool lessThan(bDNA* other); + + void initCmpFlags(bDNA *memDNA); + bool flagNotEqual(int dna_nr); + bool flagEqual(int dna_nr); + bool flagNone(int dna_nr); + + + int getPointerSize(); + + void dumpTypeDefinitions(); + + + private: + enum FileDNAFlags + { + FDF_NONE=0, + FDF_STRUCT_NEQU, + FDF_STRUCT_EQU + }; + + void initRecurseCmpFlags(int i); + + btAlignedObjectArray mCMPFlags; + + btAlignedObjectArray m_Names; + btAlignedObjectArray mTypes; + btAlignedObjectArray mStructs; + btAlignedObjectArray mTlens; + btHashMap mStructReverse; + btHashMap mTypeLookup; + + int mPtrLen; + + + + }; +} + + +#endif//__BDNA_H__ diff --git a/Demos/SerializeDemo/bDefines.h b/Demos/SerializeDemo/bDefines.h new file mode 100644 index 000000000..fcf065300 --- /dev/null +++ b/Demos/SerializeDemo/bDefines.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 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. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef __B_DEFINES_H__ +#define __B_DEFINES_H__ + + +// MISC defines, see BKE_global.h, BKE_utildefines.h +#define SIZEOFBLENDERHEADER 12 + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID2(c, d) ( (c)<<8 | (d) ) +# define MOST_SIG_BYTE 0 +# define BBIG_ENDIAN +#else +# define MAKE_ID2(c, d) ( (d)<<8 | (c) ) +# define MOST_SIG_BYTE 1 +# define BLITTLE_ENDIAN +#endif + +// ------------------------------------------------------------ +#define ID_SCE MAKE_ID2('S', 'C') +#define ID_LI MAKE_ID2('L', 'I') +#define ID_OB MAKE_ID2('O', 'B') +#define ID_ME MAKE_ID2('M', 'E') +#define ID_CU MAKE_ID2('C', 'U') +#define ID_MB MAKE_ID2('M', 'B') +#define ID_MA MAKE_ID2('M', 'A') +#define ID_TE MAKE_ID2('T', 'E') +#define ID_IM MAKE_ID2('I', 'M') +#define ID_IK MAKE_ID2('I', 'K') +#define ID_WV MAKE_ID2('W', 'V') +#define ID_LT MAKE_ID2('L', 'T') +#define ID_SE MAKE_ID2('S', 'E') +#define ID_LF MAKE_ID2('L', 'F') +#define ID_LA MAKE_ID2('L', 'A') +#define ID_CA MAKE_ID2('C', 'A') +#define ID_IP MAKE_ID2('I', 'P') +#define ID_KE MAKE_ID2('K', 'E') +#define ID_WO MAKE_ID2('W', 'O') +#define ID_SCR MAKE_ID2('S', 'R') +#define ID_VF MAKE_ID2('V', 'F') +#define ID_TXT MAKE_ID2('T', 'X') +#define ID_SO MAKE_ID2('S', 'O') +#define ID_SAMPLE MAKE_ID2('S', 'A') +#define ID_GR MAKE_ID2('G', 'R') +#define ID_ID MAKE_ID2('I', 'D') +#define ID_AR MAKE_ID2('A', 'R') +#define ID_AC MAKE_ID2('A', 'C') +#define ID_SCRIPT MAKE_ID2('P', 'Y') +#define ID_FLUIDSIM MAKE_ID2('F', 'S') +#define ID_NT MAKE_ID2('N', 'T') +#define ID_BR MAKE_ID2('B', 'R') + + +#define ID_SEQ MAKE_ID2('S', 'Q') +#define ID_CO MAKE_ID2('C', 'O') +#define ID_PO MAKE_ID2('A', 'C') +#define ID_NLA MAKE_ID2('N', 'L') + +#define ID_VS MAKE_ID2('V', 'S') +#define ID_VN MAKE_ID2('V', 'N') + + +// ------------------------------------------------------------ +#define FORM MAKE_ID('F','O','R','M') +#define DDG1 MAKE_ID('3','D','G','1') +#define DDG2 MAKE_ID('3','D','G','2') +#define DDG3 MAKE_ID('3','D','G','3') +#define DDG4 MAKE_ID('3','D','G','4') +#define GOUR MAKE_ID('G','O','U','R') +#define BLEN MAKE_ID('B','L','E','N') +#define DER_ MAKE_ID('D','E','R','_') +#define V100 MAKE_ID('V','1','0','0') +#define DATA MAKE_ID('D','A','T','A') +#define GLOB MAKE_ID('G','L','O','B') +#define IMAG MAKE_ID('I','M','A','G') +#define TEST MAKE_ID('T','E','S','T') +#define USER MAKE_ID('U','S','E','R') + + +// ------------------------------------------------------------ +#define DNA1 MAKE_ID('D','N','A','1') +#define REND MAKE_ID('R','E','N','D') +#define ENDB MAKE_ID('E','N','D','B') +#define NAME MAKE_ID('N','A','M','E') +#define SDNA MAKE_ID('S','D','N','A') +#define TYPE MAKE_ID('T','Y','P','E') +#define TLEN MAKE_ID('T','L','E','N') +#define STRC MAKE_ID('S','T','R','C') + + +// ------------------------------------------------------------ +#define SWITCH_INT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_SHORT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_LONGINT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ + s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ + s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; } + +#endif//__B_DEFINES_H__ diff --git a/Demos/SerializeDemo/bFile.cpp b/Demos/SerializeDemo/bFile.cpp new file mode 100644 index 000000000..8cd58fea9 --- /dev/null +++ b/Demos/SerializeDemo/bFile.cpp @@ -0,0 +1,1040 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include "bFile.h" +#include "bCommon.h" +#include "bChunk.h" +#include "bDNA.h" +#include +#include +#include +#define SIZEOFBLENDERHEADER 12 +#define MAX_ARRAY_LENGTH 512 +using namespace bParse; + + +int numallocs = 0; + +// ----------------------------------------------------- // +bFile::bFile(const char *filename, const char headerString[7]) + : mOwnsBuffer(true), + mFileBuffer(0), + mFileLen(0), + mVersion(0), + mDataStart(0), + mFileDNA(0), + mMemoryDNA(0), + mFlags(FD_INVALID) +{ + for (int i=0;i<7;i++) + { + m_headerString[i] = headerString[i]; + } + + FILE *fp = fopen(filename, "rb"); + if (fp) + { + fseek(fp, 0L, SEEK_END); + mFileLen = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + mFileBuffer = (char*)malloc(mFileLen+1); + fread(mFileBuffer, mFileLen, 1, fp); + + fclose(fp); + + // + parseHeader(); + + } +} + +// ----------------------------------------------------- // +bFile::bFile( char *memoryBuffer, int len, const char headerString[7]) +: mOwnsBuffer(false), + mFileBuffer(0), + mFileLen(0), + mVersion(0), + mDataStart(0), + mFileDNA(0), + mMemoryDNA(0), + mFlags(FD_INVALID) +{ + for (int i=0;i<7;i++) + { + m_headerString[i] = headerString[i]; + } + mFileBuffer = memoryBuffer; + mFileLen = len; + + parseHeader(); + +} + + +// ----------------------------------------------------- // +bFile::~bFile() +{ + if (mOwnsBuffer && mFileBuffer) + { + free(mFileBuffer); + mFileBuffer = 0; + } + + + delete mMemoryDNA; + delete mFileDNA; +} + + + + + +// ----------------------------------------------------- // +void bFile::parseHeader() +{ + char *blenderBuf = mFileBuffer; + char header[SIZEOFBLENDERHEADER+1] ; + memcpy(header, blenderBuf, SIZEOFBLENDERHEADER); + header[SIZEOFBLENDERHEADER]='\0'; + + if (strncmp(header, m_headerString, 7)!=0) + { + printf ("Invalid blend file..."); + return; + } + + char *ver = header+9; + mVersion = atoi(ver); + if (mVersion <= 241) + printf ("Warning, %d not fully tested : <= 242\n", mVersion); + + + int endian= 1; + endian= ((char*)&endian)[0]; + + // swap ptr sizes... + if (header[7]=='-') + { + mFlags |= FD_FILE_64; + if (!VOID_IS_8) + mFlags |= FD_BITS_VARIES; + } + else if (VOID_IS_8) mFlags |= FD_BITS_VARIES; + + // swap endian... + if (header[8]=='V' && endian ==1) + mFlags |= FD_ENDIAN_SWAP; + else + if (endian==0) + mFlags |= FD_ENDIAN_SWAP; + + + printf (header); + printf ("\nsizeof(void*) == %d\n",sizeof(void*)); + const char* endStr = ((mFlags & FD_ENDIAN_SWAP)!=0) ? "yes" : "no"; + printf ("Swapping endian? %s\n",endStr); + const char* bitStr = (mFlags &FD_FILE_64)!=0 ? "64 bit" : "32bit"; + printf ("File format is %s\n",bitStr); + const char* varStr = (mFlags & FD_BITS_VARIES)!=0 ? "yes" : "no"; + printf ("Varing pointer sizes? %s\n",varStr); + + + mFlags |= FD_OK; +} + +// ----------------------------------------------------- // +bool bFile::ok() +{ + return (mFlags &FD_OK)!=0; +} + +// ----------------------------------------------------- // +void bFile::parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength) +{ + if ( (mFlags &FD_OK) ==0) + return; + + char *blenderData = mFileBuffer; + int sdnaPos=0; + + char *tempBuffer = blenderData; + for (int i=0; iinit(blenderData+sdnaPos, mFileLen-sdnaPos, (mFlags & FD_ENDIAN_SWAP)!=0); + + if (verboseDumpAllTypes) + { + mFileDNA->dumpTypeDefinitions(); + } + + mMemoryDNA = new bDNA(); + mMemoryDNA->init(memDna,memDnaLength); + + + + + ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files + if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames()) + { + mFlags |= FD_VERSION_VARIES; + printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform"); + } + + // as long as it kept up to date it will be ok!! + if (mMemoryDNA->lessThan(mFileDNA)) + { + printf ("Warning, file DNA is newer than built in."); + } + + mFileDNA->initCmpFlags(mMemoryDNA); + + parseData(); + + resolvePointers(verboseDumpAllTypes);//verboseDumpAllBlocks); + + updateOldPointers(); + + printf("numAllocs = %d\n",numallocs); +} + + + +// ----------------------------------------------------- // +void bFile::swap(char *head, bChunkInd& dataChunk) +{ + char *data = head; + short *strc = mFileDNA->getStruct(dataChunk.dna_nr); + int len = mFileDNA->getLength(strc[0]); + + for (int i=0; iflagEqual(dataChunk.dna_nr)) + { + // Ouch! need to rebuild the struct + short *oldStruct,*curStruct; + char *oldType, *newType; + int oldLen, curLen, reverseOld; + + + oldStruct = mFileDNA->getStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + oldLen = mFileDNA->getLength(oldStruct[0]); + + ///don't try to convert Link block data, just memcpy it. Other data can be converted. + if (strcmp("Link",oldType)!=0) + { + reverseOld = mMemoryDNA->getReverseType(oldType); + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + curLen = mMemoryDNA->getLength(curStruct[0]); + + + + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + numallocs++; + // numBlocks * length + char *dataAlloc = new char[(dataChunk.nr*curLen)+1]; + memset(dataAlloc, 0, (dataChunk.nr*curLen)+1); + + // track allocated + addDataBlock(dataAlloc); + + char *cur = dataAlloc; + char *old = head; + for (int block=0; blockgetStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + printf("%s equal structure, just memcpy\n",oldType); +#endif // + } + + + char *dataAlloc = new char[(dataChunk.len)+1]; + memset(dataAlloc, 0, dataChunk.len+1); + + + // track allocated + addDataBlock(dataAlloc); + + memcpy(dataAlloc, head, dataChunk.len); + return dataAlloc; + +} + + +// ----------------------------------------------------- // +void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers) +{ + if (old_dna == -1) return; + if (new_dna == -1) return; + + //disable this, because we need to fixup pointers/ListBase + if (0)//mFileDNA->flagEqual(old_dna)) + { + short *strc = mFileDNA->getStruct(old_dna); + int len = mFileDNA->getLength(strc[0]); + + memcpy(strcPtr, dtPtr, len); + return; + } + + // Ok, now build the struct + char *memType, *memName, *cpc, *cpo; + short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct; + int elementLength, size, revType, old_nr, new_nr, fpLen; + short firstStructType; + + + // File to memory lookup + memoryStruct = mMemoryDNA->getStruct(new_dna); + fileStruct = mFileDNA->getStruct(old_dna); + firstStruct = fileStruct; + + + filePtrOld = fileStruct; + firstStructType = mMemoryDNA->getStruct(0)[0]; + + // Get number of elements + elementLength = memoryStruct[1]; + memoryStruct+=2; + + cpc = strcPtr; cpo = 0; + for (int ele=0; elegetType(memoryStruct[0]); + memName = mMemoryDNA->getName(memoryStruct[1]); + + + size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]); + revType = mMemoryDNA->getReverseType(memoryStruct[0]); + + if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*') + { + cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld); + if (cpo) + { + old_nr = mFileDNA->getReverseType(memType); + new_nr = revType; + fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]); + + + parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers); + cpc+=size; + cpo+=fpLen; + } + else + cpc+=size; + } + else + { + getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers); + cpc+=size; + } + + } +} + +// ----------------------------------------------------- // +static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData) +{ +#define getEle(value, current, type, cast, size, ptr)\ + if (strcmp(current, type)==0)\ + {\ + value = (*(cast*)ptr);\ + ptr += size;\ + } + +#define setEle(value, current, type, cast, size, ptr)\ + if (strcmp(current, type)==0)\ + {\ + (*(cast*)ptr) = (cast)value;\ + ptr += size;\ + } + double value = 0.0; + + for (int i=0; i3 && type <8) + { + char c; + char *cp = data; + for (int i=0; igetPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + + if (!src && !dst) + return; + + if (ptrFile == ptrMem) + memcpy(dst, src, ptrMem); + else if (ptrMem==4 && ptrFile==8) + { + long64 longValue = *((long64*)src); + *((int*)dst) = (int)(longValue>>3); + } + else if (ptrMem==8 && ptrFile==4) + *((long64*)dst)= *((int*)src); + else + { + printf ("%d %d\n", ptrFile,ptrMem); + assert(0 && "Invalid pointer len"); + } +} + +// ----------------------------------------------------- // +void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers) +{ + // find the matching memory dna data + // to the file being loaded. Fill the + // memory with the file data... + + int len = dna_addr[1]; + dna_addr+=2; + + for (int i=0; igetType(dna_addr[0]); + const char* name = mFileDNA->getName(dna_addr[1]); + + int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]); + + + if (strcmp(lookupName, name)==0) + { + //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str()); + int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]); + //assert(arrayLenold == arrayLen); + + if (name[0] == '*') + { + // cast pointers + int ptrFile = mFileDNA->getPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + + swapPtr(strcData, data); + + if (fixupPointers) + { + if (arrayLen > 1) + { + void **sarray = (void**)strcData; + void **darray = (void**)data; + + for (int a=0; agetStruct(old_nr); + int elementLength = old[1]; + old+=2; + + for (int i=0; igetType(old[0]); + char* name = mFileDNA->getName(old[1]); + int len = mFileDNA->getElementSize(old[0], old[1]); + + if (strcmp(lookupName, name)==0) + { + if (strcmp(type, lookupType)==0) + { + if (foundPos) + *foundPos = old; + return data; + } + return 0; + } + data+=len; + } + return 0; +} + + +// ----------------------------------------------------- // +void bFile::swapStruct(int dna_nr, char *data) +{ + if (dna_nr == -1) return; + + short *strc = mFileDNA->getStruct(dna_nr); + short *firstStrc = strc; + + int elementLen= strc[1]; + strc+=2; + + short first = mFileDNA->getStruct(0)[0]; + + char *buf = data; + for (int i=0; igetType(strc[0]); + char *name = mFileDNA->getName(strc[1]); + + int size = mFileDNA->getElementSize(strc[0], strc[1]); + if (strc[0] >= first && name[0]!='*') + { + int old_nr = mFileDNA->getReverseType(type); + swapStruct(old_nr,buf); + } + else + { + //int arrayLenOld = mFileDNA->getArraySize(name); + int arrayLen = mFileDNA->getArraySizeNew(strc[1]); + //assert(arrayLenOld == arrayLen); + + swapData(buf, strc[0], arrayLen); + } + buf+=size; + } +} + + + +void bFile::resolvePointersMismatch() +{ +// printf("resolvePointersStructMismatch\n"); + + int i; + + for (i=0;i< m_pointerFixupArray.size();i++) + { + char* cur = m_pointerFixupArray.at(i); + void** ptrptr = (void**) cur; + void* ptr = *ptrptr; + ptr = findLibPointer(ptr); + if (ptr) + { + //printf("Fixup pointer!\n"); + *(ptrptr) = ptr; + } else + { +// printf("pointer not found: %x\n",cur); + } + } + + for (i=0;i< m_pointerPtrFixupArray.size();i++) + { + char* cur= m_pointerPtrFixupArray.at(i); + void** ptrptr = (void**)cur; + void *ptr = findLibPointer(*ptrptr); + if (ptr) + { + (*ptrptr) = ptr; + + void **array= (void**)(*(ptrptr)); + + int n=0, n2=0; + int swapoffs = mFileDNA->getPointerSize() > mMemoryDNA->getPointerSize() ? 2 : 1; + void *np = array[n]; + while(np) + { + if (mFlags & FD_BITS_VARIES) + swapPtr((char*)&array[n], (char*)&array[n2]); + + np = findLibPointer(array[n]); + if (np) + array[n] = np; + ++n; + n2 += swapoffs; + } + } + } +} + + +///this loop only works fine if the Blender DNA structure of the file matches the headerfiles +void bFile::resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + short oldLen = fileDna->getLength(oldStruct[0]); + char* structType = fileDna->getType(oldStruct[0]); + + char* cur = (char*)findLibPointer(dataChunk.oldPtr); + for (int block=0; blockgetStruct(0)[0]; + + + char* elemPtr= strcPtr; + + short int* oldStruct = fileDna->getStruct(dna_nr); + + int elementLength = oldStruct[1]; + oldStruct+=2; + + + for (int ele=0; elegetType(oldStruct[0]); + memName = fileDna->getName(oldStruct[1]); + + + + int arrayLen = fileDna->getArraySizeNew(oldStruct[1]); + if (memName[0] == '*') + { + if (arrayLen > 1) + { + void **array= (void**)elemPtr; + for (int a=0; agetReverseType(oldStruct[0]); + if (oldStruct[0]>=firstStructType) //revType != -1 && + { + if (verboseDumpAllBlocks) + { + for (int i=0;i\n",memName,memType); + } + resolvePointersStructRecursive(elemPtr,revType, verboseDumpAllBlocks,recursion+1); + if (verboseDumpAllBlocks) + { + for (int i=0;i\n",memName); + } + } else + { + //export a simple type + if (verboseDumpAllBlocks) + { + + if (arrayLen>MAX_ARRAY_LENGTH) + { + printf("too long\n"); + } else + { + //printf("%s %s\n",memType,memName); + + bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0); + + if (isIntegerType) + { + char* newtype="int"; + int dbarray[MAX_ARRAY_LENGTH]; + int* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (int i=0;i",memName,memType); + else + printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen); + for (int i=0;i\n",memName); + } + } else + { + float value = 1.f; + char* newtype="double"; + double dbarray[MAX_ARRAY_LENGTH]; + double* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (int i=0;i",memName,memType); + else + printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen); + for (int i=0;i\n",memName); + } + } + } + + } + } + } + + int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]); + elemPtr+=size; + + } +} + + +///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures +void bFile::resolvePointers(bool verboseDumpAllBlocks) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + printf("resolvePointers start\n"); + char *dataPtr = mFileBuffer+mDataStart; + + if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES)) + { + resolvePointersMismatch(); + } + + { + for (int i=0;iflagEqual(dataChunk.dna_nr)) + { + //dataChunk.len + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + char* oldType = fileDna->getType(oldStruct[0]); + + if (verboseDumpAllBlocks) + printf("<%s>\n",oldType); + + resolvePointersChunk(dataChunk, verboseDumpAllBlocks); + + if (verboseDumpAllBlocks) + printf("\n",oldType); + } else + { + //printf("skipping mStruct\n"); + } + } + } + + printf("resolvePointers end\n"); +} + + +// ----------------------------------------------------- // +void* bFile::findLibPointer(void *ptr) +{ + + bStructHandle** ptrptr = getLibPointers().find(ptr); + if (ptrptr) + return *ptrptr; + return 0; +} + + +void bFile::updateOldPointers() +{ + int i; + + for (i=0;igetStruct(dataChunk.dna_nr); + char* typeName = dna->getType(newStruct[0]); + printf("%3d: %s ",i,typeName); + + printf("code=%s ",codestr); + + printf("ptr=%p ",dataChunk.oldPtr); + printf("len=%d ",dataChunk.len); + printf("nr=%d ",dataChunk.nr); + if (dataChunk.nr!=1) + { + printf("not 1\n"); + } + printf("\n"); + + + + + } + +#if 0 + IDFinderData ifd; + ifd.success = 0; + ifd.IDname = NULL; + ifd.just_print_it = 1; + for (i=0; im_blocks.size(); ++i) + { + BlendBlock* bb = bf->m_blocks[i]; + printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size()); + block_ID_finder(bb, bf, &ifd); + printf("\n"); + } +#endif + +} + + +void bFile::writeChunks(FILE* fp, bool fixupPointers) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + for (int i=0;igetStruct(dataChunk.dna_nr); + oldType = fileDna->getType(oldStruct[0]); + oldLen = fileDna->getLength(oldStruct[0]); + ///don't try to convert Link block data, just memcpy it. Other data can be converted. + reverseOld = mMemoryDNA->getReverseType(oldType); + + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + curLen = mMemoryDNA->getLength(curStruct[0]); + dataChunk.dna_nr = reverseOld; + if (strcmp("Link",oldType)!=0) + { + dataChunk.len = curLen * dataChunk.nr; + } else + { +// printf("keep length of link = %d\n",dataChunk.len); + } + + //write the structure header + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + + + + short int* curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr); + assert(curStruct1 == curStruct); + + char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr; + + //write the actual contents of the structure(s) + fwrite(cur,dataChunk.len,1,fp); + } else + { + printf("serious error, struct mismatch: don't write\n"); + } + } + +} + + +//eof + diff --git a/Demos/SerializeDemo/bFile.h b/Demos/SerializeDemo/bFile.h new file mode 100644 index 000000000..b3a517767 --- /dev/null +++ b/Demos/SerializeDemo/bFile.h @@ -0,0 +1,146 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BFILE_H__ +#define __BFILE_H__ + +#include "bCommon.h" +#include "bChunk.h" +#include + +namespace bParse { + + // ----------------------------------------------------- // + enum bFileFlags + { + FD_INVALID =0, + FD_OK =1, + FD_VOID_IS_8 =2, + FD_ENDIAN_SWAP =4, + FD_FILE_64 =8, + FD_BITS_VARIES =16, + FD_VERSION_VARIES = 32 + }; + + + // ----------------------------------------------------- // + class bFile + { + protected: + + char m_headerString[7]; + + bool mOwnsBuffer; + char* mFileBuffer; + int mFileLen; + int mVersion; + + + bPtrMap mLibPointers; + + int mDataStart; + bDNA* mFileDNA; + bDNA* mMemoryDNA; + + btAlignedObjectArray m_pointerFixupArray; + btAlignedObjectArray m_pointerPtrFixupArray; + + btAlignedObjectArray m_chunks; + + // + + bPtrMap mDataPointers; + + + + int mFlags; + + virtual void parseHeader(); + + virtual void parseData() = 0; + + void resolvePointersMismatch(); + void resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks); + + void resolvePointersStructRecursive(char *strcPtr, int old_dna, bool verboseDumpAllBlocks, int recursion); + void swapPtr(char *dst, char *src); + + void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers); + void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers); + char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos); + + + void swap(char *head, class bChunkInd& ch); + + void swapData(char *data, short type, int arraySize); + void swapStruct(int dna_nr, char *data); + + + + + char* readStruct(char *head, class bChunkInd& chunk); + char *getAsString(int code); + + void parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength); + + public: + bFile(const char *filename, const char headerString[7]); + + //todo: make memoryBuffer const char + //bFile( const char *memoryBuffer, int len); + bFile( char *memoryBuffer, int len, const char headerString[7]); + ~bFile(); + + bDNA* getFileDNA() + { + return mFileDNA; + } + + virtual void addDataBlock(char* dataBlock) = 0; + + int getFlags() const + { + return mFlags; + } + + bPtrMap& getLibPointers() + { + return mLibPointers; + } + + void* findLibPointer(void *ptr); + + bool ok(); + + virtual void parse(bool verboseDumpAllTypes) = 0; + + virtual int write(const char* fileName, bool fixupPointers=false) = 0; + + virtual void writeChunks(FILE* fp, bool fixupPointers ); + + virtual void writeDNA(FILE* fp) = 0; + + void updateOldPointers(); + void resolvePointers(bool verboseDumpAllBlocks); + + void dumpChunks(bDNA* dna); + + + + }; +} + + +#endif//__BFILE_H__ diff --git a/Demos/SerializeDemo/btBulletFile.cpp b/Demos/SerializeDemo/btBulletFile.cpp new file mode 100644 index 000000000..53d630393 --- /dev/null +++ b/Demos/SerializeDemo/btBulletFile.cpp @@ -0,0 +1,251 @@ +/* +bParse +Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBulletFile.h" +#include "bDefines.h" +#include "bDNA.h" +#include + + +// 32 && 64 bit versions +extern unsigned char sBulletDNAstr[]; +extern int sBulletDNAlen; + +//not yetto. extern unsigned char DNAstr64[]; +//not yetto. extern int DNAlen64; + + +using namespace bParse; + +btBulletFile::btBulletFile() +:bFile("", "BULLET ") +{ + mMemoryDNA = new bDNA(); + mMemoryDNA->init((char*)sBulletDNAstr,sBulletDNAlen); +} + + +btBulletFile::btBulletFile(const char* fileName) +:bFile(fileName, "BULLET ") +{ +} + + + +btBulletFile::btBulletFile(char *memoryBuffer, int len) +:bFile(memoryBuffer,len, "BULLET ") +{ + +} + + +btBulletFile::~btBulletFile() +{ + +} + + + +// ----------------------------------------------------- // +void btBulletFile::parseData() +{ + printf ("Building datablocks"); + printf ("Chunk size = %d",CHUNK_HEADER_LEN); + printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags)); + + const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0; + + + mDataStart = 12; + + char *dataPtr = mFileBuffer+mDataStart; + + bChunkInd dataChunk; + dataChunk.code = 0; + + + //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + int seek = ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + //dataPtr += ChunkUtils::getOffset(mFlags); + char *dataPtrHead = 0; + + while (dataChunk.code != DNA1) + { + + + + + // one behind + if (dataChunk.code == SDNA) break; + //if (dataChunk.code == DNA1) break; + + // same as (BHEAD+DATA dependancy) + dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags); + char *id = readStruct(dataPtrHead, dataChunk); + + // lookup maps + if (id) + { + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id); + + m_chunks.push_back(dataChunk); + // block it + //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code); + //if (listID) + // listID->push_back((bStructHandle*)id); + } + + if (dataChunk.code == BT_RIGIDBODY_CODE) + { + m_rigidBodies.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_COLLISIONOBJECT_CODE) + { + m_collisionObjects.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_BOXSHAPE_CODE) + { + m_collisionShapes.push_back((bStructHandle*) id); + } + +// if (dataChunk.code == GLOB) +// { +// m_glob = (bStructHandle*) id; +// } + + // next please! + dataPtr += seek; + + seek = ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + if (seek < 0) + break; + } + +} + +void btBulletFile::addDataBlock(char* dataBlock) +{ + //mMain->addDatablock(dataBlock); +} + + + + +void btBulletFile::writeDNA(FILE* fp) +{ + + bChunkInd dataChunk; + dataChunk.code = DNA1; + dataChunk.dna_nr = 0; + dataChunk.nr = 1; + + if (VOID_IS_8) + { + //dataChunk.len = DNAlen64; + //dataChunk.oldPtr = DNAstr64; + //fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + //fwrite(DNAstr64, DNAlen64,1,fp); + } + else + { + dataChunk.len = sBulletDNAlen; + dataChunk.oldPtr = sBulletDNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); + } +} + +void btBulletFile::parse(bool verboseDumpAllTypes) +{ + if (VOID_IS_8) + { + exit(0); + //parseInternal(verboseDumpAllTypes,(char*)DNAstr64,DNAlen64); + } + else + { + parseInternal(verboseDumpAllTypes,(char*)sBulletDNAstr,sBulletDNAlen); + } +} + +// experimental +int btBulletFile::write(const char* fileName, bool fixupPointers) +{ + FILE *fp = fopen(fileName, "wb"); + if (fp) + { + char header[SIZEOFBLENDERHEADER] ; + memcpy(header, m_headerString, 7); + int endian= 1; + endian= ((char*)&endian)[0]; + + if (endian) + { + header[7] = '_'; + } else + { + header[7] = '-'; + } + if (VOID_IS_8) + { + header[8]='V'; + } else + { + header[8]='v'; + } + + header[9] = '2'; + header[10] = '7'; + header[11] = '5'; + + fwrite(header,SIZEOFBLENDERHEADER,1,fp); + + writeChunks(fp, fixupPointers); + + writeDNA(fp); + + fclose(fp); + + } else + { + printf("Error: cannot open file %s for writing\n",fileName); + return 0; + } + return 1; +} + + + +void btBulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code) +{ + + bParse::bChunkInd dataChunk; + dataChunk.code = code; + dataChunk.nr = 1; + dataChunk.len = len; + dataChunk.dna_nr = mMemoryDNA->getReverseType(structType); + dataChunk.oldPtr = oldPtr; + + ///Perform structure size validation + short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr); + int elemBytes = mMemoryDNA->getLength(structInfo[0]); +// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]); + assert(len==elemBytes); + + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data); + m_chunks.push_back(dataChunk); +} \ No newline at end of file diff --git a/Demos/SerializeDemo/btBulletFile.h b/Demos/SerializeDemo/btBulletFile.h new file mode 100644 index 000000000..7ee3fba9b --- /dev/null +++ b/Demos/SerializeDemo/btBulletFile.h @@ -0,0 +1,70 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BULLET_FILE_H +#define BT_BULLET_FILE_H + + +#include "bFile.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "bDefines.h" + +#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J') +#define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y') +#define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S') + +namespace bParse { + + // ----------------------------------------------------- // + class btBulletFile : public bFile + { + + protected: + + + public: + + btAlignedObjectArray m_rigidBodies; + + btAlignedObjectArray m_collisionObjects; + + btAlignedObjectArray m_collisionShapes; + + btBulletFile(); + + btBulletFile(const char* fileName); + + btBulletFile(char *memoryBuffer, int len); + + virtual ~btBulletFile(); + + virtual void addDataBlock(char* dataBlock); + + + // experimental + virtual int write(const char* fileName, bool fixupPointers=false); + + virtual void parse(bool verboseDumpAllTypes); + + virtual void parseData(); + + virtual void writeDNA(FILE* fp); + + void addStruct(const char* structType,void* data, int len, void* oldPtr, int code); + + }; +}; + +#endif //BT_BULLET_FILE_H diff --git a/Demos/SerializeDemo/main.cpp b/Demos/SerializeDemo/main.cpp new file mode 100644 index 000000000..605f6ea42 --- /dev/null +++ b/Demos/SerializeDemo/main.cpp @@ -0,0 +1,90 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +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. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BasicDemo.h" +#include "GlutStuff.h" +#include "GLDebugDrawer.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btHashMap.h" + +class OurValue + { + int m_uid; + + public: + OurValue(const btVector3& initialPos) + :m_position(initialPos) + { + static int gUid=0; + m_uid=gUid; + gUid++; + } + + btVector3 m_position; + int getUid() const + { + return m_uid; + } + }; + + +int main(int argc,char** argv) +{ + GLDebugDrawer gDebugDrawer; + + ///testing the btHashMap + btHashMap,OurValue> map; + + OurValue value1(btVector3(2,3,4)); + btHashKey key1(value1.getUid()); + map.insert(key1,value1); + + + OurValue value2(btVector3(5,6,7)); + btHashKey key2(value2.getUid()); + map.insert(key2,value2); + + + { + OurValue value3(btVector3(7,8,9)); + btHashKey key3(value3.getUid()); + map.insert(key3,value3); + } + + + map.remove(key2); + + const OurValue* ourPtr = map.find(key1); + for (int i=0;im_position.getX(),tmp->m_position.getY(),tmp->m_position.getZ()); + } + + BasicDemo ccdDemo; + ccdDemo.initPhysics(); + ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); + + +#ifdef CHECK_MEMORY_LEAKS + ccdDemo.exitPhysics(); +#else + return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo); +#endif + + //default glut doesn't return from mainloop + return 0; +} + diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index b159d0b4e..baee81863 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -1235,6 +1235,25 @@ void btCollisionWorld::debugDrawWorld() } +void btCollisionWorld::serializeCollisionObjects(btDefaultSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() == btCollisionObject::CO_COLLISION_OBJECT) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr); + chunk->m_dna_nr = serializer->getReverseType(structType); + chunk->m_chunkCode = BT_COLLISIONOBJECT_CODE; + chunk->m_oldPtr = colObj; + } + } +} + void btCollisionWorld::serialize(btDefaultSerializer* serializer) { @@ -1252,20 +1271,7 @@ void btCollisionWorld::serialize(btDefaultSerializer* serializer) serializer->initDNA((const char*)sBulletDNAstr,sBulletDNAlen); } - int i; - - //serialize all collision objects - for (i=0;icalculateSerializeBufferSize(); - btChunk* chunk = serializer->allocate(len,1); - const char* structType = colObj->serialize(chunk->m_oldPtr); - chunk->m_dna_nr = serializer->getReverseType(structType); - chunk->m_chunkCode = BT_COLLISIONOBJECT_CODE; - chunk->m_oldPtr = colObj; - } - + serializeCollisionObjects(serializer); #if 0 { diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 8fa7c1063..4cda91b7b 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -100,6 +100,8 @@ protected: ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB) bool m_forceUpdateAllAabbs; + void serializeCollisionObjects(btDefaultSerializer* serializer); + public: //this constructor doesn't own the dispatcher and paircache/broadphase @@ -422,8 +424,8 @@ public: m_forceUpdateAllAabbs = forceUpdateAllAabbs; } - ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (to be added in the Bullet/Extras) - void serialize(btDefaultSerializer* serializer); + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo) + virtual void serialize(btDefaultSerializer* serializer); }; diff --git a/src/BulletCollision/CollisionShapes/btBoxShape.h b/src/BulletCollision/CollisionShapes/btBoxShape.h index cbc8a6d97..ad5b16f82 100644 --- a/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -323,6 +323,7 @@ public: struct btBoxShapeData { + btCollisionShapeData m_collisionShapeData; btVector3Data m_halfExtents; btVector3Data m_localScaling; }; @@ -338,6 +339,7 @@ SIMD_FORCE_INLINE int btBoxShape::calculateSerializeBufferSize() SIMD_FORCE_INLINE const char* btBoxShape::serialize(void* dataBuffer) const { btBoxShapeData* boxData = (btBoxShapeData*) dataBuffer; + btCollisionShape::serialize(&boxData->m_collisionShapeData); m_implicitShapeDimensions.serialize(boxData->m_halfExtents); m_localScaling.serialize(boxData->m_localScaling); diff --git a/src/BulletCollision/CollisionShapes/btCollisionShape.h b/src/BulletCollision/CollisionShapes/btCollisionShape.h index cb6139546..c0dc0977e 100644 --- a/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -118,6 +118,11 @@ public: return m_userPointer; } + virtual int calculateSerializeBufferSize(); + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer) const; + }; ///for serialization @@ -128,6 +133,20 @@ struct btCollisionShapeData char m_padding[4]; }; +SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() +{ + return sizeof(btCollisionShapeData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btCollisionShape::serialize(void* dataBuffer) const +{ + btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer; + shapeData->m_userPointer = m_userPointer; + shapeData->m_shapeType = m_shapeType; + //shapeData->m_padding//?? + return "btCollisionShapeData"; +} #endif //COLLISION_SHAPE_H diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index e114f783d..b37e39355 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -43,7 +43,7 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "LinearMath/btMotionState.h" - +#include "LinearMath/btSerializer.h" @@ -1078,3 +1078,47 @@ const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const } + +void btDiscreteDynamicsWorld::serializeRigidBodies(btDefaultSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() == btCollisionObject::CO_RIGID_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr); + chunk->m_dna_nr = serializer->getReverseType(structType); + chunk->m_chunkCode = BT_RIGIDBODY_CODE; + chunk->m_oldPtr = colObj; + } + } +} + + +void btDiscreteDynamicsWorld::serialize(btDefaultSerializer* serializer) +{ + + + const bool VOID_IS_8 = ((sizeof(void*)==8)); + + if (VOID_IS_8) + { + //64bit not yet supported (soon) + btAssert(0); + return; + } else + { + serializer->initDNA((const char*)sBulletDNAstr,sBulletDNAlen); + } + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->writeDNA(); +} + diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 1231d9fc8..f1249ecd4 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -77,7 +77,7 @@ protected: virtual void saveKinematicState(btScalar timeStep); - + void serializeRigidBodies(btDefaultSerializer* serializer); public: @@ -190,6 +190,9 @@ public: return m_synchronizeAllMotionStates; } + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo) + virtual void serialize(btDefaultSerializer* serializer); + }; #endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/src/BulletDynamics/Dynamics/btRigidBody.cpp b/src/BulletDynamics/Dynamics/btRigidBody.cpp index 2fc9ed302..e73ac17f9 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -326,6 +326,9 @@ int btRigidBody::calculateSerializeBufferSize() const const char* btRigidBody::serialize(void* dataBuffer) const { btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer; + + btCollisionObject::serialize(&rbd->m_collisionObjectData); + m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld); m_linearVelocity.serialize(rbd->m_linearVelocity); m_angularVelocity.serialize(rbd->m_angularVelocity); @@ -347,8 +350,6 @@ const char* btRigidBody::serialize(void* dataBuffer) const rbd->m_linearSleepingThreshold=m_linearSleepingThreshold; rbd->m_angularSleepingThreshold = m_angularSleepingThreshold; - btCollisionObject::serialize(&rbd->m_collisionObjectData); - return "btRigidBodyData"; } diff --git a/src/BulletDynamics/Dynamics/btRigidBody.h b/src/BulletDynamics/Dynamics/btRigidBody.h index 3b05e2096..7028a9bcf 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/src/BulletDynamics/Dynamics/btRigidBody.h @@ -506,6 +506,8 @@ public: ///btRigidBodyData is used for btRigidBody serialization struct btRigidBodyData { + btCollisionObjectData m_collisionObjectData; + btMatrix3x3Data m_invInertiaTensorWorld; btVector3Data m_linearVelocity; btVector3Data m_angularVelocity; @@ -531,8 +533,6 @@ struct btRigidBodyData btScalar m_linearSleepingThreshold; btScalar m_angularSleepingThreshold; - - btCollisionObjectData m_collisionObjectData; }; diff --git a/src/LinearMath/btSerializer.h b/src/LinearMath/btSerializer.h index 71f7ccc2c..5ca22b354 100644 --- a/src/LinearMath/btSerializer.h +++ b/src/LinearMath/btSerializer.h @@ -86,9 +86,9 @@ public: btDefaultSerializer(int totalSize) :m_totalSize(totalSize), - m_currentSize(0) -// m_dna(0), -// m_dnaLength(0) + m_currentSize(0), + m_dna(0), + m_dnaLength(0) { m_buffer = (unsigned char*)btAlignedAlloc(16,totalSize); m_currentSize += BT_HEADER_LENGTH; @@ -165,6 +165,9 @@ public: void initDNA(const char* bdna,int dnalen) { + ///was already initialized + if (m_dna) + return; m_dna = btAlignedAlloc(dnalen,16); memcpy(m_dna,bdna,dnalen);