static void setMissingPropertiesToDefault( RepXCollection& collection, RepXReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults ) { FoundationWrapper wrapper( collection.getAllocator() ); //Release all strings at once, instead of piece by piece RepXMemoryAllocatorImpl alloc( collection.getAllocator() ); //build a hashtable of the initial default value strings. TNameOffsetMap nameOffsets( wrapper ); for ( PxU32 idx = 0; idx < numDefaults; ++idx ) { const RepXDefaultEntry& item( defaults[idx] ); size_t nameLen = 0; const char* periodPtr = nextPeriod (item.name); for ( ; periodPtr && *periodPtr; ++periodPtr ) if( *periodPtr == '.' ) break; if ( periodPtr == NULL || *periodPtr != '.' ) continue; nameLen = periodPtr - item.name; char* newMem = (char*)alloc.allocate( PxU32(nameLen + 1) ); memcpy( newMem, item.name, nameLen ); newMem[nameLen] = 0; if ( nameOffsets.find( newMem ) ) alloc.deallocate( (PxU8*)newMem ); else nameOffsets.insert( newMem, idx ); } //Run through each collection item, and recursively find it and its children //If an object's name is in the hash map, check and add any properties that don't exist. //else return. for ( const RepXCollectionItem* item = collection.begin(), *end = collection.end(); item != end; ++ item ) { RepXCollectionItem theItem( *item ); setMissingPropertiesToDefault( theItem.mDescriptor, editor, defaults, numDefaults, nameOffsets ); } }
RepXCollection& RepXUpgrader::upgrade3_1CollectionTo3_2Collection(RepXCollection& src) { XmlReaderWriter& editor( src.createNodeEditor() ); setMissingPropertiesToDefault(src, editor, gRepX3_1Defaults, gNumRepX3_1Defaults ); RepXCollection* dest = &src.createCollection("3.2.0"); for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) { //either src or dest could do the copy operation, it doesn't matter who does it. RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); if ( strstr( newItem.liveObject.typeName, "PxMaterial" ) ) { editor.removeChild( "DynamicFrictionV" ); editor.removeChild( "StaticFrictionV" ); editor.removeChild( "dirOfAnisotropy" ); } //now desc owns the new node. Collections share a single allocation pool, however, //which will get destroyed when all the collections referencing it are destroyed themselves. //Data on nodes is shared between nodes, but the node structure itself is allocated. dest->addCollectionItem( newItem ); } editor.release(); src.destroy(); return *dest; }
bool PhysXWorld::ExportWholeScene(const char *filename) const { using namespace physx::repx; if (!PhysXSDK || !PhysXScene) return false; PxCollection *cl = PhysXSDK->createCollection(); if (!cl) return false; PhysxUserFileWriteStream fs(filename); RepXCollection* theCollection = createCollection(PhysXSDK->getTolerancesScale(), PhysXFoundation->getAllocatorCallback()); RepXIdToRepXObjectMap* theIdMap = RepXIdToRepXObjectMap::create(PxGetFoundation().getAllocatorCallback()); addSDKItemsToRepX ( *PhysXSDK, *theIdMap, *theCollection); //add physcis object addSceneItemsToRepX ( *PhysXScene, *theIdMap, *theCollection); //add physcis object // physx::repx::addObjectsToScene(theCollection, physics, cooking, scene, mStringTable ); theCollection->save(fs); theCollection->destroy(); theIdMap->destroy(); return true; // PxCollectForExportSDK(*PhysXSDK, *cl); // PxCollectForExportScene(*PhysXScene, *cl); ObjectIterator iter = GameWorld().GetFirstOfAllObjects(); while( iter.current ) { GameObject* o = iter.current; if (o->PhysicsObject) { PxActor *a = o->PhysicsObject->getPhysicsActor(); PxSerialFlags f = a->getSerialFlags(); a->collectForExport(*cl); break; } iter = GameWorld().GetNextOfAllObjects( iter ); } PxU32 numObjs = cl->getNbObjects(); numObjs; cl->serialize(fs); PhysXSDK->releaseCollection(*cl); fclose(fs.fpw); FILE* fp=NULL; if( (fp = fopen(filename, "rb")) ) { fseek(fp, 0, SEEK_END); PxU32 fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); PX_ASSERT(fileSize!=0); void* mem = malloc(fileSize+PX_SERIAL_FILE_ALIGN); void* mem16 = (void*)((size_t(mem) + PX_SERIAL_FILE_ALIGN)&~(PX_SERIAL_FILE_ALIGN-1)); fread(mem16, 1, fileSize, fp); fclose(fp); PxUserReferences* convexRefs = PhysXSDK->createUserReferences(); PxCollection* collection = PhysXSDK->createCollection(); collection->deserialize(mem16, convexRefs, NULL); PxU32 numObjs = collection->getNbObjects(); for (PxU32 i = 0; i < numObjs; ++i) { PxSerializable *o = collection->getObject(i); const char * name = o->getConcreteTypeName(); PX_ASSERT(name); } } return true; }
RepXCollection& RepXUpgrader::upgrade10CollectionTo3_1Collection(RepXCollection& src) { RepXReaderWriter& editor( src.createNodeEditor() ); setMissingPropertiesToDefault(src, editor, gRepX1_0Defaults, gNumRepX1_0Default ); RepXCollection* dest = &src.createCollection("3.1.1"); for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) { //either src or dest could do the copy operation, it doesn't matter who does it. RepXCollectionItem newItem( item->mLiveObject, src.copyRepXNode( item->mDescriptor ) ); editor.setNode( *const_cast<RepXNode*>( newItem.mDescriptor ) ); //Some old files have this name in their system. editor.renameProperty( "MassSpaceInertia", "MassSpaceInertiaTensor" ); editor.renameProperty( "SleepEnergyThreshold", "SleepThreshold" ); if ( strstr( newItem.mLiveObject.mTypeName, "Joint" ) || strstr( newItem.mLiveObject.mTypeName, "joint" ) ) { //Joints changed format a bit. old joints looked like: /* <Actor0 >1627536</Actor0> <Actor1 >1628368</Actor1> <LocalPose0 >0 0 0 1 0.5 0.5 0.5</LocalPose0> <LocalPose1 >0 0 0 1 0.3 0.3 0.3</LocalPose1>*/ //New joints look like: /* <Actors > <actor0 >58320336</actor0> <actor1 >56353568</actor1> </Actors> <LocalPose > <eACTOR0 >0 0 0 1 0.5 0.5 0.5</eACTOR0> <eACTOR1 >0 0 0 1 0.3 0.3 0.3</eACTOR1> </LocalPose> */ const char* actor0, *actor1, *lp0, *lp1; editor.readAndRemoveProperty( "Actor0", actor0 ); editor.readAndRemoveProperty( "Actor1", actor1 ); editor.readAndRemoveProperty( "LocalPose0", lp0 ); editor.readAndRemoveProperty( "LocalPose1", lp1 ); editor.addOrGotoChild( "Actors" ); editor.writePropertyIfNotEmpty( "actor0", actor0 ); editor.writePropertyIfNotEmpty( "actor1", actor1 ); editor.leaveChild(); editor.addOrGotoChild( "LocalPose" ); editor.writePropertyIfNotEmpty( "eACTOR0", lp0 ); editor.writePropertyIfNotEmpty( "eACTOR1", lp1 ); editor.leaveChild(); } //now desc owns the new node. Collections share a single allocation pool, however, //which will get destroyed when all the collections referencing it are destroyed themselves. //Data on nodes is shared between nodes, but the node structure itself is allocated. dest->addCollectionItem( newItem ); } editor.release(); src.destroy(); return *dest; }
RepXCollection& RepXUpgrader::upgrade3_2CollectionTo3_3Collection(RepXCollection& src) { XmlReaderWriter& editor( src.createNodeEditor() ); setMissingPropertiesToDefault(src, editor, gRepX3_2Defaults, gNumRepX3_2Defaults ); RepXCollection* dest = &src.createCollection("3.3.0"); struct RenameSpringToStiffness : public RecursiveTraversal { RenameSpringToStiffness(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {} void updateNode() { mEditor.renameProperty("Spring", "Stiffness"); mEditor.renameProperty("TangentialSpring", "TangentialStiffness"); } }; struct UpdateArticulationSwingLimit : public RecursiveTraversal { UpdateArticulationSwingLimit(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {} void updateNode() { if(!PxStricmp(mEditor.getCurrentItemName(), "yLimit") && !PxStricmp(mEditor.getCurrentItemValue(), "0")) mEditor.setCurrentItemValue("0.785398"); if(!PxStricmp(mEditor.getCurrentItemName(), "zLimit") && !PxStricmp(mEditor.getCurrentItemValue(), "0")) mEditor.setCurrentItemValue("0.785398"); if(!PxStricmp(mEditor.getCurrentItemName(), "TwistLimit")) { mEditor.gotoFirstChild(); PxReal lower = (PxReal)strtod(mEditor.getCurrentItemValue(), NULL); mEditor.gotoNextSibling(); PxReal upper = (PxReal)strtod(mEditor.getCurrentItemValue(), NULL); mEditor.leaveChild(); if(lower>=upper) { mEditor.writePropertyIfNotEmpty("lower", "-0.785398"); mEditor.writePropertyIfNotEmpty("upper", "0.785398"); } } } }; for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) { //either src or dest could do the copy operation, it doesn't matter who does it. RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); if ( strstr( newItem.liveObject.typeName, "PxCloth" ) || strstr( newItem.liveObject.typeName, "PxClothFabric" ) ) { physx::shdfnd::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "Didn't suppot PxCloth upgrate from 3.2 to 3.3! "); continue; } if ( strstr( newItem.liveObject.typeName, "PxParticleSystem" ) || strstr( newItem.liveObject.typeName, "PxParticleFluid" ) ) { editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); editor.renameProperty( "PositionBuffer", "Positions" ); editor.renameProperty( "VelocityBuffer", "Velocities" ); editor.renameProperty( "RestOffsetBuffer", "RestOffsets" ); } if(strstr(newItem.liveObject.typeName, "PxPrismaticJoint" ) || strstr(newItem.liveObject.typeName, "PxRevoluteJoint") || strstr(newItem.liveObject.typeName, "PxSphericalJoint") || strstr(newItem.liveObject.typeName, "PxD6Joint") || strstr(newItem.liveObject.typeName, "PxArticulation")) { editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); RenameSpringToStiffness(editor).traverse(); } if(strstr(newItem.liveObject.typeName, "PxArticulation")) { editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); UpdateArticulationSwingLimit(editor).traverse(); } //now dest owns the new node. Collections share a single allocation pool, however, //which will get destroyed when all the collections referencing it are destroyed themselves. //Data on nodes is shared between nodes, but the node structure itself is allocated. dest->addCollectionItem( newItem ); } editor.release(); src.destroy(); return *dest; }