feat(physics): wire physx sdk into build

This commit is contained in:
2026-04-15 12:22:15 +08:00
parent 5bf258df6d
commit 31f40e2cbb
2044 changed files with 752623 additions and 1 deletions

View File

@@ -0,0 +1,300 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxSerializer.h"
#include "foundation/PxHash.h"
#include "foundation/PxHashMap.h"
#include "foundation/PxString.h"
#include "extensions/PxSerialization.h"
#include "PxPhysics.h"
#include "PxPhysicsSerialization.h"
#include "SnFile.h"
#include "SnSerializationContext.h"
#include "serialization/SnSerializationRegistry.h"
#include "serialization/SnSerialUtils.h"
#include "CmCollection.h"
using namespace physx;
using namespace Sn;
namespace
{
PX_INLINE PxU8* alignPtr(PxU8* ptr, PxU32 alignment = PX_SERIAL_ALIGN)
{
if(!alignment)
return ptr;
const PxU32 padding = getPadding(size_t(ptr), alignment);
PX_ASSERT(!getPadding(size_t(ptr + padding), alignment));
return ptr + padding;
}
PX_FORCE_INLINE PxU32 read32(PxU8*& address)
{
const PxU32 value = *reinterpret_cast<PxU32*>(address);
address += sizeof(PxU32);
return value;
}
bool readHeader(PxU8*& address)
{
const PxU32 header = read32(address);
PX_UNUSED(header);
const PxU32 version = read32(address);
PX_UNUSED(version);
char binaryVersionGuid[SN_BINARY_VERSION_GUID_NUM_CHARS + 1];
PxMemCopy(binaryVersionGuid, address, SN_BINARY_VERSION_GUID_NUM_CHARS);
binaryVersionGuid[SN_BINARY_VERSION_GUID_NUM_CHARS] = 0;
address += SN_BINARY_VERSION_GUID_NUM_CHARS;
PX_UNUSED(binaryVersionGuid);
const PxU32 platformTag = read32(address);
PX_UNUSED(platformTag);
const PxU32 markedPadding = read32(address);
PX_UNUSED(markedPadding);
if (header != PX_MAKE_FOURCC('S','E','B','D'))
return PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"Buffer contains data with wrong header indicating invalid binary data.");
if (!checkCompatibility(binaryVersionGuid))
return PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"Buffer contains binary data version 0x%s and is incompatible with this PhysX sdk (0x%s).\n",
binaryVersionGuid, getBinaryVersionGuid());
if (platformTag != getBinaryPlatformTag())
return PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"Buffer contains data with platform mismatch:\nExpected: %s \nActual: %s\n",
getBinaryPlatformName(getBinaryPlatformTag()),
getBinaryPlatformName(platformTag));
return true;
}
bool checkImportReferences(const ImportReference* importReferences, PxU32 nbImportReferences, const Cm::Collection* externalRefs)
{
if (!externalRefs)
{
if (nbImportReferences > 0)
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "PxSerialization::createCollectionFromBinary: External references needed but no externalRefs collection specified.");
}
else
{
for (PxU32 i=0; i<nbImportReferences;i++)
{
PxSerialObjectId id = importReferences[i].id;
PxType type = importReferences[i].type;
PxBase* referencedObject = externalRefs->find(id);
if (!referencedObject)
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "PxSerialization::createCollectionFromBinary: External reference %llu expected in externalRefs collection but not found.", id);
if (referencedObject->getConcreteType() != type)
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "PxSerialization::createCollectionFromBinary: External reference %d type mismatch. Expected %d but found %d in externalRefs collection.", type, referencedObject->getConcreteType());
}
}
return true;
}
}
PxCollection* PxSerialization::createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs)
{
if(size_t(memBlock) & (PX_SERIAL_FILE_ALIGN-1))
{
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Buffer must be 128-bytes aligned.");
return NULL;
}
PxU8* address = reinterpret_cast<PxU8*>(memBlock);
const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs);
if (!readHeader(address))
{
return NULL;
}
ManifestEntry* manifestTable;
PxU32 nbManifestEntries;
PxU32 nbObjectsInCollection;
PxU32 objectDataEndOffset;
// read number of objects in collection
address = alignPtr(address);
nbObjectsInCollection = read32(address);
// read manifest (PxU32 offset, PxConcreteType type)
{
address = alignPtr(address);
nbManifestEntries = read32(address);
PX_ASSERT(*reinterpret_cast<PxU32*>(address) == 0); //first offset is always 0
manifestTable = (nbManifestEntries > 0) ? reinterpret_cast<ManifestEntry*>(address) : NULL;
address += nbManifestEntries*sizeof(ManifestEntry);
objectDataEndOffset = read32(address);
}
ImportReference* importReferences;
PxU32 nbImportReferences;
// read import references
{
address = alignPtr(address);
nbImportReferences = read32(address);
importReferences = (nbImportReferences > 0) ? reinterpret_cast<ImportReference*>(address) : NULL;
address += nbImportReferences*sizeof(ImportReference);
}
if (!checkImportReferences(importReferences, nbImportReferences, externalRefs))
{
return NULL;
}
ExportReference* exportReferences;
PxU32 nbExportReferences;
// read export references
{
address = alignPtr(address);
nbExportReferences = read32(address);
exportReferences = (nbExportReferences > 0) ? reinterpret_cast<ExportReference*>(address) : NULL;
address += nbExportReferences*sizeof(ExportReference);
}
// read internal references arrays
PxU32 nbInternalPtrReferences = 0;
PxU32 nbInternalHandle16References = 0;
InternalReferencePtr* internalPtrReferences = NULL;
InternalReferenceHandle16* internalHandle16References = NULL;
{
address = alignPtr(address);
nbInternalPtrReferences = read32(address);
internalPtrReferences = (nbInternalPtrReferences > 0) ? reinterpret_cast<InternalReferencePtr*>(address) : NULL;
address += nbInternalPtrReferences*sizeof(InternalReferencePtr);
nbInternalHandle16References = read32(address);
internalHandle16References = (nbInternalHandle16References > 0) ? reinterpret_cast<InternalReferenceHandle16*>(address) : NULL;
address += nbInternalHandle16References*sizeof(InternalReferenceHandle16);
}
// create internal references map
InternalPtrRefMap internalPtrReferencesMap(nbInternalPtrReferences*2);
{
//create hash (we should load the hashes directly from memory)
for (PxU32 i = 0; i < nbInternalPtrReferences; i++)
{
const InternalReferencePtr& ref = internalPtrReferences[i];
internalPtrReferencesMap.insertUnique(ref.reference, SerialObjectIndex(ref.objIndex));
}
}
InternalHandle16RefMap internalHandle16ReferencesMap(nbInternalHandle16References*2);
{
for (PxU32 i=0;i<nbInternalHandle16References;i++)
{
const InternalReferenceHandle16& ref = internalHandle16References[i];
internalHandle16ReferencesMap.insertUnique(ref.reference, SerialObjectIndex(ref.objIndex));
}
}
SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
Cm::Collection* collection = static_cast<Cm::Collection*>(PxCreateCollection());
PX_ASSERT(collection);
collection->mObjects.reserve(nbObjectsInCollection*2);
if(nbExportReferences > 0)
collection->mIds.reserve(nbExportReferences*2);
PxU8* addressObjectData = alignPtr(address);
PxU8* addressExtraData = alignPtr(addressObjectData + objectDataEndOffset);
DeserializationContext context(manifestTable, importReferences, addressObjectData, internalPtrReferencesMap, internalHandle16ReferencesMap, externalRefs, addressExtraData);
// iterate over memory containing PxBase objects, create the instances, resolve the addresses, import the external data, add to collection.
{
PxU32 nbObjects = nbObjectsInCollection;
while(nbObjects--)
{
address = alignPtr(address);
context.alignExtraData();
// read PxBase header with type and get corresponding serializer.
PxBase* header = reinterpret_cast<PxBase*>(address);
const PxType classType = header->getConcreteType();
const PxSerializer* serializer = sn.getSerializer(classType);
PX_ASSERT(serializer);
PxBase* instance = serializer->createObject(address, context);
if (!instance)
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"Cannot create class instance for concrete type %d.", classType);
collection->release();
return NULL;
}
collection->internalAdd(instance);
}
}
PX_ASSERT(nbObjectsInCollection == collection->internalGetNbObjects());
// update new collection with export references
{
bool manifestTableAccessError = false;
PX_ASSERT(addressObjectData != NULL);
for (PxU32 i=0;i<nbExportReferences;i++)
{
bool isExternal;
PxU32 manifestIndex = exportReferences[i].objIndex.getIndex(isExternal);
PX_ASSERT(!isExternal);
if (manifestIndex < nbManifestEntries)
{
PxBase* obj = reinterpret_cast<PxBase*>(addressObjectData + manifestTable[manifestIndex].offset);
collection->mIds.insertUnique(exportReferences[i].id, obj);
collection->mObjects[obj] = exportReferences[i].id;
}
else
{
manifestTableAccessError = true;
}
}
if (manifestTableAccessError)
{
PxGetFoundation().error(physx::PxErrorCode::eINTERNAL_ERROR, PX_FL, "Manifest table access error");
collection->release();
return NULL;
}
}
PxAddCollectionToPhysics(*collection);
return collection;
}

View File

@@ -0,0 +1,416 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxSerializer.h"
#include "foundation/PxPhysicsVersion.h"
#include "foundation/PxUtilities.h"
#include "foundation/PxSort.h"
#include "SnSerializationContext.h"
#include "serialization/SnSerialUtils.h"
#include "serialization/SnSerializationRegistry.h"
using namespace physx;
using namespace Cm;
using namespace Sn;
//------------------------------------------------------------------------------------
//// Binary Serialized PxCollection, format documentation
//------------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------------
//// overview:
//// header information
//// manifest table
//// import references
//// export references
//// internal references
//// object data
//// extra data
//------------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------------
//// header information:
//// header tag plus various version and platform information
//------------------------------------------------------------------------------------
// header SEBD
// PX_PHYSICS_VERSION
// PX_BINARY_SERIAL_VERSION
// platform tag
// markedPadding (on for PX_CHECKED)
// nbObjectsInCollection
//
//
//------------------------------------------------------------------------------------
//// manifest table:
//// one entry per collected object
//// offsets relative to object data buffer
//------------------------------------------------------------------------------------
// alignment
// PxU32 size
// (PxU32 offset, PxType type)*size
// PxU32 endOffset
//
//
//------------------------------------------------------------------------------------
//// import references:
//// one entry per required reference to external collection
//------------------------------------------------------------------------------------
// alignment
// PxU32 size
// (PxSerialObjectId id, PxType type)*size
//
//
//------------------------------------------------------------------------------------
//// export references:
//// one entry per object in the collection with id
//// object indices point into the manifest table (objects in the same collection)
//------------------------------------------------------------------------------------
// alignment
// PxU32 size
// (PxSerialObjectId id, SerialObjectIndex objIndex)*size
//
//
//------------------------------------------------------------------------------------
//// internal references:
//// one entry per reference, kind pair
//// object indices point either into the manifest table or into the import references
//// depending on whether the entry references the same collection or the external one
//// one section for pointer type references and one for index type references.
//------------------------------------------------------------------------------------
// alignment
// PxU32 sizePtrs;
// (size_t reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs
// PxU32 sizeHandle16;
// (PxU16 reference, PxU32 kind, SerialObjectIndex objIndex)*sizeHandle16
//
//
//------------------------------------------------------------------------------------
//// object data:
//// serialized PxBase derived class instances
//// each object size depends on specific class
//// offsets are stored in manifest table
//------------------------------------------------------------------------------------
// alignment
// (PxConcreteType type, -----)
// alignment
// (PxConcreteType type, --------)
// alignment
// (PxConcreteType type, --)
// .
// .
//
//
// -----------------------------------------------------------------------------------
//// extra data:
//// extra data memory block
//// serialized and deserialized by PxBase implementations
////----------------------------------------------------------------------------------
// extra data
//
//------------------------------------------------------------------------------------
namespace
{
class OutputStreamWriter
{
public:
PX_INLINE OutputStreamWriter(PxOutputStream& stream)
: mStream(stream)
, mCount(0)
{}
PX_INLINE PxU32 write(const void* src, PxU32 offset)
{
PxU32 count = mStream.write(src, offset);
mCount += count;
return count;
}
PX_INLINE PxU32 getStoredSize()
{
return mCount;
}
private:
OutputStreamWriter& operator=(const OutputStreamWriter&);
PxOutputStream& mStream;
PxU32 mCount;
};
class LegacySerialStream : public PxSerializationContext
{
public:
LegacySerialStream(OutputStreamWriter& writer,
const PxCollection& collection,
bool exportNames) : mWriter(writer), mCollection(collection), mExportNames(exportNames) {}
void writeData(const void* buffer, PxU32 size) { mWriter.write(buffer, size); }
PxU32 getTotalStoredSize() { return mWriter.getStoredSize(); }
void alignData(PxU32 alignment)
{
if(!alignment)
return;
PxI32 bytesToPad = PxI32(getPadding(getTotalStoredSize(), alignment));
static const PxI32 BUFSIZE = 64;
char buf[BUFSIZE];
PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
while(bytesToPad > 0)
{
writeData(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
bytesToPad -= BUFSIZE;
}
PX_ASSERT(!getPadding(getTotalStoredSize(), alignment));
}
virtual void registerReference(PxBase&, PxU32, size_t)
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, PX_FL,
"Cannot register references during exportData, exportExtraData.");
}
virtual const PxCollection& getCollection() const
{
return mCollection;
}
virtual void writeName(const char* name)
{
PxU32 len = name && mExportNames ? PxU32(strlen(name)) + 1 : 0;
writeData(&len, sizeof(len));
if(len) writeData(name, len);
}
private:
LegacySerialStream& operator=(const LegacySerialStream&);
OutputStreamWriter& mWriter;
const PxCollection& mCollection;
bool mExportNames;
};
void writeHeader(PxSerializationContext& stream, bool hasDeserializedAssets)
{
PX_UNUSED(hasDeserializedAssets);
//serialized binary data.
const PxU32 header = PX_MAKE_FOURCC('S','E','B','D');
stream.writeData(&header, sizeof(PxU32));
PxU32 version = PX_PHYSICS_VERSION;
stream.writeData(&version, sizeof(PxU32));
stream.writeData(PX_BINARY_SERIAL_VERSION, SN_BINARY_VERSION_GUID_NUM_CHARS);
PxU32 platformTag = getBinaryPlatformTag();
stream.writeData(&platformTag, sizeof(PxU32));
PxU32 markedPadding = 0;
#if PX_CHECKED
if(!hasDeserializedAssets)
markedPadding = 1;
#endif
stream.writeData(&markedPadding, sizeof(PxU32));
}
template<typename InternalReferenceType>
struct InternalReferencePredicate
{
PX_FORCE_INLINE bool operator()(InternalReferenceType& a, InternalReferenceType& b) const { return a.objIndex < b.objIndex; }
};
}
bool PxSerialization::serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& pxCollection, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs, bool exportNames)
{
if(!PxSerialization::isSerializable(pxCollection, sr, pxExternalRefs))
return false;
Collection& collection = static_cast<Collection&>(pxCollection);
const Collection* externalRefs = static_cast<const Collection*>(pxExternalRefs);
//temporary memory stream which allows fixing up data up stream
SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
// sort collection by "order" value (this will be the order in which they get serialized)
sortCollection(collection, sn, false);
//initialized the context with the sorted collection.
SerializationContext context(collection, externalRefs);
// gather reference information
bool hasDeserializedAssets = false;
{
const PxU32 nb = collection.internalGetNbObjects();
for(PxU32 i=0;i<nb;i++)
{
PxBase* s = collection.internalGetObject(i);
PX_ASSERT(s && s->getConcreteType());
#if PX_CHECKED
//can't guarantee marked padding for deserialized instances
if(!(s->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY))
hasDeserializedAssets = true;
#endif
const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
PX_ASSERT(serializer);
serializer->registerReferences(*s, context);
}
}
// now start the actual serialization into the output stream
OutputStreamWriter writer(outputStream);
LegacySerialStream stream(writer, collection, exportNames);
writeHeader(stream, hasDeserializedAssets);
// write size of collection
stream.alignData(PX_SERIAL_ALIGN);
PxU32 nbObjectsInCollection = collection.internalGetNbObjects();
stream.writeData(&nbObjectsInCollection, sizeof(PxU32));
// write the manifest table (PxU32 offset, PxConcreteType type)
{
PxArray<ManifestEntry> manifestTable(collection.internalGetNbObjects());
PxU32 headerOffset = 0;
for(PxU32 i=0;i<collection.internalGetNbObjects();i++)
{
PxBase* s = collection.internalGetObject(i);
PX_ASSERT(s && s->getConcreteType());
PxType concreteType = s->getConcreteType();
const PxSerializer* serializer = sn.getSerializer(concreteType);
PX_ASSERT(serializer);
manifestTable[i] = ManifestEntry(headerOffset, concreteType);
PxU32 classSize = PxU32(serializer->getClassSize());
headerOffset += getPadding(classSize, PX_SERIAL_ALIGN) + classSize;
}
stream.alignData(PX_SERIAL_ALIGN);
const PxU32 nb = manifestTable.size();
stream.writeData(&nb, sizeof(PxU32));
stream.writeData(manifestTable.begin(), manifestTable.size()*sizeof(ManifestEntry));
//store offset for end of object buffer (PxU32 offset)
stream.writeData(&headerOffset, sizeof(PxU32));
}
// write import references
{
const PxArray<ImportReference>& importReferences = context.getImportReferences();
stream.alignData(PX_SERIAL_ALIGN);
const PxU32 nb = importReferences.size();
stream.writeData(&nb, sizeof(PxU32));
stream.writeData(importReferences.begin(), importReferences.size()*sizeof(ImportReference));
}
// write export references
{
PxU32 nbIds = collection.getNbIds();
PxArray<ExportReference> exportReferences(nbIds);
//we can't get quickly from id to object index in collection.
//if we only need this here, its not worth to build a hash
nbIds = 0;
for (PxU32 i=0;i<collection.getNbObjects();i++)
{
PxBase& obj = collection.getObject(i);
PxSerialObjectId id = collection.getId(obj);
if (id != PX_SERIAL_OBJECT_ID_INVALID)
{
SerialObjectIndex objIndex(i, false); //i corresponds to manifest entry
exportReferences[nbIds++] = ExportReference(id, objIndex);
}
}
stream.alignData(PX_SERIAL_ALIGN);
stream.writeData(&nbIds, sizeof(PxU32));
stream.writeData(exportReferences.begin(), exportReferences.size()*sizeof(ExportReference));
}
// write internal references
{
InternalPtrRefMap& internalPtrReferencesMap = context.getInternalPtrReferencesMap();
PxArray<InternalReferencePtr> internalReferencesPtr(internalPtrReferencesMap.size());
PxU32 nbInternalPtrReferences = 0;
InternalHandle16RefMap& internalHandle16ReferencesMap = context.getInternalHandle16ReferencesMap();
PxArray<InternalReferenceHandle16> internalReferencesHandle16(internalHandle16ReferencesMap.size());
PxU32 nbInternalHandle16References = 0;
{
for(InternalPtrRefMap::Iterator iter = internalPtrReferencesMap.getIterator(); !iter.done(); ++iter)
internalReferencesPtr[nbInternalPtrReferences++] = InternalReferencePtr(iter->first, iter->second);
for(InternalHandle16RefMap::Iterator iter = internalHandle16ReferencesMap.getIterator(); !iter.done(); ++iter)
internalReferencesHandle16[nbInternalHandle16References++] = InternalReferenceHandle16(PxTo16(iter->first), iter->second);
//sort InternalReferences according to SerialObjectIndex for determinism
PxSort<InternalReferencePtr, InternalReferencePredicate<InternalReferencePtr> >(internalReferencesPtr.begin(), internalReferencesPtr.size(), InternalReferencePredicate<InternalReferencePtr>());
PxSort<InternalReferenceHandle16, InternalReferencePredicate<InternalReferenceHandle16> >(internalReferencesHandle16.begin(), internalReferencesHandle16.size(), InternalReferencePredicate<InternalReferenceHandle16>());
}
stream.alignData(PX_SERIAL_ALIGN);
stream.writeData(&nbInternalPtrReferences, sizeof(PxU32));
stream.writeData(internalReferencesPtr.begin(), internalReferencesPtr.size()*sizeof(InternalReferencePtr));
stream.writeData(&nbInternalHandle16References, sizeof(PxU32));
stream.writeData(internalReferencesHandle16.begin(), internalReferencesHandle16.size()*sizeof(InternalReferenceHandle16));
}
// write object data
{
stream.alignData(PX_SERIAL_ALIGN);
const PxU32 nb = collection.internalGetNbObjects();
for(PxU32 i=0;i<nb;i++)
{
PxBase* s = collection.internalGetObject(i);
PX_ASSERT(s && s->getConcreteType());
const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
PX_ASSERT(serializer);
stream.alignData(PX_SERIAL_ALIGN);
serializer->exportData(*s, stream);
}
}
// write extra data
{
const PxU32 nb = collection.internalGetNbObjects();
for(PxU32 i=0;i<nb;i++)
{
PxBase* s = collection.internalGetObject(i);
PX_ASSERT(s && s->getConcreteType());
const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
PX_ASSERT(serializer);
stream.alignData(PX_SERIAL_ALIGN);
serializer->exportExtraData(*s, stream);
}
}
return true;
}

View File

@@ -0,0 +1,113 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxBase.h"
#include "SnSerializationContext.h"
using namespace physx;
using namespace Sn;
PxBase* DeserializationContext::resolveReference(PxU32 kind, size_t reference) const
{
SerialObjectIndex objIndex;
if (kind == PX_SERIAL_REF_KIND_PXBASE)
{
const InternalPtrRefMap::Entry* entry0 = mInternalPtrReferencesMap.find(reference);
PX_ASSERT(entry0);
objIndex = entry0->second;
}
else if (kind == PX_SERIAL_REF_KIND_MATERIAL_IDX)
{
const InternalHandle16RefMap::Entry* entry0 = mInternalHandle16ReferencesMap.find(PxU16(reference));
PX_ASSERT(entry0);
objIndex = entry0->second;
}
else
{
return NULL;
}
bool isExternal;
PxU32 index = objIndex.getIndex(isExternal);
PxBase* base = NULL;
if (isExternal)
{
const ImportReference& entry = mImportReferences[index];
base = mExternalRefs->find(entry.id);
}
else
{
const ManifestEntry& entry = mManifestTable[index];
base = reinterpret_cast<PxBase*>(mObjectDataAddress + entry.offset);
}
PX_ASSERT(base);
return base;
}
void SerializationContext::registerReference(PxBase& serializable, PxU32 kind, size_t reference)
{
#if PX_CHECKED
if ((kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) == 0 && reference > 0xffff)
{
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "PxSerializationContext::registerReference: only 16 bit handles supported.");
return;
}
#endif
bool isExternal = mExternalRefs && mExternalRefs->contains(serializable);
PxU32 index;
if (isExternal)
{
PxSerialObjectId id = mExternalRefs->getId(serializable);
PX_ASSERT(id != PX_SERIAL_OBJECT_ID_INVALID);
if (const PxHashMap<PxSerialObjectId, PxU32>::Entry* entry = mImportReferencesMap.find(id))
{
index = entry->second;
}
else
{
index = mImportReferences.size();
mImportReferencesMap.insert(id, index);
mImportReferences.pushBack(ImportReference(id, serializable.getConcreteType()));
}
}
else
{
PX_ASSERT(mCollection.contains(serializable));
index = mObjToCollectionIndexMap[&serializable];
}
if (kind & PX_SERIAL_REF_KIND_PXBASE)
{
mInternalPtrReferencesMap[reference] = SerialObjectIndex(index, isExternal);
}
else if (kind & PX_SERIAL_REF_KIND_MATERIAL_IDX)
{
mInternalHandle16ReferencesMap[PxU16(reference)] = SerialObjectIndex(index, isExternal);
}
}

View File

@@ -0,0 +1,282 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_SERIALIZATION_CONTEXT_H
#define SN_SERIALIZATION_CONTEXT_H
#include "foundation/PxAssert.h"
#include "foundation/PxMemory.h"
#include "foundation/PxHash.h"
#include "foundation/PxUserAllocated.h"
#include "common/PxSerialFramework.h"
#include "extensions/PxDefaultStreams.h"
#include "CmCollection.h"
#include "CmUtils.h"
#include "../SnSerialUtils.h"
namespace physx
{
namespace Sn
{
struct ManifestEntry
{
PX_FORCE_INLINE ManifestEntry(PxU32 _offset, PxType _type)
{
PxMarkSerializedMemory(this, sizeof(ManifestEntry));
offset = _offset;
type = _type;
}
PX_FORCE_INLINE ManifestEntry() { PxMarkSerializedMemory(this, sizeof(ManifestEntry)); }
PX_FORCE_INLINE void operator =(const ManifestEntry& m)
{
PxMemCopy(this, &m, sizeof(ManifestEntry));
}
PxU32 offset;
PxType type;
};
struct ImportReference
{
PX_FORCE_INLINE ImportReference(PxSerialObjectId _id, PxType _type)
{
PxMarkSerializedMemory(this, sizeof(ImportReference));
id = _id;
type = _type;
}
PX_FORCE_INLINE ImportReference() { PxMarkSerializedMemory(this, sizeof(ImportReference)); }
PX_FORCE_INLINE void operator =(const ImportReference& m)
{
PxMemCopy(this, &m, sizeof(ImportReference));
}
PxSerialObjectId id;
PxType type;
};
#define SERIAL_OBJECT_INDEX_TYPE_BIT (1u<<31)
struct SerialObjectIndex
{
PX_FORCE_INLINE SerialObjectIndex(PxU32 index, bool external) { setIndex(index, external); }
PX_FORCE_INLINE SerialObjectIndex(const SerialObjectIndex& objIndex) : mObjIndex(objIndex.mObjIndex) {}
PX_FORCE_INLINE SerialObjectIndex() : mObjIndex(PX_INVALID_U32) {}
PX_FORCE_INLINE void setIndex(PxU32 index, bool external)
{
PX_ASSERT((index & SERIAL_OBJECT_INDEX_TYPE_BIT) == 0);
mObjIndex = index | (external ? SERIAL_OBJECT_INDEX_TYPE_BIT : 0);
}
PX_FORCE_INLINE PxU32 getIndex(bool& isExternal)
{
PX_ASSERT(mObjIndex != PX_INVALID_U32);
isExternal = (mObjIndex & SERIAL_OBJECT_INDEX_TYPE_BIT) > 0;
return mObjIndex & ~SERIAL_OBJECT_INDEX_TYPE_BIT;
}
PX_FORCE_INLINE bool operator < (const SerialObjectIndex& so) const
{
return mObjIndex < so.mObjIndex;
}
private:
PxU32 mObjIndex;
};
struct ExportReference
{
PX_FORCE_INLINE ExportReference(PxSerialObjectId _id, SerialObjectIndex _objIndex)
{
PxMarkSerializedMemory(this, sizeof(ExportReference));
id = _id;
objIndex = _objIndex;
}
PX_FORCE_INLINE ExportReference() { PxMarkSerializedMemory(this, sizeof(ExportReference)); }
PX_FORCE_INLINE void operator =(const ExportReference& m)
{
PxMemCopy(this, &m, sizeof(ExportReference));
}
PxSerialObjectId id;
SerialObjectIndex objIndex;
};
struct InternalReferencePtr
{
PX_FORCE_INLINE InternalReferencePtr() {}
PX_FORCE_INLINE InternalReferencePtr(size_t _reference, SerialObjectIndex _objIndex) :
reference(_reference),
objIndex(_objIndex)
#if PX_P64_FAMILY
,pad(PX_PADDING_32)
#endif
{
}
size_t reference;
SerialObjectIndex objIndex;
#if PX_P64_FAMILY
PxU32 pad;
#endif
};
struct InternalReferenceHandle16
{
PX_FORCE_INLINE InternalReferenceHandle16() {}
PX_FORCE_INLINE InternalReferenceHandle16(PxU16 _reference, SerialObjectIndex _objIndex) :
reference(_reference),
pad(PX_PADDING_16),
objIndex(_objIndex)
{
}
PxU16 reference;
PxU16 pad;
SerialObjectIndex objIndex;
};
typedef Cm::CollectionHashMap<size_t, SerialObjectIndex> InternalPtrRefMap;
typedef Cm::CollectionHashMap<PxU16, SerialObjectIndex> InternalHandle16RefMap;
class DeserializationContext : public PxDeserializationContext, public PxUserAllocated
{
PX_NOCOPY(DeserializationContext)
public:
DeserializationContext(const ManifestEntry* manifestTable,
const ImportReference* importReferences,
PxU8* objectDataAddress,
const InternalPtrRefMap& internalPtrReferencesMap,
const InternalHandle16RefMap& internalHandle16ReferencesMap,
const Cm::Collection* externalRefs,
PxU8* extraData)
: mManifestTable(manifestTable)
, mImportReferences(importReferences)
, mObjectDataAddress(objectDataAddress)
, mInternalPtrReferencesMap(internalPtrReferencesMap)
, mInternalHandle16ReferencesMap(internalHandle16ReferencesMap)
, mExternalRefs(externalRefs)
{
mExtraDataAddress = extraData;
}
virtual PxBase* resolveReference(PxU32 kind, size_t reference) const;
private:
//various pointers to deserialized data
const ManifestEntry* mManifestTable;
const ImportReference* mImportReferences;
PxU8* mObjectDataAddress;
//internal references maps for resolving references.
const InternalPtrRefMap& mInternalPtrReferencesMap;
const InternalHandle16RefMap& mInternalHandle16ReferencesMap;
//external collection for resolving import references.
const Cm::Collection* mExternalRefs;
//const PxU32 mPhysXVersion;
};
class SerializationContext : public PxSerializationContext, public PxUserAllocated
{
PX_NOCOPY(SerializationContext)
public:
SerializationContext(const Cm::Collection& collection, const Cm::Collection* externalRefs)
: mCollection(collection)
, mExternalRefs(externalRefs)
{
// fill object to collection index map (same ordering as manifest)
for (PxU32 i=0;i<mCollection.internalGetNbObjects();i++)
{
mObjToCollectionIndexMap[mCollection.internalGetObject(i)] = i;
}
}
virtual void writeData(const void* buffer, PxU32 size) { mMemStream.write(buffer, size); }
virtual PxU32 getTotalStoredSize() { return mMemStream.getSize(); }
virtual void alignData(PxU32 alignment = PX_SERIAL_ALIGN)
{
if(!alignment)
return;
PxI32 bytesToPad = PxI32(getPadding(mMemStream.getSize(), alignment));
static const PxI32 BUFSIZE = 64;
char buf[BUFSIZE];
PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
while(bytesToPad > 0)
{
mMemStream.write(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
bytesToPad -= BUFSIZE;
}
PX_ASSERT(!getPadding(getTotalStoredSize(), alignment));
}
virtual void writeName(const char*)
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, PX_FL,
"Cannot export names during exportData.");
}
const PxCollection& getCollection() const { return mCollection; }
virtual void registerReference(PxBase& serializable, PxU32 kind, size_t reference);
const PxArray<ImportReference>& getImportReferences() { return mImportReferences; }
InternalPtrRefMap& getInternalPtrReferencesMap() { return mInternalPtrReferencesMap; }
InternalHandle16RefMap& getInternalHandle16ReferencesMap() { return mInternalHandle16ReferencesMap; }
PxU32 getSize() const { return mMemStream.getSize(); }
PxU8* getData() const { return mMemStream.getData(); }
private:
//import reference map for unique registration of import references and corresponding buffer.
PxHashMap<PxSerialObjectId, PxU32> mImportReferencesMap;
PxArray<ImportReference> mImportReferences;
//maps for unique registration of internal references
InternalPtrRefMap mInternalPtrReferencesMap;
InternalHandle16RefMap mInternalHandle16ReferencesMap;
//map for quick lookup of manifest index.
PxHashMap<const PxBase*, PxU32> mObjToCollectionIndexMap;
//collection and externalRefs collection for assigning references.
const Cm::Collection& mCollection;
const Cm::Collection* mExternalRefs;
PxDefaultMemoryOutputStream mMemStream;
};
} // namespace Sn
}
#endif

View File

@@ -0,0 +1,84 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_FILE_H
#define SN_FILE_H
// fopen_s - returns 0 on success, non-zero on failure
#if PX_WINDOWS_FAMILY
#include <stdio.h>
namespace physx
{
namespace sn
{
PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode)
{
static const PxU32 MAX_LEN = 300;
char buf[MAX_LEN+1];
PxU32 i;
for(i = 0; i<MAX_LEN && name[i]; i++)
buf[i] = name[i] == '/' ? '\\' : name[i];
buf[i] = 0;
return i == MAX_LEN ? -1 : ::fopen_s(file, buf, mode);
};
} // namespace sn
} // namespace physx
#elif PX_UNIX_FAMILY || PX_SWITCH
#include <stdio.h>
namespace physx
{
namespace sn
{
PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode)
{
FILE* fp = ::fopen(name, mode);
if(fp)
{
*file = fp;
return PxI32(0);
}
return -1;
}
} // namespace sn
} // namespace physx
#else
#error "Platform not supported!"
#endif
#endif //SN_FILE_H

View File

@@ -0,0 +1,131 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "extensions/PxSerialization.h"
#include "foundation/PxPhysicsVersion.h"
#include "SnSerialUtils.h"
#include "foundation/PxString.h"
#include "foundation/PxBasicTemplates.h"
using namespace physx;
namespace
{
#define SN_NUM_BINARY_PLATFORMS 9
const PxU32 sBinaryPlatformTags[SN_NUM_BINARY_PLATFORMS] =
{
PX_MAKE_FOURCC('W','_','3','2'),
PX_MAKE_FOURCC('W','_','6','4'),
PX_MAKE_FOURCC('L','_','3','2'),
PX_MAKE_FOURCC('L','_','6','4'),
PX_MAKE_FOURCC('M','_','3','2'),
PX_MAKE_FOURCC('M','_','6','4'),
PX_MAKE_FOURCC('N','X','3','2'),
PX_MAKE_FOURCC('N','X','6','4'),
PX_MAKE_FOURCC('L','A','6','4')
};
const char* sBinaryPlatformNames[SN_NUM_BINARY_PLATFORMS] =
{
"win32",
"win64",
"linux32",
"linux64",
"mac32",
"mac64",
"switch32",
"switch64",
"linuxaarch64"
};
}
namespace physx { namespace Sn {
PxU32 getBinaryPlatformTag()
{
#if PX_WINDOWS && PX_X86
return sBinaryPlatformTags[0];
#elif PX_WINDOWS && PX_X64
return sBinaryPlatformTags[1];
#elif PX_LINUX && PX_X86
return sBinaryPlatformTags[2];
#elif PX_LINUX && PX_X64
return sBinaryPlatformTags[3];
#elif PX_OSX && PX_X86
return sBinaryPlatformTags[4];
#elif PX_OSX && PX_X64
return sBinaryPlatformTags[5];
#elif PX_SWITCH && !PX_A64
return sBinaryPlatformTags[6];
#elif PX_SWITCH && PX_A64
return sBinaryPlatformTags[7];
#elif PX_LINUX && PX_A64
return sBinaryPlatformTags[8];
#else
#error Unknown binary platform
#endif
}
bool isBinaryPlatformTagValid(physx::PxU32 platformTag)
{
PxU32 platformIndex = 0;
while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++;
return platformIndex < SN_NUM_BINARY_PLATFORMS;
}
const char* getBinaryPlatformName(physx::PxU32 platformTag)
{
PxU32 platformIndex = 0;
while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++;
return (platformIndex == SN_NUM_BINARY_PLATFORMS) ? "unknown" : sBinaryPlatformNames[platformIndex];
}
const char* getBinaryVersionGuid()
{
PX_COMPILE_TIME_ASSERT(sizeof(PX_BINARY_SERIAL_VERSION) == SN_BINARY_VERSION_GUID_NUM_CHARS + 1);
return PX_BINARY_SERIAL_VERSION;
}
bool checkCompatibility(const char* binaryVersionGuidCandidate)
{
for(PxU32 i=0; i<SN_BINARY_VERSION_GUID_NUM_CHARS; i++)
{
if (binaryVersionGuidCandidate[i] != PX_BINARY_SERIAL_VERSION[i])
{
return false;
}
}
return true;
}
} // Sn
} // physx

View File

@@ -0,0 +1,56 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_SERIAL_UTILS_H
#define SN_SERIAL_UTILS_H
#define SN_BINARY_VERSION_GUID_NUM_CHARS 32
namespace physx
{
namespace Sn
{
PxU32 getBinaryPlatformTag();
bool isBinaryPlatformTagValid(PxU32 platformTag);
const char* getBinaryPlatformName(PxU32 platformTag);
const char* getBinaryVersionGuid();
bool checkCompatibility(const char* binaryVersionGuidCandidate);
PX_INLINE PxU32 getPadding(size_t value, PxU32 alignment)
{
const PxU32 mask = alignment - 1;
const PxU32 overhead = PxU32(value) & mask;
return (alignment - overhead) & mask;
}
}
}
#endif

View File

@@ -0,0 +1,303 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxSerializer.h"
#include "extensions/PxConstraintExt.h"
#include "foundation/PxPhysicsVersion.h"
#include "PxPhysicsAPI.h"
#include "SnSerializationRegistry.h"
#include "SnSerialUtils.h"
#include "ExtSerialization.h"
#include "CmCollection.h"
using namespace physx;
using namespace Sn;
namespace
{
struct RequiresCallback : public PxProcessPxBaseCallback
{
RequiresCallback(physx::PxCollection& c) : collection(c) {}
void process(PxBase& base)
{
if(!collection.contains(base))
collection.add(base);
}
PxCollection& collection;
PX_NOCOPY(RequiresCallback)
};
struct CompleteCallback : public PxProcessPxBaseCallback
{
CompleteCallback(physx::PxCollection& r, physx::PxCollection& c, const physx::PxCollection* e) :
required(r), complete(c), external(e) {}
void process(PxBase& base)
{
if(complete.contains(base) || (external && external->contains(base)))
return;
if(!required.contains(base))
required.add(base);
}
PxCollection& required;
PxCollection& complete;
const PxCollection* external;
PX_NOCOPY(CompleteCallback)
};
void getRequiresCollection(PxCollection& required, PxCollection& collection, PxCollection& complete, const PxCollection* external, PxSerializationRegistry& sr, bool followJoints)
{
CompleteCallback callback(required, complete, external);
for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
{
PxBase& s = collection.getObject(i);
const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
PX_ASSERT(serializer);
serializer->requiresObjects(s, callback);
if(followJoints)
{
PxRigidActor* actor = s.is<PxRigidActor>();
if(actor)
{
PxArray<PxConstraint*> objects(actor->getNbConstraints());
actor->getConstraints(objects.begin(), objects.size());
for(PxU32 j=0;j<objects.size();j++)
{
PxU32 typeId;
PxJoint* joint = reinterpret_cast<PxJoint*>(objects[j]->getExternalReference(typeId));
if(typeId == PxConstraintExtIDs::eJOINT)
{
const PxSerializer* sj = sr.getSerializer(joint->getConcreteType());
PX_ASSERT(sj);
sj->requiresObjects(*joint, callback);
if(!required.contains(*joint))
required.add(*joint);
}
}
}
}
}
}
}
bool PxSerialization::isSerializable(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalReferences)
{
PxCollection* subordinateCollection = PxCreateCollection();
PX_ASSERT(subordinateCollection);
for(PxU32 i = 0; i < collection.getNbObjects(); ++i)
{
PxBase& s = collection.getObject(i);
const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
PX_ASSERT(serializer);
if(serializer->isSubordinate())
subordinateCollection->add(s);
if(externalReferences)
{
PxSerialObjectId id = collection.getId(s);
if(id != PX_SERIAL_OBJECT_ID_INVALID)
{
PxBase* object = externalReferences->find(id);
if(object && (object != &s))
{
subordinateCollection->release();
return PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: Reference id %llu used both in current collection and in externalReferences. "
"Please use unique identifiers.", id);
}
}
}
}
PxCollection* requiresCollection = PxCreateCollection();
PX_ASSERT(requiresCollection);
RequiresCallback requiresCallback0(*requiresCollection);
for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
{
PxBase& s = collection.getObject(i);
const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
PX_ASSERT(serializer);
serializer->requiresObjects(s, requiresCallback0);
Cm::Collection* cmRequiresCollection = static_cast<Cm::Collection*>(requiresCollection);
for(PxU32 j = 0; j < cmRequiresCollection->getNbObjects(); ++j)
{
PxBase& s0 = cmRequiresCollection->getObject(j);
if(subordinateCollection->contains(s0))
{
subordinateCollection->remove(s0);
continue;
}
bool requiredIsInCollection = collection.contains(s0);
if(!requiredIsInCollection)
{
if(externalReferences)
{
if(!externalReferences->contains(s0))
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: Object of type %s references a missing object of type %s. "
"The missing object needs to be added to either the current collection or the externalReferences collection.",
s.getConcreteTypeName(), s0.getConcreteTypeName());
}
else if(externalReferences->getId(s0) == PX_SERIAL_OBJECT_ID_INVALID)
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: Object of type %s in externalReferences collection requires an id.",
s0.getConcreteTypeName());
}
else
continue;
}
else
{
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: Object of type %s references a missing serial object of type %s. "
"Please completed the collection or specify an externalReferences collection containing the object.",
s.getConcreteTypeName(), s0.getConcreteTypeName());
}
subordinateCollection->release();
requiresCollection->release();
return false;
}
}
cmRequiresCollection->mObjects.clear();
}
requiresCollection->release();
PxU32 numOrphans = subordinateCollection->getNbObjects();
for(PxU32 j = 0; j < numOrphans; ++j)
{
PxBase& subordinate = subordinateCollection->getObject(j);
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: An object of type %s is subordinate but not required "
"by other objects in the collection (orphan). Please remove the object from the collection or add its owner.",
subordinate.getConcreteTypeName());
}
subordinateCollection->release();
if(numOrphans>0)
return false;
if(externalReferences)
{
PxCollection* oppositeRequiresCollection = PxCreateCollection();
PX_ASSERT(oppositeRequiresCollection);
RequiresCallback requiresCallback(*oppositeRequiresCollection);
for (PxU32 i = 0; i < externalReferences->getNbObjects(); ++i)
{
PxBase& s = externalReferences->getObject(i);
const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
PX_ASSERT(serializer);
serializer->requiresObjects(s, requiresCallback);
Cm::Collection* cmCollection = static_cast<Cm::Collection*>(oppositeRequiresCollection);
for(PxU32 j = 0; j < cmCollection->getNbObjects(); ++j)
{
PxBase& s0 = cmCollection->getObject(j);
if(collection.contains(s0))
{
oppositeRequiresCollection->release();
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::isSerializable: Object of type %s in externalReferences references an object "
"of type %s in collection (circular dependency).",
s.getConcreteTypeName(), s0.getConcreteTypeName());
return false;
}
}
cmCollection->mObjects.clear();
}
oppositeRequiresCollection->release();
}
return true;
}
void PxSerialization::complete(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* exceptFor, bool followJoints)
{
PxCollection* curCollection = PxCreateCollection();
PX_ASSERT(curCollection);
curCollection->add(collection);
PxCollection* requiresCollection = PxCreateCollection();
PX_ASSERT(requiresCollection);
do
{
getRequiresCollection(*requiresCollection, *curCollection, collection, exceptFor, sr, followJoints);
collection.add(*requiresCollection);
PxCollection* swap = curCollection;
curCollection = requiresCollection;
requiresCollection = swap;
(static_cast<Cm::Collection*>(requiresCollection))->mObjects.clear();
}while(curCollection->getNbObjects() > 0);
requiresCollection->release();
curCollection->release();
}
void PxSerialization::createSerialObjectIds(PxCollection& collection, const PxSerialObjectId base)
{
PxSerialObjectId localBase = base;
PxU32 nbObjects = collection.getNbObjects();
for (PxU32 i = 0; i < nbObjects; ++i)
{
while(collection.find(localBase))
{
localBase++;
}
PxBase& s = collection.getObject(i);
if(PX_SERIAL_OBJECT_ID_INVALID == collection.getId(s))
{
collection.addId(s, localBase);
localBase++;
}
}
}

View File

@@ -0,0 +1,270 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "common/PxSerializer.h"
#include "foundation/PxString.h"
#include "PxPhysics.h"
#include "PxPhysicsSerialization.h"
#include "PxArticulationLink.h"
#include "SnSerializationRegistry.h"
#include "ExtSerialization.h"
#include "CmCollection.h"
using namespace physx;
namespace
{
class CollectionSorter : public PxProcessPxBaseCallback
{
typedef PxPair<PxBase*, PxSerialObjectId> Object;
class Element
{
public:
Object object;
PxArray<PxU32> children;
bool isFinished;
Element(PxBase* obj = NULL) : object(obj, PX_SERIAL_OBJECT_ID_INVALID), isFinished(false) {}
};
public:
CollectionSorter(Cm::Collection& collection, Sn::SerializationRegistry& sr, bool isRepx) : mCollection(collection), mSr(sr), mIsRepx(isRepx) {}
virtual ~CollectionSorter(){}
void process(PxBase& base)
{
addChild(&base);
//ArticulationLink is not a repx serializer, so should require Articulation here
if( mIsRepx && PxConcreteType::eARTICULATION_LINK == base.getConcreteType() )
{
PxArticulationLink* link = static_cast<PxArticulationLink*>(&base);
PxBase* a = reinterpret_cast<PxBase*>(&link->getArticulation());
if(mCurElement->object.first != a ) //don't require itself
addChild(a);
}
}
void sort()
{
Element element;
PxU32 i;
PxU32 nbObject = mCollection.internalGetNbObjects();
const Cm::Collection::ObjectToIdMap::Entry* objectdatas = mCollection.internalGetObjects();
for( i = 0; i < nbObject; ++i )
{
element.object.first = objectdatas[i].first;
element.object.second = objectdatas[i].second;
mObjToIdMap.insert(objectdatas[i].first, mElements.size());
mElements.pushBack(element);
}
for( i = 0; i < nbObject; ++i )
{
mCurElement = &mElements[i];
const PxSerializer* serializer = mSr.getSerializer(mCurElement->object.first->getConcreteType());
PX_ASSERT(serializer);
serializer->requiresObjects(*mCurElement->object.first, *this);
}
for( i = 0; i < nbObject; ++i )
{
if( mElements[i].isFinished )
continue;
AddElement(mElements[i]);
}
mCollection.mObjects.clear();
for(PxArray<Object>::Iterator o = mSorted.begin(); o != mSorted.end(); ++o )
{
mCollection.internalAdd(o->first, o->second);
}
}
void AddElement(Element& e)
{
if( !e.isFinished )
{
for( PxArray<PxU32>::Iterator child = e.children.begin(); child != e.children.end(); ++child )
{
AddElement(mElements[*child]);
}
mSorted.pushBack(e.object);
e.isFinished = true;
}
}
private:
PX_INLINE void addChild(PxBase* base)
{
PX_ASSERT(mCurElement);
const PxHashMap<PxBase*, PxU32>::Entry* entry = mObjToIdMap.find(base);
if(entry)
mCurElement->children.pushBack(entry->second);
}
CollectionSorter& operator=(const CollectionSorter&);
PxHashMap<PxBase*, PxU32> mObjToIdMap;
PxArray<Element> mElements;
Cm::Collection& mCollection;
Sn::SerializationRegistry& mSr;
PxArray<Object> mSorted;
Element* mCurElement;
bool mIsRepx;
};
}
namespace physx { namespace Sn {
SerializationRegistry::SerializationRegistry(PxPhysics& physics)
: mPhysics(physics)
{
PxRegisterPhysicsSerializers(*this);
Ext::RegisterExtensionsSerializers(*this);
}
SerializationRegistry::~SerializationRegistry()
{
PxUnregisterPhysicsSerializers(*this);
Ext::UnregisterExtensionsSerializers(*this);
if(mSerializers.size() > 0)
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::release(): some registered PxSerializer instances were not unregistered");
}
if(mRepXSerializers.size() > 0)
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::release(): some registered PxRepXSerializer instances were not unregistered");
}
}
void SerializationRegistry::registerSerializer(PxType type, PxSerializer& serializer)
{
if(mSerializers.find(type))
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::registerSerializer: Type %d has already been registered", type);
}
mSerializers.insert(type, &serializer);
}
PxSerializer* SerializationRegistry::unregisterSerializer(PxType type)
{
const SerializerMap::Entry* e = mSerializers.find(type);
PxSerializer* s = e ? e->second : NULL;
if(!mSerializers.erase(type))
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::unregisterSerializer: failed to find PxSerializer instance for type %d", type);
}
return s;
}
const PxSerializer* SerializationRegistry::getSerializer(PxType type) const
{
const SerializerMap::Entry* e = mSerializers.find(type);
#if PX_CHECKED
if (!e)
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::getSerializer: failed to find PxSerializer instance for type %d", type);
}
#endif
return e ? e->second : NULL;
}
PxType SerializationRegistry::getSerializerType(PxU32 index) const
{
PX_ASSERT(index < mSerializers.size());
return mSerializers.getEntries()[index].first;
}
const char* SerializationRegistry::getSerializerName(PxU32 index) const
{
PX_ASSERT(index < mSerializers.size());
return mSerializers.getEntries()[index].second->getConcreteTypeName();
}
void SerializationRegistry::registerRepXSerializer(PxType type, PxRepXSerializer& serializer)
{
if(mRepXSerializers.find(type))
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::registerRepXSerializer: Type %d has already been registered", type);
}
mRepXSerializers.insert(type, &serializer);
}
PxRepXSerializer* SerializationRegistry::getRepXSerializer(const char* typeName) const
{
SerializationRegistry* sr = const_cast<SerializationRegistry*>(this);
for( RepXSerializerMap::Iterator iter = sr->mRepXSerializers.getIterator(); !iter.done(); ++iter)
{
if ( physx::Pxstricmp( iter->second->getTypeName(), typeName ) == 0 )
return iter->second;
}
return NULL;
}
PxRepXSerializer* SerializationRegistry::unregisterRepXSerializer(PxType type)
{
const RepXSerializerMap::Entry* e = mRepXSerializers.find(type);
PxRepXSerializer* s = e ? e->second : NULL;
if(!mRepXSerializers.erase(type))
{
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
"PxSerializationRegistry::unregisterRepXSerializer: failed to find PxRepXSerializer instance for type %d", type);
}
return s;
}
void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx)
{
CollectionSorter sorter(collection, sr, isRepx);
sorter.sort();
}
} // Sn
PxSerializationRegistry* PxSerialization::createSerializationRegistry(PxPhysics& physics)
{
return PX_NEW(Sn::SerializationRegistry)(physics);
}
} // physx

View File

@@ -0,0 +1,88 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_SERIALIZATION_REGISTRY_H
#define SN_SERIALIZATION_REGISTRY_H
#include "extensions/PxSerialization.h"
#include "extensions/PxRepXSerializer.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxHashMap.h"
#include "foundation/PxArray.h"
namespace physx
{
namespace Cm { class Collection; }
namespace Sn {
class SerializationRegistry : public PxSerializationRegistry, public PxUserAllocated
{
public:
SerializationRegistry(PxPhysics& physics);
virtual ~SerializationRegistry();
virtual void release(){ PX_DELETE_THIS; }
PxPhysics& getPhysics() const { return mPhysics; }
//binary
void registerSerializer(PxType type, PxSerializer& serializer);
PxSerializer* unregisterSerializer(PxType type);
const PxSerializer* getSerializer(PxType type) const;
const char* getSerializerName(PxU32 index) const;
PxType getSerializerType(PxU32 index) const;
PxU32 getNbSerializers() const { return mSerializers.size(); }
//repx
void registerRepXSerializer(PxType type, PxRepXSerializer& serializer);
PxRepXSerializer* getRepXSerializer(const char* typeName) const;
PxRepXSerializer* unregisterRepXSerializer(PxType type);
protected:
SerializationRegistry &operator=(const SerializationRegistry &);
private:
typedef PxCoalescedHashMap<PxType, PxSerializer*> SerializerMap;
typedef PxHashMap<PxType, PxRepXSerializer*> RepXSerializerMap;
PxPhysics& mPhysics;
SerializerMap mSerializers;
RepXSerializerMap mRepXSerializers;
};
void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx);
} // Sn
} // physx
#endif

View File

@@ -0,0 +1,838 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxAssert.h"
#include "foundation/PxMemory.h"
#include "foundation/PxFoundationConfig.h"
#include "foundation/PxAllocator.h"
#include "PsFastXml.h"
#include <stdio.h>
#include <string.h>
#include <new>
#include <ctype.h>
using namespace physx;
namespace
{
#define MIN_CLOSE_COUNT 2
#define DEFAULT_READ_BUFFER_SIZE (16 * 1024)
#define NUM_ENTITY 5
struct Entity
{
const char* str;
unsigned int strLength;
char chr;
};
static const Entity entity[NUM_ENTITY] = {
{ "&lt;", 4, '<' }, { "&amp;", 5, '&' }, { "&gt;", 4, '>' }, { "&quot;", 6, '\"' }, { "&apos;", 6, '\'' }
};
class MyFastXml : public physx::shdfnd::FastXml
{
public:
enum CharType
{
CT_DATA,
CT_EOF,
CT_SOFT,
CT_END_OF_ELEMENT, // either a forward slash or a greater than symbol
CT_END_OF_LINE
};
MyFastXml(Callback* c)
{
mStreamFromMemory = true;
mCallback = c;
memset(mTypes, CT_DATA, sizeof(mTypes));
mTypes[0] = CT_EOF;
mTypes[uint8_t(' ')] = mTypes[uint8_t('\t')] = CT_SOFT;
mTypes[uint8_t('/')] = mTypes[uint8_t('>')] = mTypes[uint8_t('?')] = CT_END_OF_ELEMENT;
mTypes[uint8_t('\n')] = mTypes[uint8_t('\r')] = CT_END_OF_LINE;
mError = 0;
mStackIndex = 0;
mFileBuf = NULL;
mReadBufferEnd = NULL;
mReadBuffer = NULL;
mReadBufferSize = DEFAULT_READ_BUFFER_SIZE;
mOpenCount = 0;
mLastReadLoc = 0;
for(uint32_t i = 0; i < (MAX_STACK + 1); i++)
{
mStack[i] = NULL;
mStackAllocated[i] = false;
}
}
char* processClose(char c, const char* element, char* scan, int32_t argc, const char** argv,
FastXml::Callback* iface, bool& isError)
{
AttributePairs attr(argc, argv);
if(c == '/' || c == '?')
{
char* slash = const_cast<char*>(static_cast<const char*>(strchr(element, c)));
if(slash)
*slash = 0;
if(c == '?' && strcmp(element, "xml") == 0)
{
isError = true;
if(!iface->processXmlDeclaration(attr, 0, mLineNo))
return NULL;
}
else
{
if(!iface->processElement(element, 0, attr, mLineNo))
{
isError = true;
mError = "User aborted the parsing process";
return NULL;
}
pushElement(element);
const char* close = popElement();
if(!iface->processClose(close, mStackIndex, isError))
{
return NULL;
}
}
if(!slash)
++scan;
}
else
{
scan = skipNextData(scan);
char* data = scan; // this is the data portion of the element, only copies memory if we encounter line feeds
char* dest_data = 0;
while(*scan && *scan != '<')
{
if(getCharType(scan) == CT_END_OF_LINE)
{
if(*scan == '\r')
mLineNo++;
dest_data = scan;
*dest_data++ = ' '; // replace the linefeed with a space...
scan = skipNextData(scan);
while(*scan && *scan != '<')
{
if(getCharType(scan) == CT_END_OF_LINE)
{
if(*scan == '\r')
mLineNo++;
*dest_data++ = ' '; // replace the linefeed with a space...
scan = skipNextData(scan);
}
else
{
*dest_data++ = *scan++;
}
}
break;
}
else if('&' == *scan)
{
dest_data = scan;
while(*scan && *scan != '<')
{
if('&' == *scan)
{
if(*(scan + 1) && *(scan + 1) == '#' && *(scan + 2))
{
if(*(scan + 2) == 'x')
{
// Hexadecimal.
if(!*(scan + 3))
break;
char* q = scan + 3;
q = strchr(q, ';');
if(!q || !*q)
PX_ASSERT(0);
--q;
char ch = char(*q > '9' ? (tolower(*q) - 'a' + 10) : *q - '0');
if(*(--q) != tolower('x'))
ch |= char(*q > '9' ? (tolower(*q) - 'a' + 10) : *q - '0') << 4;
*dest_data++ = ch;
}
else
{
// Decimal.
if(!*(scan + 2))
break;
const char* q = scan + 2;
q = strchr(q, ';');
if(!q || !*q)
PX_ASSERT(0);
--q;
char ch = *q - '0';
if(*(--q) != '#')
ch |= (*q - '0') * 10;
*dest_data++ = ch;
}
char* start = scan;
char* end = strchr(start, ';');
if(end)
{
*end = 0;
scan = end + 1;
}
continue;
}
for(int i = 0; i < NUM_ENTITY; ++i)
{
if(strncmp(entity[i].str, scan, entity[i].strLength) == 0)
{
*dest_data++ = entity[i].chr;
scan += entity[i].strLength;
break;
}
}
}
else
{
*dest_data++ = *scan++;
}
}
break;
}
else
++scan;
}
if(*scan == '<')
{
if(scan[1] != '/')
{
PX_ASSERT(mOpenCount > 0);
mOpenCount--;
}
if(dest_data)
{
*dest_data = 0;
}
else
{
*scan = 0;
}
scan++; // skip it..
if(*data == 0)
data = 0;
if(!iface->processElement(element, data, attr, mLineNo))
{
isError = true;
mError = "User aborted the parsing process";
return NULL;
}
pushElement(element);
// check for the comment use case...
if(scan[0] == '!' && scan[1] == '-' && scan[2] == '-')
{
scan += 3;
while(*scan && *scan == ' ')
++scan;
char* comment = scan;
char* comment_end = strstr(scan, "-->");
if(comment_end)
{
*comment_end = 0;
scan = comment_end + 3;
if(!iface->processComment(comment))
{
isError = true;
mError = "User aborted the parsing process";
return NULL;
}
}
}
else if(*scan == '/')
{
scan = processClose(scan, iface, isError);
if(scan == NULL)
{
return NULL;
}
}
}
else
{
isError = true;
mError = "Data portion of an element wasn't terminated properly";
return NULL;
}
}
if(mOpenCount < MIN_CLOSE_COUNT)
{
scan = readData(scan);
}
return scan;
}
char* processClose(char* scan, FastXml::Callback* iface, bool& isError)
{
const char* start = popElement(), *close = start;
if(scan[1] != '>')
{
scan++;
close = scan;
while(*scan && *scan != '>')
scan++;
*scan = 0;
}
if(0 != strcmp(start, close))
{
isError = true;
mError = "Open and closing tags do not match";
return 0;
}
if(!iface->processClose(close, mStackIndex, isError))
{
// we need to set the read pointer!
uint32_t offset = uint32_t(mReadBufferEnd - scan) - 1;
uint32_t readLoc = mLastReadLoc - offset;
mFileBuf->seek(readLoc);
return NULL;
}
++scan;
return scan;
}
virtual bool processXml(physx::PxInputData& fileBuf, bool streamFromMemory)
{
releaseMemory();
mFileBuf = &fileBuf;
mStreamFromMemory = streamFromMemory;
return processXml(mCallback);
}
// if we have finished processing the data we had pending..
char* readData(char* scan)
{
for(uint32_t i = 0; i < (mStackIndex + 1); i++)
{
if(!mStackAllocated[i])
{
const char* text = mStack[i];
if(text)
{
uint32_t tlen = uint32_t(strlen(text));
mStack[i] = static_cast<const char*>(mCallback->allocate(tlen + 1));
PxMemCopy(const_cast<void*>(static_cast<const void*>(mStack[i])), text, tlen + 1);
mStackAllocated[i] = true;
}
}
}
if(!mStreamFromMemory)
{
if(scan == NULL)
{
uint32_t seekLoc = mFileBuf->tell();
mReadBufferSize = (mFileBuf->getLength() - seekLoc);
}
else
{
return scan;
}
}
if(mReadBuffer == NULL)
{
mReadBuffer = static_cast<char*>(mCallback->allocate(mReadBufferSize + 1));
}
uint32_t offset = 0;
uint32_t readLen = mReadBufferSize;
if(scan)
{
offset = uint32_t(scan - mReadBuffer);
uint32_t copyLen = mReadBufferSize - offset;
if(copyLen)
{
PX_ASSERT(scan >= mReadBuffer);
memmove(mReadBuffer, scan, copyLen);
mReadBuffer[copyLen] = 0;
readLen = mReadBufferSize - copyLen;
}
offset = copyLen;
}
uint32_t readCount = mFileBuf->read(&mReadBuffer[offset], readLen);
while(readCount > 0)
{
mReadBuffer[readCount + offset] = 0; // end of string terminator...
mReadBufferEnd = &mReadBuffer[readCount + offset];
const char* scan_ = &mReadBuffer[offset];
while(*scan_)
{
if(*scan_ == '<' && scan_[1] != '/')
{
mOpenCount++;
}
scan_++;
}
if(mOpenCount < MIN_CLOSE_COUNT)
{
uint32_t oldSize = uint32_t(mReadBufferEnd - mReadBuffer);
mReadBufferSize = mReadBufferSize * 2;
char* oldReadBuffer = mReadBuffer;
mReadBuffer = static_cast<char*>(mCallback->allocate(mReadBufferSize + 1));
PxMemCopy(mReadBuffer, oldReadBuffer, oldSize);
mCallback->deallocate(oldReadBuffer);
offset = oldSize;
uint32_t readSize = mReadBufferSize - oldSize;
readCount = mFileBuf->read(&mReadBuffer[offset], readSize);
if(readCount == 0)
break;
}
else
{
break;
}
}
mLastReadLoc = mFileBuf->tell();
return mReadBuffer;
}
bool processXml(FastXml::Callback* iface)
{
bool ret = true;
const int MAX_ATTRIBUTE = 2048; // can't imagine having more than 2,048 attributes in a single element right?
mLineNo = 1;
char* element, *scan = readData(0);
while(*scan)
{
scan = skipNextData(scan);
if(*scan == 0)
break;
if(*scan == '<')
{
if(scan[1] != '/')
{
PX_ASSERT(mOpenCount > 0);
mOpenCount--;
}
scan++;
if(*scan == '?') // Allow xml declarations
{
scan++;
}
else if(scan[0] == '!' && scan[1] == '-' && scan[2] == '-')
{
scan += 3;
while(*scan && *scan == ' ')
scan++;
char* comment = scan, *comment_end = strstr(scan, "-->");
if(comment_end)
{
*comment_end = 0;
scan = comment_end + 3;
if(!iface->processComment(comment))
{
mError = "User aborted the parsing process";
return false;
}
}
continue;
}
else if(scan[0] == '!') // Allow doctype
{
scan++;
// DOCTYPE syntax differs from usual XML so we parse it here
// Read DOCTYPE
const char* tag = "DOCTYPE";
if(!strstr(scan, tag))
{
mError = "Invalid DOCTYPE";
return false;
}
scan += strlen(tag);
// Skip whites
while(CT_SOFT == getCharType(scan))
++scan;
// Read rootElement
const char* rootElement = scan;
while(CT_DATA == getCharType(scan))
++scan;
char* endRootElement = scan;
// TODO: read remaining fields (fpi, uri, etc.)
while(CT_END_OF_ELEMENT != getCharType(scan++))
;
*endRootElement = 0;
if(!iface->processDoctype(rootElement, 0, 0, 0))
{
mError = "User aborted the parsing process";
return false;
}
continue; // Restart loop
}
}
if(*scan == '/')
{
bool isError = false;
scan = processClose(scan, iface, isError);
if(!scan)
{
if(isError)
{
mError = "User aborted the parsing process";
}
return !isError;
}
}
else
{
if(*scan == '?')
scan++;
element = scan;
int32_t argc = 0;
const char* argv[MAX_ATTRIBUTE];
bool close;
scan = nextSoftOrClose(scan, close);
if(close)
{
char c = *(scan - 1);
if(c != '?' && c != '/')
{
c = '>';
}
*scan++ = 0;
bool isError = false;
scan = processClose(c, element, scan, argc, argv, iface, isError);
if(!scan)
{
if(isError)
{
mError = "User aborted the parsing process";
}
return !isError;
}
}
else
{
if(*scan == 0)
{
return ret;
}
*scan = 0; // place a zero byte to indicate the end of the element name...
scan++;
while(*scan)
{
scan = skipNextData(scan); // advance past any soft seperators (tab or space)
if(getCharType(scan) == CT_END_OF_ELEMENT)
{
char c = *scan++;
if('?' == c)
{
if('>' != *scan) //?>
{
PX_ASSERT(0);
return false;
}
scan++;
}
bool isError = false;
scan = processClose(c, element, scan, argc, argv, iface, isError);
if(!scan)
{
if(isError)
{
mError = "User aborted the parsing process";
}
return !isError;
}
break;
}
else
{
if(argc >= MAX_ATTRIBUTE)
{
mError = "encountered too many attributes";
return false;
}
argv[argc] = scan;
scan = nextSep(scan); // scan up to a space, or an equal
if(*scan)
{
if(*scan != '=')
{
*scan = 0;
scan++;
while(*scan && *scan != '=')
scan++;
if(*scan == '=')
scan++;
}
else
{
*scan = 0;
scan++;
}
if(*scan) // if not eof...
{
scan = skipNextData(scan);
if(*scan == '"')
{
scan++;
argc++;
argv[argc] = scan;
argc++;
while(*scan && *scan != 34)
scan++;
if(*scan == '"')
{
*scan = 0;
scan++;
}
else
{
mError = "Failed to find closing quote for attribute";
return false;
}
}
else
{
// mError = "Expected quote to begin attribute";
// return false;
// PH: let's try to have a more graceful fallback
argc--;
while(*scan != '/' && *scan != '>' && *scan != 0)
scan++;
}
}
} // if( *scan )
} // if ( mTypes[*scan]
} // if( close )
} // if( *scan == '/'
} // while( *scan )
}
if(mStackIndex)
{
mError = "Invalid file format";
return false;
}
return ret;
}
const char* getError(int32_t& lineno)
{
const char* ret = mError;
lineno = mLineNo;
mError = 0;
return ret;
}
virtual void release()
{
Callback* c = mCallback; // get the user allocator interface
MyFastXml* f = this; // cast the this pointer
f->~MyFastXml(); // explicitely invoke the destructor for this class
c->deallocate(f); // now free up the memory associated with it.
}
private:
virtual ~MyFastXml()
{
releaseMemory();
}
PX_INLINE void releaseMemory()
{
mFileBuf = NULL;
mCallback->deallocate(mReadBuffer);
mReadBuffer = NULL;
mStackIndex = 0;
mReadBufferEnd = NULL;
mOpenCount = 0;
mLastReadLoc = 0;
mError = NULL;
for(uint32_t i = 0; i < (mStackIndex + 1); i++)
{
if(mStackAllocated[i])
{
mCallback->deallocate(const_cast<void*>(static_cast<const void*>(mStack[i])));
mStackAllocated[i] = false;
}
mStack[i] = NULL;
}
}
PX_INLINE CharType getCharType(char* scan) const
{
return mTypes[uint8_t(*scan)];
}
PX_INLINE char* nextSoftOrClose(char* scan, bool& close)
{
while(*scan && getCharType(scan) != CT_SOFT && *scan != '>')
scan++;
close = *scan == '>';
return scan;
}
PX_INLINE char* nextSep(char* scan)
{
while(*scan && getCharType(scan) != CT_SOFT && *scan != '=')
scan++;
return scan;
}
PX_INLINE char* skipNextData(char* scan)
{
// while we have data, and we encounter soft seperators or line feeds...
while(*scan && (getCharType(scan) == CT_SOFT || getCharType(scan) == CT_END_OF_LINE))
{
if(*scan == '\n')
mLineNo++;
scan++;
}
return scan;
}
void pushElement(const char* element)
{
PX_ASSERT(mStackIndex < uint32_t(MAX_STACK));
if(mStackIndex < uint32_t(MAX_STACK))
{
if(mStackAllocated[mStackIndex])
{
mCallback->deallocate(const_cast<void*>(static_cast<const void*>(mStack[mStackIndex])));
mStackAllocated[mStackIndex] = false;
}
mStack[mStackIndex++] = element;
}
}
const char* popElement()
{
PX_ASSERT(mStackIndex > 0);
if(mStackAllocated[mStackIndex])
{
mCallback->deallocate(const_cast<void*>(static_cast<const void*>(mStack[mStackIndex])));
mStackAllocated[mStackIndex] = false;
}
mStack[mStackIndex] = NULL;
return mStackIndex ? mStack[--mStackIndex] : NULL;
}
static const int MAX_STACK = 2048;
CharType mTypes[256];
physx::PxInputData* mFileBuf;
char* mReadBuffer;
char* mReadBufferEnd;
uint32_t mOpenCount;
uint32_t mReadBufferSize;
uint32_t mLastReadLoc;
int32_t mLineNo;
const char* mError;
uint32_t mStackIndex;
const char* mStack[MAX_STACK + 1];
bool mStreamFromMemory;
bool mStackAllocated[MAX_STACK + 1];
Callback* mCallback;
};
}
namespace physx
{
namespace shdfnd
{
FastXml* createFastXml(FastXml::Callback* iface)
{
MyFastXml* m = static_cast<MyFastXml*>(iface->allocate(sizeof(MyFastXml)));
if(m)
{
PX_PLACEMENT_NEW(m, MyFastXml(iface));
}
return static_cast<FastXml*>(m);
}
}
}

View File

@@ -0,0 +1,166 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PSFASTXML_PSFASTXML_H
#define PSFASTXML_PSFASTXML_H
#include "foundation/PxSimpleTypes.h" // defines basic data types; modify for your platform as needed.
#include "foundation/PxIO.h"
#include "foundation/PxAssert.h"
#include "foundation/PxAllocator.h"
namespace physx
{
namespace shdfnd
{
class FastXml
{
PX_NOCOPY(FastXml)
public:
class AttributePairs
{
int argc;
const char** argv;
public:
AttributePairs() : argc(0), argv(NULL)
{
}
AttributePairs(int c, const char** v) : argc(c), argv(v)
{
}
PX_INLINE int getNbAttr() const
{
return argc / 2;
}
const char* getKey(uint32_t index) const
{
PX_ASSERT((index * 2) < uint32_t(argc));
return argv[index * 2];
}
const char* getValue(uint32_t index) const
{
PX_ASSERT((index * 2 + 1) < uint32_t(argc));
return argv[index * 2 + 1];
}
const char* get(const char* attr) const
{
int32_t count = argc / 2;
for(int32_t i = 0; i < count; ++i)
{
const char* key = argv[i * 2], *value = argv[i * 2 + 1];
if(strcmp(key, attr) == 0)
return value;
}
return NULL;
}
};
/***
* Callbacks to the user with the contents of the XML file properly digested.
*/
class Callback
{
public:
virtual ~Callback()
{
}
virtual bool processComment(const char* comment) = 0; // encountered a comment in the XML
// 'element' is the name of the element that is being closed.
// depth is the recursion depth of this element.
// Return true to continue processing the XML file.
// Return false to stop processing the XML file; leaves the read pointer of the stream right after this close
// tag.
// The bool 'isError' indicates whether processing was stopped due to an error, or intentionally canceled early.
virtual bool processClose(const char* element, uint32_t depth, bool& isError) = 0; // process the 'close'
// indicator for a previously
// encountered element
// return true to continue processing the XML document, false to skip.
virtual bool processElement(const char* elementName, // name of the element
const char* elementData, // element data, null if none
const AttributePairs& attr, // attributes
int32_t lineno) = 0; // line number in the source XML file
// process the XML declaration header
virtual bool processXmlDeclaration(const AttributePairs&, // attributes
const char* /*elementData*/, int32_t /*lineno*/)
{
return true;
}
virtual bool processDoctype(const char* /*rootElement*/, // Root element tag
const char* /*type*/, // SYSTEM or PUBLIC
const char* /*fpi*/, // Formal Public Identifier
const char* /*uri*/) // Path to schema file
{
return true;
}
virtual void* allocate(uint32_t size)
{
return PxGetBroadcastAllocator()->allocate(size, "FastXml", PX_FL);
}
virtual void deallocate(void* ptr)
{
PxGetBroadcastAllocator()->deallocate(ptr);
}
};
virtual bool processXml(PxInputData& buff, bool streamFromMemory = false) = 0;
virtual const char* getError(int32_t& lineno) = 0; // report the reason for a parsing error, and the line number
// where it occurred.
FastXml()
{
}
virtual void release() = 0;
protected:
virtual ~FastXml()
{
}
};
FastXml* createFastXml(FastXml::Callback* iface);
} // shdfnd
} // physx
#endif // PSFASTXML_PSFASTXML_H

View File

@@ -0,0 +1,135 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxMetaDataObjects.h"
#include "PxExtensionMetaDataObjects.h"
#include "ExtJointMetaDataExtensions.h"
#include "SnJointRepXSerializer.h"
namespace physx {
template<typename TJointType>
inline TJointType* createJoint( PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1 )
{
PX_UNUSED(physics);
PX_UNUSED(actor0);
PX_UNUSED(actor1);
PX_UNUSED(localFrame0);
PX_UNUSED(localFrame1);
return NULL;
}
template<>
inline PxD6Joint* createJoint<PxD6Joint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxD6JointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<>
inline PxDistanceJoint* createJoint<PxDistanceJoint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxDistanceJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<>
inline PxFixedJoint* createJoint<PxFixedJoint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxFixedJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<>
inline PxPrismaticJoint* createJoint<PxPrismaticJoint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxPrismaticJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<>
inline PxRevoluteJoint* createJoint<PxRevoluteJoint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxRevoluteJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<>
inline PxSphericalJoint* createJoint<PxSphericalJoint>(PxPhysics& physics,
PxRigidActor* actor0, const PxTransform& localFrame0,
PxRigidActor* actor1, const PxTransform& localFrame1)
{
return PxSphericalJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
}
template<typename TJointType>
PxRepXObject PxJointRepXSerializer<TJointType>::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
PxRigidActor* actor0 = NULL;
PxRigidActor* actor1 = NULL;
PxTransform localPose0 = PxTransform(PxIdentity);
PxTransform localPose1 = PxTransform(PxIdentity);
bool ok = true;
if ( inReader.gotoChild( "Actors" ) )
{
ok = readReference<PxRigidActor>( inReader, *inCollection, "actor0", actor0 );
ok &= readReference<PxRigidActor>( inReader, *inCollection, "actor1", actor1 );
inReader.leaveChild();
}
TJointType* theJoint = !ok ? NULL : createJoint<TJointType>( inArgs.physics, actor0, localPose0, actor1, localPose1 );
if ( theJoint )
{
PxConstraint* constraint = theJoint->getConstraint();
PX_ASSERT( constraint );
inCollection->add( *constraint );
this->fileToObjectImpl( theJoint, inReader, inAllocator, inArgs, inCollection );
}
return PxCreateRepXObject(theJoint);
}
template<typename TJointType>
void PxJointRepXSerializer<TJointType>::objectToFileImpl( const TJointType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& )
{
writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection );
}
// explicit template instantiations
template struct PxJointRepXSerializer<PxFixedJoint>;
template struct PxJointRepXSerializer<PxDistanceJoint>;
template struct PxJointRepXSerializer<PxD6Joint>;
template struct PxJointRepXSerializer<PxPrismaticJoint>;
template struct PxJointRepXSerializer<PxRevoluteJoint>;
template struct PxJointRepXSerializer<PxSphericalJoint>;
}

View File

@@ -0,0 +1,67 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_JOINT_REPX_SERIALIZER_H
#define SN_JOINT_REPX_SERIALIZER_H
#include "extensions/PxRepXSimpleType.h"
#include "SnRepXSerializerImpl.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class XmlReader;
class XmlMemoryAllocator;
class XmlWriter;
class MemoryBuffer;
template<typename TJointType>
struct PX_DEPRECATED PxJointRepXSerializer : public RepXSerializerImpl<TJointType>
{
PxJointRepXSerializer(PxAllocatorCallback& inAllocator) : RepXSerializerImpl<TJointType>(inAllocator) {}
virtual PxRepXObject fileToObject(XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection);
virtual void objectToFileImpl(const TJointType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs&);
virtual TJointType* allocateObject(PxRepXInstantiationArgs&) { return NULL; }
};
#if PX_SUPPORT_EXTERN_TEMPLATE
// explicit template instantiations declarations
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxD6Joint>;
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxDistanceJoint>;
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxFixedJoint>;
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxPrismaticJoint>;
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxRevoluteJoint>;
extern template struct PX_DEPRECATED PxJointRepXSerializer<PxSphericalJoint>;
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,134 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_PX_STREAM_OPERATORS_H
#define SN_PX_STREAM_OPERATORS_H
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
#include "foundation/PxBounds3.h"
#include "foundation/PxString.h"
#include "PxFiltering.h"
namespace physx
{
static inline PxU32 strLenght( const char* inStr )
{
return inStr ? PxU32(strlen(inStr)) : 0;
}
}
namespace physx // ADL requires we put the operators in the same namespace as the underlying type of PxOutputStream
{
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const char* inString )
{
if ( inString && *inString )
{
ioStream.write( inString, PxU32(strlen(inString)) );
}
return ioStream;
}
template<typename TDataType>
inline PxOutputStream& toStream( PxOutputStream& ioStream, const char* inFormat, const TDataType inData )
{
char buffer[128] = { 0 };
Pxsnprintf( buffer, 128, inFormat, inData );
ioStream << buffer;
return ioStream;
}
struct endl_obj {};
//static endl_obj endl;
inline PxOutputStream& operator << ( PxOutputStream& ioStream, bool inData ) { ioStream << (inData ? "true" : "false"); return ioStream; }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxI32 inData ) { return toStream( ioStream, "%d", inData ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU16 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU8 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, char inData ) { return toStream( ioStream, "%c", inData ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU32 inData ) { return toStream( ioStream, "%u", inData ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU64 inData ) { return toStream( ioStream, "%llu", inData ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const void* inData ) { return ioStream << static_cast<uint64_t>(size_t(inData)); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF32 inData ) { return toStream( ioStream, "%g", PxF64(inData) ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF64 inData ) { return toStream( ioStream, "%g", inData ); }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, endl_obj) { return ioStream << "\n"; }
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxVec3& inData )
{
ioStream << inData[0];
ioStream << " ";
ioStream << inData[1];
ioStream << " ";
ioStream << inData[2];
return ioStream;
}
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxQuat& inData )
{
ioStream << inData.x;
ioStream << " ";
ioStream << inData.y;
ioStream << " ";
ioStream << inData.z;
ioStream << " ";
ioStream << inData.w;
return ioStream;
}
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxTransform& inData )
{
ioStream << inData.q;
ioStream << " ";
ioStream << inData.p;
return ioStream;
}
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxBounds3& inData )
{
ioStream << inData.minimum;
ioStream << " ";
ioStream << inData.maximum;
return ioStream;
}
inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxFilterData& inData )
{
ioStream << inData.word0 << " " << inData.word1 << " " << inData.word2 << " " << inData.word3;
return ioStream;
}
inline PxOutputStream& operator << ( PxOutputStream& ioStream, struct PxMetaDataPlane& inData )
{
ioStream << inData.normal;
ioStream << " ";
ioStream << inData.distance;
return ioStream;
}
}
#endif

View File

@@ -0,0 +1,244 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepEnergyThreshold", "0.005" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.UserData", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )

View File

@@ -0,0 +1,273 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )

View File

@@ -0,0 +1,312 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" )
DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.InertiaScale", "1" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.FrictionCoefficient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DragCoefficient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.CollisionMassScale", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ExternalAcceleration", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleMass", "0.001" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Restitution", "0.5" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DynamicFriction", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.StaticFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.SimulationFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.MaxMotionDistance", "0.06" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.RestOffset", "0.004" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ContactOffset", "0.008" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.GridSize", "0.96" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ProjectionPlane", "0 0 1 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT")
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ActorFlags", "eVISUALIZATION" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DominanceGroup", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.OwnerClient", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Damping", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ExternalAcceleration", "0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleMass", "0.001" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Restitution", "0.5" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DynamicFriction", "0.05" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.StaticFriction", "0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.SimulationFilterData", "0 0 0 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.MaxMotionDistance", "0.06" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestOffset", "0.004" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ContactOffset", "0.008" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.GridSize", "0.64" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ProjectionPlane", "0 0 1 0" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Stiffness", "20" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Viscosity", "6" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestParticleDistance", "0.02" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" )
DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT")
DEFINE_REPX_DEFAULT_PROPERTY("PxAggregate.SelfCollision", "false" )
DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )

View File

@@ -0,0 +1,173 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_REPX_COLLECTION_H
#define SN_REPX_COLLECTION_H
#include "common/PxTolerancesScale.h"
#include "extensions/PxRepXSerializer.h"
namespace physx { namespace Sn {
struct XmlNode;
struct RepXCollectionItem
{
PxRepXObject liveObject;
XmlNode* descriptor;
RepXCollectionItem( PxRepXObject inItem = PxRepXObject(), XmlNode* inDescriptor = NULL )
: liveObject( inItem )
, descriptor( inDescriptor )
{
}
};
struct RepXDefaultEntry
{
const char* name;
const char* value;
RepXDefaultEntry( const char* pn, const char* val ) : name( pn ), value( val ){}
};
/**
* The result of adding an object to the collection.
*/
struct RepXAddToCollectionResult
{
enum Enum
{
Success,
SerializerNotFound,
InvalidParameters, //Null data passed in.
AlreadyInCollection
};
PxSerialObjectId collectionId;
Enum result;
RepXAddToCollectionResult( Enum inResult = Success, const PxSerialObjectId inId = 0 )
: collectionId( inId )
, result( inResult )
{
}
bool isValid() { return result == Success && collectionId != 0; }
};
/**
* A RepX collection contains a set of static data objects that can be transformed
* into live objects. It uses RepX serializer to do two transformations:
* live object <-> collection object (descriptor)
* collection object <-> file system.
*
* A live object is considered to be something live in the physics
* world such as a material or a rigidstatic.
*
* A collection object is a piece of data from which a live object
* of identical characteristics can be created.
*
* Clients need to pass PxCollection so that objects can resolve
* references. In addition, objects must be added in an order such that
* references can be resolved in the first place. So objects must be added
* to the collection *after* objects they are dependent upon.
*
* When deserializing from a file, the collection will allocate char*'s that will
* not be freed when the collection itself is freed. The user must be responsible
* for these character allocations.
*/
class RepXCollection
{
protected:
virtual ~RepXCollection(){}
public:
virtual void destroy() = 0;
/**
* Set the scale on this collection. The scale is saved with the collection.
*
* If the scale wasn't set, it will be invalid.
*/
virtual void setTolerancesScale( const PxTolerancesScale& inScale ) = 0;
/**
* Get the scale that was set at collection creation time or at load time.
* If this is a loaded file and the source data does not contain a scale
* this value will be invalid (PxTolerancesScale::isValid()).
*/
virtual PxTolerancesScale getTolerancesScale() const = 0;
/**
* Set the up vector on this collection. The up vector is saved with the collection.
*
* If the up vector wasn't set, it will be (0,0,0).
*/
virtual void setUpVector( const PxVec3& inUpVector ) = 0;
/**
* If the up vector wasn't set, it will be (0,0,0). Else this will be the up vector
* optionally set when the collection was created.
*/
virtual PxVec3 getUpVector() const = 0;
virtual const char* getVersion() = 0;
static const char* getLatestVersion();
//Necessary accessor functions for translation/upgrading.
virtual const RepXCollectionItem* begin() const = 0;
virtual const RepXCollectionItem* end() const = 0;
//Performs a deep copy of the repx node.
virtual XmlNode* copyRepXNode( const XmlNode* srcNode ) = 0;
virtual void addCollectionItem( RepXCollectionItem inItem ) = 0;
//Create a new repx node with this name. Its value is unset.
virtual XmlNode& createRepXNode( const char* name ) = 0;
virtual RepXCollection& createCollection( const char* inVersionStr ) = 0;
//Release this when finished.
virtual XmlReaderWriter& createNodeEditor() = 0;
virtual PxAllocatorCallback& getAllocator() = 0;
virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inPxCollection ) = 0;
virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs ) = 0;
/**
* Save this collection out to a file stream. Uses the RepX serialize to perform
* collection object->file conversions.
*
* /param[in] inStream Write-only stream to save collection out to.
*/
virtual void save( PxOutputStream& inStream ) = 0;
};
} }
#endif

View File

@@ -0,0 +1,561 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPhysicsAPI.h"
#include "PxMetaDataObjects.h"
#include "SnPxStreamOperators.h"
#include "foundation/PxUtilities.h"
#include "SnXmlImpl.h"
#include "SnXmlSerializer.h"
#include "SnXmlDeserializer.h"
#include "SnRepXCoreSerializer.h"
using namespace physx::Sn;
namespace physx {
typedef PxReadOnlyPropertyInfo<PxPropertyInfoName::PxArticulationLink_InboundJoint, PxArticulationLink, PxArticulationJointReducedCoordinate *> TIncomingJointPropType;
//*************************************************************
// Actual RepXSerializer implementations for PxMaterial
//*************************************************************
PxMaterial* PxMaterialRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
{
return inArgs.physics.createMaterial(0, 0, 0);
}
PxRepXObject PxShapeRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
PxProfileAllocatorWrapper wrapper( inAllocator.getAllocator() );
TReaderNameStack names( wrapper );
PxProfileArray<PxU32> contexts( wrapper );
bool hadError = false;
RepXVisitorReader<PxShape> theVisitor( names, contexts, inArgs, inReader, NULL, inAllocator, *inCollection, hadError );
PxArray<PxMaterial*> materials;
PxGeometry* geometry = NULL;
parseShape( theVisitor, geometry, materials );
if(hadError)
return PxRepXObject();
PxShape *theShape = inArgs.physics.createShape( *geometry, materials.begin(), PxTo16(materials.size()) );
switch(geometry->getType())
{
case PxGeometryType::eSPHERE :
static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry();
break;
case PxGeometryType::ePLANE :
static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry();
break;
case PxGeometryType::eCAPSULE :
static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry();
break;
case PxGeometryType::eBOX :
static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry();
break;
case PxGeometryType::eCONVEXCORE:
static_cast<PxConvexCoreGeometry*>(geometry)->~PxConvexCoreGeometry();
break;
case PxGeometryType::eCONVEXMESH :
static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry();
break;
case PxGeometryType::eTRIANGLEMESH :
static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry();
break;
case PxGeometryType::eHEIGHTFIELD :
static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry();
break;
case PxGeometryType::eTETRAHEDRONMESH :
static_cast<PxTetrahedronMeshGeometry*>(geometry)->~PxTetrahedronMeshGeometry();
break;
case PxGeometryType::ePARTICLESYSTEM:
static_cast<PxParticleSystemGeometry*>(geometry)->~PxParticleSystemGeometry();
break;
case PxGeometryType::eCUSTOM :
static_cast<PxCustomGeometry*>(geometry)->~PxCustomGeometry();
break;
case PxGeometryType::eGEOMETRY_COUNT:
case PxGeometryType::eINVALID:
PX_ASSERT(0);
}
inAllocator.getAllocator().deallocate(geometry);
bool ret = readAllProperties( inArgs, inReader, theShape, inAllocator, *inCollection );
return ret ? PxCreateRepXObject(theShape) : PxRepXObject();
}
//*************************************************************
// Actual RepXSerializer implementations for PxTriangleMesh
//*************************************************************
template<typename TTriIndexElem>
inline void writeTriangle( MemoryBuffer& inTempBuffer, const Triangle<TTriIndexElem>& inTriangle )
{
inTempBuffer << inTriangle.mIdx0
<< " " << inTriangle.mIdx1
<< " " << inTriangle.mIdx2;
}
PxU32 materialAccess( const PxTriangleMesh* inMesh, PxU32 inIndex ) { return inMesh->getTriangleMaterialIndex( inIndex ); }
template<typename TDataType>
void writeDatatype( MemoryBuffer& inTempBuffer, const TDataType& inType ) { inTempBuffer << inType; }
void PxBVH33TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH33TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
{
bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff;
PxU32 numVertices = mesh->getNbVertices();
const PxVec3* vertices = mesh->getVertices();
writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 );
bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
PxU32 triCount = mesh->getNbTriangles();
const void* indices = mesh->getTriangles();
if ( isU16 )
writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> );
else
writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> );
if ( hasMatIndex )
writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> );
//Cooked stream
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = numVertices;
meshDesc.points.data = vertices;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = triCount;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32);
if(isU16)
{
meshDesc.triangles.stride = sizeof(PxU16)*3;
meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES;
}
else
{
meshDesc.triangles.stride = sizeof(PxU32)*3;
}
if(hasMatIndex)
{
PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount];
for(PxU32 i = 0; i < triCount; i++)
materialIndices[i] = mesh->getTriangleMaterialIndex(i);
meshDesc.materialIndices.data = materialIndices;
meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex);
}
if(inArgs.cooker != NULL)
{
TMemoryPoolManager theManager(mAllocator);
MemoryBuffer theTempBuf( &theManager );
theTempBuf.clear();
PxCookTriangleMesh( *inArgs.cooker, meshDesc, theTempBuf );
writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
}
delete []meshDesc.materialIndices.data;
}
PxRepXObject PxBVH33TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ )
{
//We can't do a simple inverse; we *have* to cook data to get a mesh.
PxTriangleMeshDesc theDesc;
readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator);
PxU32 triCount;
readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator);
PxStridedData cookedData;
cookedData.stride = sizeof(PxU8);
PxU32 dataSize;
readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
TMemoryPoolManager theManager(inAllocator.getAllocator());
MemoryBuffer theTempBuf( &theManager );
// PxTriangleMesh* theMesh = NULL;
PxBVH33TriangleMesh* theMesh = NULL;
if(dataSize != 0)
{
theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
}
if(theMesh == NULL)
{
PX_ASSERT(inArgs.cooker);
theTempBuf.clear();
PxCookingParams params = *inArgs.cooker;
params.midphaseDesc = PxMeshMidPhase::eBVH33;
PxCookTriangleMesh( params, theDesc, theTempBuf );
// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
}
return PxCreateRepXObject( theMesh );
}
void PxBVH34TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH34TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
{
bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff;
PxU32 numVertices = mesh->getNbVertices();
const PxVec3* vertices = mesh->getVertices();
writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 );
bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
PxU32 triCount = mesh->getNbTriangles();
const void* indices = mesh->getTriangles();
if ( isU16 )
writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> );
else
writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> );
if ( hasMatIndex )
writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> );
//Cooked stream
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = numVertices;
meshDesc.points.data = vertices;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = triCount;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32);
if(isU16)
{
meshDesc.triangles.stride = sizeof(PxU16)*3;
meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES;
}
else
{
meshDesc.triangles.stride = sizeof(PxU32)*3;
}
if(hasMatIndex)
{
PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount];
for(PxU32 i = 0; i < triCount; i++)
materialIndices[i] = mesh->getTriangleMaterialIndex(i);
meshDesc.materialIndices.data = materialIndices;
meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex);
}
if(inArgs.cooker != NULL)
{
TMemoryPoolManager theManager(mAllocator);
MemoryBuffer theTempBuf( &theManager );
theTempBuf.clear();
PxCookTriangleMesh( *inArgs.cooker, meshDesc, theTempBuf );
writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
}
delete []meshDesc.materialIndices.data;
}
PxRepXObject PxBVH34TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ )
{
//We can't do a simple inverse; we *have* to cook data to get a mesh.
PxTriangleMeshDesc theDesc;
readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator);
PxU32 triCount;
readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator);
PxStridedData cookedData;
cookedData.stride = sizeof(PxU8);
PxU32 dataSize;
readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
TMemoryPoolManager theManager(inAllocator.getAllocator());
MemoryBuffer theTempBuf( &theManager );
// PxTriangleMesh* theMesh = NULL;
PxBVH34TriangleMesh* theMesh = NULL;
if(dataSize != 0)
{
theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
}
if(theMesh == NULL)
{
PX_ASSERT(inArgs.cooker);
theTempBuf.clear();
PxCookingParams params = *inArgs.cooker;
params.midphaseDesc = PxMeshMidPhase::eBVH34;
PxCookTriangleMesh( params, theDesc, theTempBuf );
// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
}
return PxCreateRepXObject(theMesh);
}
//*************************************************************
// Actual RepXSerializer implementations for PxHeightField
//*************************************************************
void PxHeightFieldRepXSerializer::objectToFileImpl( const PxHeightField* inHeightField, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
{
PxHeightFieldDesc theDesc;
theDesc.nbRows = inHeightField->getNbRows();
theDesc.nbColumns = inHeightField->getNbColumns();
theDesc.format = inHeightField->getFormat();
theDesc.samples.stride = inHeightField->getSampleStride();
theDesc.samples.data = NULL;
theDesc.convexEdgeThreshold = inHeightField->getConvexEdgeThreshold();
theDesc.flags = inHeightField->getFlags();
PxU32 theCellCount = inHeightField->getNbRows() * inHeightField->getNbColumns();
PxU32 theSampleStride = sizeof( PxHeightFieldSample );
PxU32 theSampleBufSize = theCellCount * theSampleStride;
PxHeightFieldSample* theSamples = reinterpret_cast< PxHeightFieldSample*> ( inTempBuffer.mManager->allocate( theSampleBufSize ) );
inHeightField->saveCells( theSamples, theSampleBufSize );
theDesc.samples.data = theSamples;
writeAllProperties( &theDesc, inWriter, inTempBuffer, *inCollection );
writeStridedBufferProperty<PxHeightFieldSample>( inWriter, inTempBuffer, "samples", theDesc.samples, theDesc.nbRows * theDesc.nbColumns, 6, writeHeightFieldSample);
inTempBuffer.mManager->deallocate( reinterpret_cast<PxU8*>(theSamples) );
}
PxRepXObject PxHeightFieldRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
PX_ASSERT(inArgs.cooker);
PxHeightFieldDesc theDesc;
readAllProperties( inArgs, inReader, &theDesc, inAllocator, *inCollection );
//Now read the data...
PxU32 count = 0; //ignored becaues numRows and numColumns tells the story
readStridedBufferProperty<PxHeightFieldSample>( inReader, "samples", theDesc.samples, count, inAllocator);
PxHeightField* retval = PxCreateHeightField( theDesc, inArgs.physics.getPhysicsInsertionCallback() );
return PxCreateRepXObject(retval);
}
//*************************************************************
// Actual RepXSerializer implementations for PxConvexMesh
//*************************************************************
void PxConvexMeshRepXSerializer::objectToFileImpl( const PxConvexMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
{
writeBuffer( inWriter, inTempBuffer, 2, mesh->getVertices(), mesh->getNbVertices(), "points", writePxVec3 );
if(inArgs.cooker != NULL)
{
//Cache cooked Data
PxConvexMeshDesc theDesc;
theDesc.points.data = mesh->getVertices();
theDesc.points.stride = sizeof(PxVec3);
theDesc.points.count = mesh->getNbVertices();
theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
TMemoryPoolManager theManager(mAllocator);
MemoryBuffer theTempBuf( &theManager );
PxCookConvexMesh( *inArgs.cooker, theDesc, theTempBuf );
writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
}
}
//Conversion from scene object to descriptor.
PxRepXObject PxConvexMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/)
{
PxConvexMeshDesc theDesc;
readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxStridedData cookedData;
cookedData.stride = sizeof(PxU8);
PxU32 dataSize;
readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
TMemoryPoolManager theManager(inAllocator.getAllocator());
MemoryBuffer theTempBuf( &theManager );
PxConvexMesh* theMesh = NULL;
if(dataSize != 0)
{
theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
theMesh = inArgs.physics.createConvexMesh( theTempBuf );
}
if(theMesh == NULL)
{
PX_ASSERT(inArgs.cooker);
theTempBuf.clear();
PxCookConvexMesh( *inArgs.cooker, theDesc, theTempBuf );
theMesh = inArgs.physics.createConvexMesh( theTempBuf );
}
return PxCreateRepXObject(theMesh);
}
//*************************************************************
// Actual RepXSerializer implementations for PxRigidStatic
//*************************************************************
PxRigidStatic* PxRigidStaticRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
{
return inArgs.physics.createRigidStatic( PxTransform(PxIdentity) );
}
//*************************************************************
// Actual RepXSerializer implementations for PxRigidDynamic
//*************************************************************
PxRigidDynamic* PxRigidDynamicRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
{
return inArgs.physics.createRigidDynamic( PxTransform(PxIdentity) );
}
//*************************************************************
// Actual RepXSerializer implementations for PxArticulationReducedCoordinate
//*************************************************************
void PxArticulationReducedCoordinateRepXSerializer::objectToFileImpl(const PxArticulationReducedCoordinate* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
{
TNameStack nameStack(inTempBuffer.mManager->mWrapper);
Sn::TArticulationLinkLinkMap linkMap(inTempBuffer.mManager->mWrapper);
RepXVisitorWriter<PxArticulationReducedCoordinate> writer(nameStack, inWriter, inObj, inTempBuffer, *inCollection, &linkMap);
RepXPropertyFilter<RepXVisitorWriter<PxArticulationReducedCoordinate> > theOp(writer);
visitAllProperties<PxArticulationReducedCoordinate>(theOp);
}
PxArticulationReducedCoordinate* PxArticulationReducedCoordinateRepXSerializer::allocateObject(PxRepXInstantiationArgs& inArgs) { return inArgs.physics.createArticulationReducedCoordinate(); }
//*************************************************************
// Actual RepXSerializer implementations for PxAggregate
//*************************************************************
void PxAggregateRepXSerializer::objectToFileImpl( const PxAggregate* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
{
PxArticulationLink *link = NULL;
inWriter.addAndGotoChild( "Actors" );
for(PxU32 i = 0; i < data->getNbActors(); ++i)
{
PxActor* actor;
if(data->getActors(&actor, 1, i))
{
link = actor->is<PxArticulationLink>();
}
if(link && !link->getInboundJoint() )
{
writeProperty( inWriter, *inCollection, inTempBuffer, "PxArticulationRef", &link->getArticulation());
}
else if( !link )
{
PxSerialObjectId theId = 0;
theId = inCollection->getId( *actor );
if( theId == 0 )
theId = static_cast<uint64_t>(size_t(actor));
writeProperty( inWriter, *inCollection, inTempBuffer, "PxActorRef", theId );
}
}
inWriter.leaveChild( );
writeProperty( inWriter, *inCollection, inTempBuffer, "NumActors", data->getNbActors() );
writeProperty( inWriter, *inCollection, inTempBuffer, "MaxNbActors", data->getMaxNbActors() );
writeProperty(inWriter, *inCollection, inTempBuffer, "MaxNbShapes", data->getMaxNbShapes());
writeProperty( inWriter, *inCollection, inTempBuffer, "SelfCollision", data->getSelfCollision() );
writeAllProperties( data, inWriter, inTempBuffer, *inCollection );
}
PxRepXObject PxAggregateRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
PxU32 numActors;
readProperty( inReader, "NumActors", numActors );
PxU32 maxNbActors;
readProperty( inReader, "MaxNbActors", maxNbActors );
PxU32 maxNbShapes;
readProperty(inReader, "MaxNbShapes", maxNbShapes);
bool selfCollision;
bool ret = readProperty( inReader, "SelfCollision", selfCollision );
PxAggregate* theAggregate = inArgs.physics.createAggregate(maxNbActors, maxNbShapes, selfCollision);
ret &= readAllProperties( inArgs, inReader, theAggregate, inAllocator, *inCollection );
inReader.pushCurrentContext();
if ( inReader.gotoChild( "Actors" ) )
{
inReader.pushCurrentContext();
for( bool matSuccess = inReader.gotoFirstChild(); matSuccess;
matSuccess = inReader.gotoNextSibling() )
{
const char* actorType = inReader.getCurrentItemName();
if ( 0 == physx::Pxstricmp( actorType, "PxActorRef" ) )
{
PxActor *actor = NULL;
ret &= readReference<PxActor>( inReader, *inCollection, actor );
if(actor)
{
PxScene *currScene = actor->getScene();
if(currScene)
{
currScene->removeActor(*actor);
}
theAggregate->addActor(*actor);
}
}
else if ( 0 == physx::Pxstricmp( actorType, "PxArticulationRef" ) )
{
PxArticulationReducedCoordinate* articulation = NULL;
ret &= readReference<PxArticulationReducedCoordinate>( inReader, *inCollection, articulation );
if(articulation)
{
PxScene *currScene = articulation->getScene();
if(currScene)
{
currScene->removeArticulation(*articulation);
}
theAggregate->addArticulation(*articulation);
}
}
}
inReader.popCurrentContext();
inReader.leaveChild();
}
inReader.popCurrentContext();
return ret ? PxCreateRepXObject(theAggregate) : PxRepXObject();
}
}

View File

@@ -0,0 +1,121 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_REPX_CORE_SERIALIZER_H
#define SN_REPX_CORE_SERIALIZER_H
#include "foundation/PxSimpleTypes.h"
#include "SnRepXSerializerImpl.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class XmlReader;
class XmlMemoryAllocator;
class XmlWriter;
class MemoryBuffer;
struct PX_DEPRECATED PxMaterialRepXSerializer : RepXSerializerImpl<PxMaterial>
{
PxMaterialRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxMaterial>( inCallback ) {}
virtual PxMaterial* allocateObject( PxRepXInstantiationArgs& );
};
struct PX_DEPRECATED PxShapeRepXSerializer : public RepXSerializerImpl<PxShape>
{
PxShapeRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxShape>( inCallback ) {}
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxShape* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
struct PX_DEPRECATED PxBVH33TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH33TriangleMesh>
{
PxBVH33TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH33TriangleMesh>( inCallback ) {}
virtual void objectToFileImpl( const PxBVH33TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxBVH33TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
struct PX_DEPRECATED PxBVH34TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH34TriangleMesh>
{
PxBVH34TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH34TriangleMesh>( inCallback ) {}
virtual void objectToFileImpl( const PxBVH34TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxBVH34TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
struct PX_DEPRECATED PxHeightFieldRepXSerializer : public RepXSerializerImpl<PxHeightField>
{
PxHeightFieldRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxHeightField>( inCallback ) {}
virtual void objectToFileImpl( const PxHeightField*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxHeightField* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
struct PX_DEPRECATED PxConvexMeshRepXSerializer : public RepXSerializerImpl<PxConvexMesh>
{
PxConvexMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxConvexMesh>( inCallback ) {}
virtual void objectToFileImpl( const PxConvexMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxConvexMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
struct PX_DEPRECATED PxRigidStaticRepXSerializer : public RepXSerializerImpl<PxRigidStatic>
{
PxRigidStaticRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidStatic>( inCallback ) {}
virtual PxRigidStatic* allocateObject( PxRepXInstantiationArgs& );
};
struct PX_DEPRECATED PxRigidDynamicRepXSerializer : public RepXSerializerImpl<PxRigidDynamic>
{
PxRigidDynamicRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidDynamic>( inCallback ) {}
virtual PxRigidDynamic* allocateObject( PxRepXInstantiationArgs& );
};
struct PX_DEPRECATED PxArticulationReducedCoordinateRepXSerializer : public RepXSerializerImpl<PxArticulationReducedCoordinate>
{
PxArticulationReducedCoordinateRepXSerializer(PxAllocatorCallback& inCallback) : RepXSerializerImpl<PxArticulationReducedCoordinate>(inCallback) {}
virtual void objectToFileImpl(const PxArticulationReducedCoordinate*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs&);
virtual PxArticulationReducedCoordinate* allocateObject(PxRepXInstantiationArgs&);
};
struct PX_DEPRECATED PxAggregateRepXSerializer : public RepXSerializerImpl<PxAggregate>
{
PxAggregateRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxAggregate>( inCallback ) {}
virtual void objectToFileImpl( const PxAggregate*, PxCollection*, XmlWriter& , MemoryBuffer&, PxRepXInstantiationArgs& );
virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
virtual PxAggregate* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,90 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_REPX_SERIALIZER_IMPL_H
#define SN_REPX_SERIALIZER_IMPL_H
#include "foundation/PxUserAllocated.h"
#include "SnXmlVisitorWriter.h"
#include "SnXmlVisitorReader.h"
namespace physx {
using namespace Sn;
/**
* The repx serializer impl takes the raw, untyped repx extension interface
* and implements the simpler functions plus does the reinterpret-casts required
* for any object to implement the serializer safely.
*/
template<typename TLiveType>
struct RepXSerializerImpl : public PxRepXSerializer, PxUserAllocated
{
protected:
RepXSerializerImpl( const RepXSerializerImpl& inOther );
RepXSerializerImpl& operator=( const RepXSerializerImpl& inOther );
public:
PxAllocatorCallback& mAllocator;
RepXSerializerImpl( PxAllocatorCallback& inAllocator )
: mAllocator( inAllocator )
{
}
virtual const char* getTypeName() { return PxTypeInfo<TLiveType>::name(); }
virtual void objectToFile( const PxRepXObject& inLiveObject, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
{
const TLiveType* theObj = reinterpret_cast<const TLiveType*>( inLiveObject.serializable );
objectToFileImpl( theObj, inCollection, inWriter, inTempBuffer, inArgs );
}
virtual PxRepXObject fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
TLiveType* theObj( allocateObject( inArgs ) );
if ( theObj )
if(fileToObjectImpl( theObj, inReader, inAllocator, inArgs, inCollection ))
return PxCreateRepXObject(theObj);
return PxRepXObject();
}
virtual void objectToFileImpl( const TLiveType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
{
writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection );
}
virtual bool fileToObjectImpl( TLiveType* inObj, XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
{
return readAllProperties( inArgs, inReader, inObj, inAllocator, *inCollection );
}
virtual TLiveType* allocateObject( PxRepXInstantiationArgs& inArgs ) = 0;
};
}
#endif

View File

@@ -0,0 +1,462 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxMemory.h"
#include "SnXmlImpl.h"
#include "SnXmlReader.h"
#include "SnXmlMemoryAllocator.h"
#include "SnRepXCollection.h"
#include "SnRepXUpgrader.h"
using namespace physx::profile;
namespace physx { namespace Sn {
#define DEFINE_REPX_DEFAULT_PROPERTY( name, val ) RepXDefaultEntry( name, val ),
static RepXDefaultEntry gRepX1_0Defaults[] = {
#include "SnRepX1_0Defaults.h"
};
static PxU32 gNumRepX1_0Default = sizeof( gRepX1_0Defaults ) / sizeof ( *gRepX1_0Defaults );
static RepXDefaultEntry gRepX3_1Defaults[] = {
#include "SnRepX3_1Defaults.h"
};
static PxU32 gNumRepX3_1Defaults = sizeof( gRepX3_1Defaults ) / sizeof ( *gRepX3_1Defaults );
static RepXDefaultEntry gRepX3_2Defaults[] = {
#include "SnRepX3_2Defaults.h"
};
static PxU32 gNumRepX3_2Defaults = sizeof( gRepX3_2Defaults ) / sizeof ( *gRepX3_2Defaults );
inline const char* nextPeriod( const char* str )
{
for( ++str; str && *str && *str != '.'; ++str ); //empty loop intentional
return str;
}
inline bool safeStrEq(const char* lhs, const char* rhs)
{
if (lhs == rhs)
return true;
//If they aren't equal, and one of them is null,
//then they can't be equal.
//This is assuming that the null char* is not equal to
//the empty "" char*.
if (!lhs || !rhs)
return false;
return ::strcmp(lhs, rhs) == 0;
}
typedef PxProfileHashMap<const char*, PxU32> TNameOffsetMap;
void setMissingPropertiesToDefault( XmlNode* topNode, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults, TNameOffsetMap& map )
{
for ( XmlNode* child = topNode->mFirstChild; child != NULL; child = child->mNextSibling )
setMissingPropertiesToDefault( child, editor, defaults, numDefaults, map );
const TNameOffsetMap::Entry* entry( map.find( topNode->mName ) );
if ( entry )
{
XmlReaderWriter& theReader( editor );
theReader.setNode( *topNode );
char nameBuffer[512] = {0};
size_t nameLen = strlen( topNode->mName );
//For each default property entry for this node type.
for ( const RepXDefaultEntry* item = defaults + entry->second; Pxstrncmp( item->name, topNode->mName, nameLen ) == 0; ++item )
{
bool childAdded = false;
const char* nameStart = item->name + nameLen;
++nameStart;
theReader.pushCurrentContext();
const char* str = nameStart;
while( *str )
{
const char *period = nextPeriod( str );
size_t len = size_t(PxMin( period - str, ptrdiff_t(1023) )); //can't be too careful these days.
PxMemCopy( nameBuffer, str, PxU32(len) );
nameBuffer[len] = 0;
if ( theReader.gotoChild( nameBuffer ) == false )
{
childAdded = true;
theReader.addOrGotoChild( nameBuffer );
}
if (*period )
str = period + 1;
else
str = period;
}
if ( childAdded )
theReader.setCurrentItemValue( item->value );
theReader.popCurrentContext();
}
}
}
static void setMissingPropertiesToDefault( RepXCollection& collection, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults )
{
PxProfileAllocatorWrapper wrapper( collection.getAllocator() );
//Release all strings at once, instead of piece by piece
XmlMemoryAllocatorImpl 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 = size_t(periodPtr - item.name);
char* newMem = reinterpret_cast<char*>(alloc.allocate( PxU32(nameLen + 1) ));
PxMemCopy( newMem, item.name, PxU32(nameLen) );
newMem[nameLen] = 0;
if ( nameOffsets.find( newMem ) )
alloc.deallocate( reinterpret_cast<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.descriptor, editor, defaults, numDefaults, nameOffsets );
}
}
struct RecursiveTraversal
{
RecursiveTraversal(XmlReaderWriter& editor): mEditor(editor) {}
void traverse()
{
mEditor.pushCurrentContext();
updateNode();
for(bool exists = mEditor.gotoFirstChild(); exists; exists = mEditor.gotoNextSibling())
traverse();
mEditor.popCurrentContext();
}
virtual void updateNode() = 0;
virtual ~RecursiveTraversal() {}
XmlReaderWriter& mEditor;
protected:
RecursiveTraversal& operator=(const RecursiveTraversal&){return *this;}
};
RepXCollection& RepXUpgrader::upgrade10CollectionTo3_1Collection(RepXCollection& src)
{
XmlReaderWriter& 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->liveObject, src.copyRepXNode( item->descriptor ) );
editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
//Some old files have this name in their system.
editor.renameProperty( "MassSpaceInertia", "MassSpaceInertiaTensor" );
editor.renameProperty( "SleepEnergyThreshold", "SleepThreshold" );
if ( strstr( newItem.liveObject.typeName, "Joint" ) || strstr( newItem.liveObject.typeName, "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_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;
}
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" ) )
{
PxGetFoundation().error(PxErrorCode::eDEBUG_WARNING, PX_FL, "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;
}
RepXCollection& RepXUpgrader::upgrade3_3CollectionTo3_4Collection(RepXCollection& src)
{
RepXCollection* dest = &src.createCollection("3.4.0");
for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item )
{
if(strstr(item->liveObject.typeName, "PxTriangleMesh"))
{
PxRepXObject newMeshRepXObj("PxBVH33TriangleMesh", item->liveObject.serializable, item->liveObject.id);
XmlNode* newMeshNode = src.copyRepXNode( item->descriptor );
newMeshNode->mName = "PxBVH33TriangleMesh";
RepXCollectionItem newMeshItem(newMeshRepXObj, newMeshNode);
dest->addCollectionItem( newMeshItem );
continue;
}
RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) );
dest->addCollectionItem( newItem );
}
src.destroy();
return *dest;
}
RepXCollection& RepXUpgrader::upgrade3_4CollectionTo4_0Collection(RepXCollection& src)
{
RepXCollection* dest = &src.createCollection("4.0.0");
for (const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++item)
{
if (strstr(item->liveObject.typeName, "PxParticleFluid") ||
strstr(item->liveObject.typeName, "PxParticleSystem") ||
strstr(item->liveObject.typeName, "PxClothFabric") ||
strstr(item->liveObject.typeName, "PxCloth"))
{
continue;
}
RepXCollectionItem newItem(item->liveObject, src.copyRepXNode(item->descriptor));
dest->addCollectionItem(newItem);
}
src.destroy();
return *dest;
}
RepXCollection& RepXUpgrader::upgradeCollection(RepXCollection& src)
{
const char* srcVersion = src.getVersion();
if( safeStrEq( srcVersion, RepXCollection::getLatestVersion() ))
return src;
typedef RepXCollection& (*UPGRADE_FUNCTION)(RepXCollection& src);
struct Upgrade { const char* versionString; UPGRADE_FUNCTION upgradeFunction; };
static const Upgrade upgradeTable[] =
{
{ "1.0", upgrade10CollectionTo3_1Collection },
{ "3.1", NULL },
{ "3.1.1", upgrade3_1CollectionTo3_2Collection },
{ "3.2.0", upgrade3_2CollectionTo3_3Collection },
{ "3.3.0", NULL },
{ "3.3.1", NULL },
{ "3.3.2", NULL },
{ "3.3.3", NULL },
{ "3.3.4", upgrade3_3CollectionTo3_4Collection },
{ "3.4.0", NULL },
{ "3.4.1", NULL },
{ "3.4.2", upgrade3_4CollectionTo4_0Collection }
}; //increasing order and complete
const PxU32 upgradeTableSize = sizeof(upgradeTable)/sizeof(upgradeTable[0]);
PxU32 repxVersion = UINT16_MAX;
for (PxU32 i=0; i<upgradeTableSize; i++)
{
if( safeStrEq( srcVersion, upgradeTable[i].versionString ))
{
repxVersion = i;
break;
}
}
RepXCollection* dest = &src;
for( PxU32 j = repxVersion; j < upgradeTableSize; j++ )
{
if( upgradeTable[j].upgradeFunction )
dest = &(upgradeTable[j].upgradeFunction)(*dest);
}
return *dest;
}
} }

View File

@@ -0,0 +1,54 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_REPX_UPGRADER_H
#define SN_REPX_UPGRADER_H
#include "foundation/PxSimpleTypes.h"
namespace physx { namespace Sn {
class RepXCollection;
class RepXUpgrader
{
public:
//If a new collection is created, the source collection is destroyed.
//Thus you only need to release the new collection.
//This holds for all of the upgrade functions.
//So be aware, that the argument to these functions may not be valid
//after they are called, but the return value always will be valid.
static RepXCollection& upgradeCollection( RepXCollection& src );
static RepXCollection& upgrade10CollectionTo3_1Collection( RepXCollection& src );
static RepXCollection& upgrade3_1CollectionTo3_2Collection( RepXCollection& src );
static RepXCollection& upgrade3_2CollectionTo3_3Collection( RepXCollection& src );
static RepXCollection& upgrade3_3CollectionTo3_4Collection( RepXCollection& src );
static RepXCollection& upgrade3_4CollectionTo4_0Collection( RepXCollection& src );
};
} }
#endif

View File

@@ -0,0 +1,256 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_SIMPLE_XML_WRITER_H
#define SN_SIMPLE_XML_WRITER_H
#include "foundation/PxArray.h"
#include "SnXmlMemoryPoolStreams.h"
namespace physx { namespace Sn {
class SimpleXmlWriter
{
public:
struct STagWatcher
{
typedef SimpleXmlWriter TXmlWriterType;
TXmlWriterType& mWriter;
STagWatcher( const STagWatcher& inOther );
STagWatcher& operator-( const STagWatcher& inOther );
STagWatcher( TXmlWriterType& inWriter, const char* inTagName )
: mWriter( inWriter )
{
mWriter.beginTag( inTagName );
}
~STagWatcher() { mWriter.endTag(); }
protected:
STagWatcher& operator=(const STagWatcher&);
};
virtual ~SimpleXmlWriter(){}
virtual void beginTag( const char* inTagname ) = 0;
virtual void endTag() = 0;
virtual void addAttribute( const char* inName, const char* inValue ) = 0;
virtual void writeContentTag( const char* inTag, const char* inContent ) = 0;
virtual void addContent( const char* inContent ) = 0;
virtual PxU32 tabCount() = 0;
private:
SimpleXmlWriter& operator=(const SimpleXmlWriter&);
};
template<typename TStreamType>
class SimpleXmlWriterImpl : public SimpleXmlWriter
{
PxProfileAllocatorWrapper mWrapper;
TStreamType& mStream;
SimpleXmlWriterImpl( const SimpleXmlWriterImpl& inOther );
SimpleXmlWriterImpl& operator=( const SimpleXmlWriterImpl& inOther );
PxProfileArray<const char*> mTags;
bool mTagOpen;
PxU32 mInitialTagDepth;
public:
SimpleXmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 )
: mWrapper( inAllocator )
, mStream( inStream )
, mTags( mWrapper )
, mTagOpen( false )
, mInitialTagDepth( inInitialTagDepth )
{
}
virtual ~SimpleXmlWriterImpl()
{
while( mTags.size() )
endTag();
}
PxU32 tabCount() { return mTags.size() + mInitialTagDepth; }
void writeTabs( PxU32 inSize )
{
inSize += mInitialTagDepth;
for ( PxU32 idx =0; idx < inSize; ++idx )
mStream << "\t";
}
void beginTag( const char* inTagname )
{
closeTag();
writeTabs(mTags.size());
mTags.pushBack( inTagname );
mStream << "<" << inTagname;
mTagOpen = true;
}
void addAttribute( const char* inName, const char* inValue )
{
PX_ASSERT( mTagOpen );
mStream << " " << inName << "=" << "\"" << inValue << "\"";
}
void closeTag(bool useNewline = true)
{
if ( mTagOpen )
{
mStream << " " << ">";
if (useNewline )
mStream << "\n";
}
mTagOpen = false;
}
void doEndOpenTag()
{
mStream << "</" << mTags.back() << ">" << "\n";
}
void endTag()
{
PX_ASSERT( mTags.size() );
if ( mTagOpen )
mStream << " " << "/>" << "\n";
else
{
writeTabs(mTags.size()-1);
doEndOpenTag();
}
mTagOpen = false;
mTags.popBack();
}
static bool IsNormalizableWhitespace(char c) { return c == 0x9 || c == 0xA || c == 0xD; }
static bool IsValidXmlCharacter(char c) { return IsNormalizableWhitespace(c) || c >= 0x20; }
void addContent( const char* inContent )
{
closeTag(false);
//escape xml
for( ; *inContent; inContent++ )
{
switch (*inContent)
{
case '<':
mStream << "&lt;";
break;
case '>':
mStream << "&gt;";
break;
case '&':
mStream << "&amp;";
break;
case '\'':
mStream << "&apos;";
break;
case '"':
mStream << "&quot;";
break;
default:
if (IsValidXmlCharacter(*inContent)) {
if (IsNormalizableWhitespace(*inContent))
{
char s[32];
Pxsnprintf(s, 32, "&#x%02X;", unsigned(*inContent));
mStream << s;
}
else
mStream << *inContent;
}
break;
}
}
}
void writeContentTag( const char* inTag, const char* inContent )
{
beginTag( inTag );
addContent( inContent );
doEndOpenTag();
mTags.popBack();
}
void insertXml( const char* inXml )
{
closeTag();
mStream << inXml;
}
};
struct BeginTag
{
const char* mTagName;
BeginTag( const char* inTagName )
: mTagName( inTagName ) { }
};
struct EndTag
{
EndTag() {}
};
struct Att
{
const char* mAttName;
const char* mAttValue;
Att( const char* inAttName, const char* inAttValue )
: mAttName( inAttName )
, mAttValue( inAttValue ) { }
};
struct Content
{
const char* mContent;
Content( const char* inContent )
: mContent( inContent ) { }
};
struct ContentTag
{
const char* mTagName;
const char* mContent;
ContentTag( const char* inTagName, const char* inContent )
: mTagName( inTagName )
, mContent( inContent ) { }
};
inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; }
inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const EndTag& inTag ) { PX_UNUSED(inTag); inWriter.endTag(); return inWriter; }
inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; }
inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; }
inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; }
inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName )
{
PxU8 data = 0;
tempBuffer.write( &data, sizeof(PxU8) );
inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) );
tempBuffer.clear();
}
template<typename TDataType>
inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue )
{
tempBuffer << inValue;
writeProperty( inWriter, tempBuffer, inPropName );
}
} }
#endif

View File

@@ -0,0 +1,193 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_DESERIALIZER_H
#define SN_XML_DESERIALIZER_H
#include "SnXmlVisitorReader.h"
namespace physx { namespace Sn {
//Definitions needed internally in the Serializer headers.
template<typename TTriIndexElem>
struct Triangle
{
TTriIndexElem mIdx0;
TTriIndexElem mIdx1;
TTriIndexElem mIdx2;
Triangle( TTriIndexElem inIdx0 = 0, TTriIndexElem inIdx1 = 0, TTriIndexElem inIdx2 = 0)
: mIdx0( inIdx0 )
, mIdx1( inIdx1 )
, mIdx2( inIdx2 )
{
}
};
struct XmlMemoryAllocateMemoryPoolAllocator
{
XmlMemoryAllocator* mAllocator;
XmlMemoryAllocateMemoryPoolAllocator( XmlMemoryAllocator* inAlloc ) : mAllocator( inAlloc ) {}
PxU8* allocate( PxU32 inSize ) { return mAllocator->allocate( inSize ); }
void deallocate( PxU8* inMem ) { mAllocator->deallocate( inMem ); }
};
inline bool isEmpty(const char *s)
{
while (*s != '\0')
{
if (!isspace(*s))
return false;
s++;
}
return true;
}
inline void strtoLong( Triangle<PxU32>& ioDatatype,const char*& ioData )
{
strto( ioDatatype.mIdx0, ioData );
strto( ioDatatype.mIdx1, ioData );
strto( ioDatatype.mIdx2, ioData );
}
inline void strtoLong( PxHeightFieldSample& ioDatatype,const char*& ioData )
{
PxU32 tempData;
strto( tempData, ioData );
if ( isBigEndian() )
{
PxU32& theItem(tempData);
PxU32 theDest = 0;
PxU8* theReadPtr( reinterpret_cast< PxU8* >( &theItem ) );
PxU8* theWritePtr( reinterpret_cast< PxU8* >( &theDest ) );
//A height field sample is a 16 bit number
//followed by two bytes.
//We write this out as a 32 bit integer, LE.
//Thus, on a big endian, we need to move the bytes
//around a bit.
//LE - 1 2 3 4
//BE - 4 3 2 1 - after convert from xml number
//Correct BE - 2 1 3 4, just like LE but with the 16 number swapped
theWritePtr[0] = theReadPtr[2];
theWritePtr[1] = theReadPtr[3];
theWritePtr[2] = theReadPtr[1];
theWritePtr[3] = theReadPtr[0];
theItem = theDest;
}
ioDatatype = *reinterpret_cast<PxHeightFieldSample*>( &tempData );
}
template<typename TDataType>
inline void readStridedFlagsProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator,
const PxU32ToName* inConversions)
{
const char* theSrcData;
outStride = sizeof( TDataType );
outData = NULL;
outCount = 0;
if ( ioReader.read( inPropName, theSrcData ) )
{
XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator );
MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator );
if ( theSrcData )
{
char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) );
char* aData = strtok(theStartData, " \n");
while( aData )
{
TDataType tempValue;
stringToFlagsType( aData, inAllocator, tempValue, inConversions );
aData = strtok(NULL," \n");
tempBuffer.write( &tempValue, sizeof(TDataType) );
}
outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer );
outCount = tempBuffer.mWriteOffset / sizeof( TDataType );
tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) );
}
tempBuffer.releaseBuffer();
}
}
template<typename TDataType>
inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator)
{
const char* theSrcData;
outStride = sizeof( TDataType );
outData = NULL;
outCount = 0;
if ( ioReader.read( inPropName, theSrcData ) )
{
XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator );
MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator );
if ( theSrcData )
{
char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) );
const char* theData = theStartData;
while( !isEmpty(theData) )
{
//These buffers are whitespace delimited.
TDataType theType;
strtoLong( theType, theData );
tempBuffer.write( &theType, sizeof(theType) );
}
outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer );
outCount = tempBuffer.mWriteOffset / sizeof( TDataType );
tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) );
}
tempBuffer.releaseBuffer();
}
}
template<typename TDataType>
inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxStridedData& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator)
{
TDataType* tempData = NULL;
readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator );
ioData.data = tempData;
}
template<typename TDataType>
inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxTypedBoundedData<const TDataType>& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator)
{
TDataType* tempData = NULL;
readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator );
ioData.data = reinterpret_cast<PxMaterialTableIndex*>( tempData );
}
template<typename TDataType>
inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxBoundedData& ioData, XmlMemoryAllocator& inAllocator)
{
return readStridedBufferProperty<TDataType>( ioReader, inPropName, ioData, ioData.count, inAllocator );
}
} }
#endif

View File

@@ -0,0 +1,243 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_IMPL_H
#define SN_XML_IMPL_H
#include "SnXmlMemoryPool.h"
#include "foundation/PxString.h"
#include "foundation/PxMemory.h"
namespace physx { namespace Sn {
typedef CMemoryPoolManager TMemoryPoolManager;
namespace snXmlImpl {
inline PxU32 strLen( const char* inStr )
{
PxU32 len = 0;
if ( inStr )
{
while ( *inStr )
{
++len;
++inStr;
}
}
return len;
}
}
inline const char* copyStr( PxAllocatorCallback& inAllocator, const char* inStr )
{
if ( inStr && *inStr )
{
PxU32 theLen = snXmlImpl::strLen( inStr );
//The memory will never be released by repx. If you want it released, you need to pass in a custom allocator
//that tracks all allocations and releases unreleased allocations yourself.
char* dest = reinterpret_cast<char* >( inAllocator.allocate( theLen + 1, "Repx::const char*", PX_FL ) );
PxMemCopy( dest, inStr, theLen );
dest[theLen] = 0;
return dest;
}
return "";
}
template<typename TManagerType>
inline const char* copyStr( TManagerType* inMgr, const char* inStr )
{
if ( inStr && *inStr )
{
PxU32 theLen = snXmlImpl::strLen( inStr );
char* dest = reinterpret_cast<char* >( inMgr->allocate( theLen + 1 ) );
PxMemCopy( dest, inStr, theLen );
dest[theLen] = 0;
return dest;
}
return "";
}
inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr, PxU32 )
{
if ( inStr && *inStr )
{
inMgr->deallocate( reinterpret_cast< PxU8* >( const_cast<char*>( inStr ) ) );
}
}
inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr )
{
if ( inStr && *inStr )
{
PxU32 theLen = snXmlImpl::strLen( inStr );
releaseStr( inMgr, inStr, theLen );
}
}
struct XmlNode
{
const char* mName; //Never released until all collections are released
const char* mData; //Never released until all collections are released
XmlNode* mNextSibling;
XmlNode* mPreviousSibling;
XmlNode* mFirstChild;
XmlNode* mParent;
XmlNode( const XmlNode& );
XmlNode& operator=( const XmlNode& );
PX_INLINE void initPtrs()
{
mNextSibling = NULL;
mPreviousSibling = NULL;
mFirstChild = NULL;
mParent = NULL;
}
PX_INLINE XmlNode( const char* inName = "", const char* inData = "" )
: mName( inName )
, mData( inData )
{ initPtrs(); }
void addChild( XmlNode* inItem )
{
inItem->mParent = this;
if ( mFirstChild == NULL )
mFirstChild = inItem;
else
{
XmlNode* theNode = mFirstChild;
//Follow the chain till the end.
while( theNode->mNextSibling != NULL )
theNode = theNode->mNextSibling;
theNode->mNextSibling = inItem;
inItem->mPreviousSibling = theNode;
}
}
PX_INLINE XmlNode* findChildByName( const char* inName )
{
for ( XmlNode* theNode = mFirstChild; theNode; theNode = theNode->mNextSibling )
{
XmlNode* theRepXNode = theNode;
if ( physx::Pxstricmp( theRepXNode->mName, inName ) == 0 )
return theNode;
}
return NULL;
}
PX_INLINE void orphan()
{
if ( mParent )
{
if ( mParent->mFirstChild == this )
mParent->mFirstChild = mNextSibling;
}
if ( mPreviousSibling )
mPreviousSibling->mNextSibling = mNextSibling;
if ( mNextSibling )
mNextSibling->mPreviousSibling = mPreviousSibling;
if ( mFirstChild )
mFirstChild->mParent = NULL;
initPtrs();
}
};
inline XmlNode* allocateRepXNode( TMemoryPoolManager* inManager, const char* inName, const char* inData )
{
XmlNode* retval = inManager->allocate<XmlNode>();
retval->mName = copyStr( inManager, inName );
retval->mData = copyStr( inManager, inData );
return retval;
}
inline void release( TMemoryPoolManager* inManager, XmlNode* inNode )
{
//We *don't* release the strings associated with the node
//because they could be shared. Instead, we just let them 'leak'
//in some sense, at least until the memory manager itself is deleted.
//DO NOT UNCOMMENT THE LINES BELOW!!
//releaseStr( inManager, inNode->mName );
//releaseStr( inManager, inNode->mData );
inManager->deallocate( inNode );
}
static PX_INLINE void releaseNodeAndChildren( TMemoryPoolManager* inManager, XmlNode* inNode )
{
if ( inNode->mFirstChild )
{
XmlNode* childNode( inNode->mFirstChild );
while( childNode )
{
XmlNode* _node( childNode );
childNode = _node->mNextSibling;
releaseNodeAndChildren( inManager, _node );
}
}
inNode->orphan();
release( inManager, inNode );
}
static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent );
static XmlNode* copyRepXNode( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent = NULL )
{
XmlNode* newNode( allocateRepXNode( inManager, NULL, NULL ) );
newNode->mName = inNode->mName; //Some light structural sharing
newNode->mData = inNode->mData; //Some light structural sharing
newNode->mParent = inParent;
if ( inNode->mFirstChild )
newNode->mFirstChild = copyRepXNodeAndSiblings( inManager, inNode->mFirstChild, newNode );
return newNode;
}
static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent )
{
XmlNode* sibling = inNode->mNextSibling;
if ( sibling ) sibling = copyRepXNodeAndSiblings( inManager, sibling, inParent );
XmlNode* newNode = copyRepXNode( inManager, inNode, inParent );
newNode->mNextSibling = sibling;
if ( sibling ) sibling->mPreviousSibling = newNode;
return newNode;
}
inline bool isBigEndian() { int i = 1; return *(reinterpret_cast<char*>(&i))==0; }
struct NameStackEntry
{
const char* mName;
bool mOpen;
NameStackEntry( const char* nm ) : mName( nm ), mOpen( false ) {}
};
typedef PxProfileArray<NameStackEntry> TNameStack;
} }
#endif

View File

@@ -0,0 +1,129 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_MEMORY_ALLOCATOR_H
#define SN_XML_MEMORY_ALLOCATOR_H
#include "foundation/PxSimpleTypes.h"
namespace physx {
class PX_DEPRECATED XmlMemoryAllocator
{
protected:
virtual ~XmlMemoryAllocator(){}
public:
virtual PxU8* allocate(PxU32 inSize) = 0;
virtual void deallocate( PxU8* inMem ) = 0;
virtual PxAllocatorCallback& getAllocator() = 0;
template<typename TObjectType>
TObjectType* allocate()
{
TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) );
new (retval) TObjectType();
return retval;
}
template<typename TObjectType, typename TArgType>
TObjectType* allocate(const TArgType &arg)
{
TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) );
new (retval) TObjectType(arg);
return retval;
}
template<typename TObjectType>
void deallocate( TObjectType* inObject )
{
deallocate( reinterpret_cast<PxU8*>( inObject ) );
}
template<typename TObjectType>
inline TObjectType* batchAllocate(PxU32 inCount )
{
TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
for ( PxU32 idx = 0; idx < inCount; ++idx )
{
new (retval + idx) TObjectType();
}
return retval;
}
template<typename TObjectType, typename TArgType>
inline TObjectType* batchAllocate(PxU32 inCount, const TArgType &arg)
{
TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
for ( PxU32 idx = 0; idx < inCount; ++idx )
{
new (retval + idx) TObjectType(arg);
}
return retval;
}
//Duplicate function definition for gcc.
template<typename TObjectType>
inline TObjectType* batchAllocate(TObjectType*, PxU32 inCount )
{
TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
for ( PxU32 idx = 0; idx < inCount; ++idx )
{
new (retval + idx) TObjectType();
}
return retval;
}
};
struct PX_DEPRECATED XmlMemoryAllocatorImpl : public XmlMemoryAllocator
{
Sn::TMemoryPoolManager mManager;
XmlMemoryAllocatorImpl( PxAllocatorCallback& inAllocator )
: mManager( inAllocator )
{
}
XmlMemoryAllocatorImpl &operator=(const XmlMemoryAllocatorImpl &);
virtual PxAllocatorCallback& getAllocator()
{
return mManager.getWrapper().getAllocator();
}
virtual PxU8* allocate(PxU32 inSize )
{
if ( !inSize )
return NULL;
return mManager.allocate( inSize );
}
virtual void deallocate( PxU8* inMem )
{
if ( inMem )
mManager.deallocate( inMem );
}
};
}
#endif

View File

@@ -0,0 +1,373 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_MEMORY_POOL_H
#define SN_XML_MEMORY_POOL_H
#include "foundation/PxAssert.h"
#include "foundation/PxArray.h"
#include "PxProfileAllocatorWrapper.h"
namespace physx {
using namespace physx::profile;
/**
* Linked list used to store next node ptr.
*/
struct SMemPoolNode
{
SMemPoolNode* mNextNode;
};
/**
* Template arguments are powers of two.
* A very fast memory pool that is not memory efficient. It contains a vector of pointers
* to blocks of memory along with a linked list of free sections. All sections are
* of the same size so allocating memory is very fast, there isn't a linear search
* through blocks of indeterminate size. It also means there is memory wasted
* when objects aren't sized to powers of two.
*/
template<PxU8 TItemSize
, PxU8 TItemCount >
class CMemoryPool
{
typedef PxProfileArray<PxU8*> TPxU8PtrList;
PxProfileAllocatorWrapper& mWrapper;
TPxU8PtrList mAllMemory;
SMemPoolNode* mFirstFreeNode;
public:
CMemoryPool(PxProfileAllocatorWrapper& inWrapper)
: mWrapper( inWrapper )
, mAllMemory( inWrapper )
, mFirstFreeNode( NULL )
{}
~CMemoryPool()
{
TPxU8PtrList::ConstIterator theEnd = mAllMemory.end();
for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin();
theIter != theEnd;
++theIter )
{
PxU8* thePtr = *theIter;
mWrapper.getAllocator().deallocate( thePtr );
}
mAllMemory.clear();
mFirstFreeNode = NULL;
}
//Using deallocated memory to hold the pointers to the next amount of memory.
PxU8* allocate()
{
if ( mFirstFreeNode )
{
PxU8* retval = reinterpret_cast<PxU8*>(mFirstFreeNode);
mFirstFreeNode = mFirstFreeNode->mNextNode;
return retval;
}
PxU32 itemSize = GetItemSize();
PxU32 itemCount = 1 << TItemCount;
//No free nodes, make some more.
PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( itemCount * itemSize, "RepX fixed-size memory pool", PX_FL));
PxU8* dataPtr = retval + itemSize;
//Free extra chunks
for( PxU32 idx = 1; idx < itemCount; ++idx, dataPtr += itemSize )
deallocate( dataPtr );
mAllMemory.pushBack(retval);
return retval;
}
void deallocate( PxU8* inData )
{
SMemPoolNode* nodePtr = reinterpret_cast<SMemPoolNode*>(inData);
nodePtr->mNextNode = mFirstFreeNode;
mFirstFreeNode = nodePtr;
}
//We have to have at least a pointer's worth of memory
inline PxU32 GetItemSize() { return sizeof(SMemPoolNode) << TItemSize; }
};
typedef PxU32 TMemAllocSizeType;
struct SVariableMemPoolNode : SMemPoolNode
{
TMemAllocSizeType mSize;
SVariableMemPoolNode* NextNode() { return static_cast< SVariableMemPoolNode* >( mNextNode ); }
};
/**
* Manages variable sized allocations.
* Keeps track of freed allocations in a insertion sorted
* list. Allocating new memory traverses the list linearly.
* This object will split nodes if the node is more than
* twice as large as the request memory allocation.
*/
class CVariableMemoryPool
{
typedef PxProfileHashMap<TMemAllocSizeType, SVariableMemPoolNode*> TFreeNodeMap;
typedef PxProfileArray<PxU8*> TPxU8PtrList;
PxProfileAllocatorWrapper& mWrapper;
TPxU8PtrList mAllMemory;
TFreeNodeMap mFreeNodeMap;
PxU32 mMinAllocationSize;
CVariableMemoryPool &operator=(const CVariableMemoryPool &);
public:
CVariableMemoryPool(PxProfileAllocatorWrapper& inWrapper, PxU32 inMinAllocationSize = 0x20 )
: mWrapper( inWrapper )
, mAllMemory( inWrapper )
, mFreeNodeMap( inWrapper)
, mMinAllocationSize( inMinAllocationSize )
{}
~CVariableMemoryPool()
{
TPxU8PtrList::ConstIterator theEnd = mAllMemory.end();
for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin();
theIter != theEnd;
++theIter )
{
PxU8* thePtr = *theIter;
mWrapper.getAllocator().deallocate( thePtr );
}
mAllMemory.clear();
mFreeNodeMap.clear();
}
PxU8* MarkMem( PxU8* inMem, TMemAllocSizeType inSize )
{
PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) );
SVariableMemPoolNode* theMem = reinterpret_cast<SVariableMemPoolNode*>( inMem );
theMem->mSize = inSize;
return reinterpret_cast< PxU8* >( theMem + 1 );
}
//Using deallocated memory to hold the pointers to the next amount of memory.
PxU8* allocate( PxU32 size )
{
//Ensure we can place the size of the memory at the start
//of the memory block.
//Kai: to reduce the size of hash map, the requested size is aligned to 128 bytes
PxU32 theRequestedSize = (size + sizeof(SVariableMemPoolNode) + 127) & ~127;
TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( theRequestedSize ) );
if ( NULL != entry )
{
SVariableMemPoolNode* theNode = entry->second;
PX_ASSERT( NULL != theNode );
PX_ASSERT( theNode->mSize == theRequestedSize );
entry->second = theNode->NextNode();
if (entry->second == NULL)
mFreeNodeMap.erase( theRequestedSize );
return reinterpret_cast< PxU8* >( theNode + 1 );
}
if ( theRequestedSize < mMinAllocationSize )
theRequestedSize = mMinAllocationSize;
//No large enough free nodes, make some more.
PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( size_t(theRequestedSize), "RepX variable sized memory pool", PX_FL));
//If we allocated it, we free it.
mAllMemory.pushBack( retval );
return MarkMem( retval, theRequestedSize );
}
//The size is stored at the beginning of the memory block.
void deallocate( PxU8* inData )
{
SVariableMemPoolNode* theData = reinterpret_cast< SVariableMemPoolNode* >( inData ) - 1;
TMemAllocSizeType theSize = theData->mSize;
AddFreeMem( reinterpret_cast< PxU8* >( theData ), theSize );
}
void CheckFreeListInvariant( SVariableMemPoolNode* inNode )
{
if ( inNode && inNode->mNextNode )
{
PX_ASSERT( inNode->mSize <= inNode->NextNode()->mSize );
}
}
void AddFreeMem( PxU8* inMemory, TMemAllocSizeType inSize )
{
PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) );
SVariableMemPoolNode* theNewNode = reinterpret_cast< SVariableMemPoolNode* >( inMemory );
theNewNode->mNextNode = NULL;
theNewNode->mSize = inSize;
TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( inSize ) );
if (NULL != entry)
{
theNewNode->mNextNode = entry->second;
entry->second = theNewNode;
}
else
{
mFreeNodeMap.insert( inSize, theNewNode );
}
}
};
/**
* The manager keeps a list of memory pools for different sizes of allocations.
* Anything too large simply gets allocated using the new operator.
* This doesn't mark the memory with the size of the allocated memory thus
* allowing much more efficient allocation of small items. For large enough
* allocations, it does mark the size.
*
* When using as a general memory manager, you need to wrap this class with
* something that actually does mark the returned allocation with the size
* of the allocation.
*/
class CMemoryPoolManager
{
CMemoryPoolManager &operator=(const CMemoryPoolManager &);
public:
PxProfileAllocatorWrapper mWrapper;
//CMemoryPool<0,8> m0ItemPool;
//CMemoryPool<1,8> m1ItemPool;
//CMemoryPool<2,8> m2ItemPool;
//CMemoryPool<3,8> m3ItemPool;
//CMemoryPool<4,8> m4ItemPool;
//CMemoryPool<5,8> m5ItemPool;
//CMemoryPool<6,8> m6ItemPool;
//CMemoryPool<7,8> m7ItemPool;
//CMemoryPool<8,8> m8ItemPool;
CVariableMemoryPool mVariablePool;
CMemoryPoolManager( PxAllocatorCallback& inAllocator )
: mWrapper( inAllocator )
//, m0ItemPool( mWrapper )
//, m1ItemPool( mWrapper )
//, m2ItemPool( mWrapper )
//, m3ItemPool( mWrapper )
//, m4ItemPool( mWrapper )
//, m5ItemPool( mWrapper )
//, m6ItemPool( mWrapper )
//, m7ItemPool( mWrapper )
//, m8ItemPool( mWrapper )
, mVariablePool( mWrapper )
{
}
PxProfileAllocatorWrapper& getWrapper() { return mWrapper; }
inline PxU8* allocate( PxU32 inSize )
{
/*
if ( inSize <= m0ItemPool.GetItemSize() )
return m0ItemPool.allocate();
if ( inSize <= m1ItemPool.GetItemSize() )
return m1ItemPool.allocate();
if ( inSize <= m2ItemPool.GetItemSize() )
return m2ItemPool.allocate();
if ( inSize <= m3ItemPool.GetItemSize() )
return m3ItemPool.allocate();
if ( inSize <= m4ItemPool.GetItemSize() )
return m4ItemPool.allocate();
if ( inSize <= m5ItemPool.GetItemSize() )
return m5ItemPool.allocate();
if ( inSize <= m6ItemPool.GetItemSize() )
return m6ItemPool.allocate();
if ( inSize <= m7ItemPool.GetItemSize() )
return m7ItemPool.allocate();
if ( inSize <= m8ItemPool.GetItemSize() )
return m8ItemPool.allocate();
*/
return mVariablePool.allocate( inSize );
}
inline void deallocate( PxU8* inMemory )
{
if ( inMemory == NULL )
return;
/*
if ( inSize <= m0ItemPool.GetItemSize() )
m0ItemPool.deallocate(inMemory);
else if ( inSize <= m1ItemPool.GetItemSize() )
m1ItemPool.deallocate(inMemory);
else if ( inSize <= m2ItemPool.GetItemSize() )
m2ItemPool.deallocate(inMemory);
else if ( inSize <= m3ItemPool.GetItemSize() )
m3ItemPool.deallocate(inMemory);
else if ( inSize <= m4ItemPool.GetItemSize() )
m4ItemPool.deallocate(inMemory);
else if ( inSize <= m5ItemPool.GetItemSize() )
m5ItemPool.deallocate(inMemory);
else if ( inSize <= m6ItemPool.GetItemSize() )
m6ItemPool.deallocate(inMemory);
else if ( inSize <= m7ItemPool.GetItemSize() )
m7ItemPool.deallocate(inMemory);
else if ( inSize <= m8ItemPool.GetItemSize() )
m8ItemPool.deallocate(inMemory);
else
*/
mVariablePool.deallocate(inMemory);
}
/**
* allocate an object. Calls constructor on the new memory.
*/
template<typename TObjectType>
inline TObjectType* allocate()
{
TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) ) );
new (retval)TObjectType();
return retval;
}
/**
* deallocate an object calling the destructor on the object.
* This *must* be the concrete type, it cannot be a generic type.
*/
template<typename TObjectType>
inline void deallocate( TObjectType* inObject )
{
inObject->~TObjectType();
deallocate( reinterpret_cast<PxU8*>(inObject) );
}
/**
* allocate an object. Calls constructor on the new memory.
*/
template<typename TObjectType>
inline TObjectType* BatchAllocate(PxU32 inCount )
{
TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
return retval;
}
/**
* deallocate an object calling the destructor on the object.
* This *must* be the concrete type, it cannot be a generic type.
*/
template<typename TObjectType>
inline void BatchDeallocate( TObjectType* inObject, PxU32 inCount )
{
PX_UNUSED(inCount);
deallocate( reinterpret_cast<PxU8*>(inObject) );
}
};
}
#endif

View File

@@ -0,0 +1,172 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_MEMORY_POOL_STREAMS_H
#define SN_XML_MEMORY_POOL_STREAMS_H
#include "foundation/PxTransform.h"
#include "foundation/PxIO.h"
#include "SnXmlMemoryPool.h"
namespace physx {
template<typename TDataType>
struct XmlDefaultValue
{
bool force_compile_error;
};
#define XML_DEFINE_DEFAULT_VALUE(type, defVal ) \
template<> \
struct XmlDefaultValue<type> \
{ \
type getDefaultValue() { return type(defVal); } \
};
XML_DEFINE_DEFAULT_VALUE(PxU8, 0)
XML_DEFINE_DEFAULT_VALUE(PxI8, 0)
XML_DEFINE_DEFAULT_VALUE(PxU16, 0)
XML_DEFINE_DEFAULT_VALUE(PxI16, 0)
XML_DEFINE_DEFAULT_VALUE(PxU32, 0)
XML_DEFINE_DEFAULT_VALUE(PxI32, 0)
XML_DEFINE_DEFAULT_VALUE(PxU64, 0)
XML_DEFINE_DEFAULT_VALUE(PxI64, 0)
XML_DEFINE_DEFAULT_VALUE(PxF32, 0)
XML_DEFINE_DEFAULT_VALUE(PxF64, 0)
#undef XML_DEFINE_DEFAULT_VALUE
template<>
struct XmlDefaultValue<PxVec3>
{
PxVec3 getDefaultValue() { return PxVec3( 0,0,0 ); }
};
template<>
struct XmlDefaultValue<PxTransform>
{
PxTransform getDefaultValue() { return PxTransform(PxIdentity); }
};
template<>
struct XmlDefaultValue<PxQuat>
{
PxQuat getDefaultValue() { return PxQuat(PxIdentity); }
};
/**
* Mapping of PxOutputStream to a memory pool manager.
* Allows write-then-read semantics of a set of
* data. Can safely write up to 4GB of data; then you
* will silently fail...
*/
template<typename TAllocatorType>
struct MemoryBufferBase : public PxOutputStream, public PxInputStream
{
TAllocatorType* mManager;
mutable PxU32 mWriteOffset;
mutable PxU32 mReadOffset;
PxU8* mBuffer;
PxU32 mCapacity;
MemoryBufferBase( TAllocatorType* inManager )
: mManager( inManager )
, mWriteOffset( 0 )
, mReadOffset( 0 )
, mBuffer( NULL )
, mCapacity( 0 )
{
}
virtual ~MemoryBufferBase()
{
mManager->deallocate( mBuffer );
}
PxU8* releaseBuffer()
{
clear();
mCapacity = 0;
PxU8* retval(mBuffer);
mBuffer = NULL;
return retval;
}
void clear()
{
mWriteOffset = mReadOffset = 0;
}
virtual PxU32 read(void* dest, PxU32 count)
{
bool fits = ( mReadOffset + count ) <= mWriteOffset;
PX_ASSERT( fits );
if ( fits )
{
PxMemCopy( dest, mBuffer + mReadOffset, count );
mReadOffset += count;
return count;
}
return 0;
}
inline void checkCapacity( PxU32 inNewCapacity )
{
if ( mCapacity < inNewCapacity )
{
PxU32 newCapacity = 32;
while( newCapacity < inNewCapacity )
newCapacity = newCapacity << 1;
PxU8* newData( mManager->allocate( newCapacity ) );
if ( mWriteOffset )
PxMemCopy( newData, mBuffer, mWriteOffset );
mManager->deallocate( mBuffer );
mBuffer = newData;
mCapacity = newCapacity;
}
}
virtual PxU32 write(const void* src, PxU32 count)
{
checkCapacity( mWriteOffset + count );
PxMemCopy( mBuffer + mWriteOffset, src, count );
mWriteOffset += count;
return count;
}
};
class MemoryBuffer : public MemoryBufferBase<CMemoryPoolManager >
{
public:
MemoryBuffer( CMemoryPoolManager* inManager ) : MemoryBufferBase<CMemoryPoolManager >( inManager ) {}
};
}
#endif

View File

@@ -0,0 +1,130 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_READER_H
#define SN_XML_READER_H
#include "foundation/PxSimpleTypes.h"
#include "extensions/PxRepXSimpleType.h"
namespace physx {
namespace Sn { struct XmlNode; }
/**
* Reader used to read data out of the repx format.
*/
class XmlReader
{
protected:
virtual ~XmlReader(){}
public:
/** Read a key-value pair out of the database */
virtual bool read( const char* inName, const char*& outData ) = 0;
/** Read an object id out of the database */
virtual bool read( const char* inName, PxSerialObjectId& outId ) = 0;
/** Goto a child element by name. That child becomes this reader's context */
virtual bool gotoChild( const char* inName ) = 0;
/** Goto the first child regardless of name */
virtual bool gotoFirstChild() = 0;
/** Goto the next sibling regardless of name */
virtual bool gotoNextSibling() = 0;
/** Count all children of the current object */
virtual PxU32 countChildren() = 0;
/** Get the name of the current item */
virtual const char* getCurrentItemName() = 0;
/** Get the value of the current item */
virtual const char* getCurrentItemValue() = 0;
/** Leave the current child */
virtual bool leaveChild() = 0;
/** Get reader for the parental object */
virtual XmlReader* getParentReader() = 0;
/**
* Ensures we don't leave the reader in an odd state
* due to not leaving a given child
*/
virtual void pushCurrentContext() = 0;
/** Pop the current context back to where it during push*/
virtual void popCurrentContext() = 0;
};
//Used when upgrading a repx collection
class XmlReaderWriter : public XmlReader
{
public:
//Clears the stack of nodes (push/pop current node reset)
//and sets the current node to inNode.
virtual void setNode( Sn::XmlNode& node ) = 0;
//If the child exists, add it.
//the either way goto that child.
virtual void addOrGotoChild( const char* name ) = 0;
//Value is copied into the collection, inValue has no further references
//to it.
virtual void setCurrentItemValue( const char* value ) = 0;
//Removes the child but does not release the char* name or char* data ptrs.
//Those pointers are never released and are shared among collections.
//Thus copying nodes is cheap and safe.
virtual bool removeChild( const char* name ) = 0;
virtual void release() = 0;
bool renameProperty( const char* oldName, const char* newName )
{
if ( gotoChild( oldName ) )
{
const char* value = getCurrentItemValue();
leaveChild();
removeChild( oldName );
addOrGotoChild( newName );
setCurrentItemValue( value );
leaveChild();
return true;
}
return false;
}
bool readAndRemoveProperty( const char* name, const char*& outValue )
{
bool retval = read( name, outValue );
if ( retval ) removeChild( name );
return retval;
}
bool writePropertyIfNotEmpty( const char* name, const char* value )
{
if ( value && *value )
{
addOrGotoChild( name );
setCurrentItemValue( value );
leaveChild();
return true;
}
return false;
}
};
}
#endif

View File

@@ -0,0 +1,836 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "SnXmlImpl.h"
#include "foundation/PxHash.h"
#include "foundation/PxHashMap.h"
#include "foundation/PxString.h"
#include "SnSimpleXmlWriter.h"
#include "foundation/PxSort.h"
#include "PsFastXml.h"
#include "SnXmlMemoryPool.h"
#include "PxExtensionMetaDataObjects.h"
#include "SnXmlVisitorWriter.h"
#include "SnXmlVisitorReader.h"
#include "SnXmlMemoryAllocator.h"
#include "SnXmlStringToType.h"
#include "SnRepXCollection.h"
#include "SnRepXUpgrader.h"
#include "../SnSerializationRegistry.h"
#include "CmCollection.h"
using namespace physx;
using namespace Sn;
using namespace physx::profile; //for the foundation wrapper system.
namespace physx { namespace Sn {
class XmlNodeWriter : public SimpleXmlWriter
{
XmlMemoryAllocatorImpl& mParseAllocator;
XmlNode* mCurrentNode;
XmlNode* mTopNode;
PxU32 mTabCount;
public:
XmlNodeWriter( XmlMemoryAllocatorImpl& inAllocator, PxU32 inTabCount = 0 )
: mParseAllocator( inAllocator )
, mCurrentNode( NULL )
, mTopNode( NULL )
, mTabCount( inTabCount )
{}
XmlNodeWriter& operator=(const XmlNodeWriter&);
virtual ~XmlNodeWriter(){}
void onNewNode( XmlNode* newNode )
{
if ( mCurrentNode != NULL )
mCurrentNode->addChild( newNode );
if ( mTopNode == NULL )
mTopNode = newNode;
mCurrentNode = newNode;
++mTabCount;
}
XmlNode* getTopNode() const { return mTopNode; }
virtual void beginTag( const char* inTagname )
{
onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTagname, NULL ) );
}
virtual void endTag()
{
if ( mCurrentNode )
mCurrentNode = mCurrentNode->mParent;
if ( mTabCount )
--mTabCount;
}
virtual void addAttribute( const char*, const char* )
{
PX_ASSERT( false );
}
virtual void writeContentTag( const char* inTag, const char* inContent )
{
onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTag, inContent ) );
endTag();
}
virtual void addContent( const char* inContent )
{
if ( mCurrentNode->mData )
releaseStr( &mParseAllocator.mManager, mCurrentNode->mData );
mCurrentNode->mData = copyStr( &mParseAllocator.mManager, inContent );
}
virtual PxU32 tabCount() { return mTabCount; }
};
struct XmlWriterImpl : public XmlWriter
{
PxU32 mTagDepth;
SimpleXmlWriter* mWriter;
MemoryBuffer* mMemBuffer;
XmlWriterImpl( SimpleXmlWriter* inWriter, MemoryBuffer* inMemBuffer )
: mTagDepth( 0 )
, mWriter( inWriter )
, mMemBuffer( inMemBuffer )
{
}
~XmlWriterImpl()
{
while( mTagDepth )
{
--mTagDepth;
mWriter->endTag();
}
}
virtual void write( const char* inName, const char* inData )
{
mWriter->writeContentTag( inName, inData );
}
virtual void write( const char* inName, const PxRepXObject& inLiveObject )
{
(*mMemBuffer) << inLiveObject.id;
writeProperty( *mWriter, *mMemBuffer, inName );
}
virtual void addAndGotoChild( const char* inName )
{
mWriter->beginTag( inName );
mTagDepth++;
}
virtual void leaveChild()
{
if ( mTagDepth )
{
mWriter->endTag();
--mTagDepth;
}
}
};
struct XmlParseArgs
{
XmlMemoryAllocatorImpl* mAllocator;
PxProfileArray<RepXCollectionItem>* mCollection;
XmlParseArgs( XmlMemoryAllocatorImpl* inAllocator
, PxProfileArray<RepXCollectionItem>* inCollection)
: mAllocator( inAllocator )
, mCollection( inCollection )
{
}
};
struct XmlNodeReader : public XmlReaderWriter
{
PxProfileAllocatorWrapper mWrapper;
CMemoryPoolManager& mManager;
XmlNode* mCurrentNode;
XmlNode* mTopNode;
PxProfileArray<XmlNode*> mContext;
XmlNodeReader( XmlNode* inCurrentNode, PxAllocatorCallback& inAllocator, CMemoryPoolManager& nodePoolManager )
: mWrapper( inAllocator )
, mManager( nodePoolManager )
, mCurrentNode( inCurrentNode )
, mTopNode( inCurrentNode )
, mContext( mWrapper )
{
}
//Does this node exist as data in the format.
virtual bool read( const char* inName, const char*& outData )
{
XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
if ( theChild )
{
outData = theChild->mData;
return outData && *outData;
}
return false;
}
virtual bool read( const char* inName, PxSerialObjectId& outId )
{
XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
if ( theChild )
{
const char* theValue( theChild->mData );
strto( outId, theValue );
return true;
}
return false;
}
virtual bool gotoChild( const char* inName )
{
XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
if ( theChild )
{
mCurrentNode = theChild;
return true;
}
return false;
}
virtual bool gotoFirstChild()
{
if ( mCurrentNode->mFirstChild )
{
mCurrentNode = mCurrentNode->mFirstChild;
return true;
}
return false;
}
virtual bool gotoNextSibling()
{
if ( mCurrentNode->mNextSibling )
{
mCurrentNode = mCurrentNode->mNextSibling;
return true;
}
return false;
}
virtual PxU32 countChildren()
{
PxU32 retval = 0;
for ( XmlNode* theChild = mCurrentNode->mFirstChild; theChild != NULL; theChild = theChild->mNextSibling )
++retval;
return retval;
}
virtual const char* getCurrentItemName()
{
return mCurrentNode->mName;
}
virtual const char* getCurrentItemValue()
{
return mCurrentNode->mData;
}
virtual bool leaveChild()
{
if ( mCurrentNode != mTopNode && mCurrentNode->mParent )
{
mCurrentNode = mCurrentNode->mParent;
return true;
}
return false;
}
virtual void pushCurrentContext()
{
mContext.pushBack( mCurrentNode );
}
virtual void popCurrentContext()
{
if ( mContext.size() )
{
mCurrentNode = mContext.back();
mContext.popBack();
}
}
virtual void setNode( XmlNode& inNode )
{
mContext.clear();
mCurrentNode = &inNode;
mTopNode = mCurrentNode;
}
virtual XmlReader* getParentReader()
{
XmlReader* retval = PX_PLACEMENT_NEW((mWrapper.getAllocator().allocate(sizeof(XmlNodeReader), "createNodeEditor", PX_FL)), XmlNodeReader)
( mTopNode, mWrapper.getAllocator(), mManager );
return retval;
}
virtual void addOrGotoChild( const char* inName )
{
if ( gotoChild( inName )== false )
{
XmlNode* newNode = allocateRepXNode( &mManager, inName, NULL );
mCurrentNode->addChild( newNode );
mCurrentNode = newNode;
}
}
virtual void setCurrentItemValue( const char* inValue )
{
mCurrentNode->mData = copyStr( &mManager, inValue );
}
virtual bool removeChild( const char* name )
{
XmlNode* theChild( mCurrentNode->findChildByName( name ) );
if ( theChild )
{
releaseNodeAndChildren( &mManager, theChild );
return true;
}
return false;
}
virtual void release() { this->~XmlNodeReader(); mWrapper.getAllocator().deallocate(this); }
private:
XmlNodeReader& operator=(const XmlNodeReader&);
};
PX_INLINE void freeNodeAndChildren( XmlNode* tempNode, TMemoryPoolManager& inManager )
{
for( XmlNode* theNode = tempNode->mFirstChild; theNode != NULL; theNode = theNode->mNextSibling )
freeNodeAndChildren( theNode, inManager );
tempNode->orphan();
release( &inManager, tempNode );
}
class XmlParser : public shdfnd::FastXml::Callback
{
XmlParseArgs mParseArgs;
//For parse time only allocations
XmlMemoryAllocatorImpl& mParseAllocator;
XmlNode* mCurrentNode;
XmlNode* mTopNode;
public:
XmlParser( XmlParseArgs inArgs, XmlMemoryAllocatorImpl& inParseAllocator )
: mParseArgs( inArgs )
, mParseAllocator( inParseAllocator )
, mCurrentNode( NULL )
, mTopNode( NULL )
{
}
virtual ~XmlParser(){}
virtual bool processComment(const char* /*comment*/) { return true; }
// 'element' is the name of the element that is being closed.
// depth is the recursion depth of this element.
// Return true to continue processing the XML file.
// Return false to stop processing the XML file; leaves the read pointer of the stream right after this close tag.
// The bool 'isError' indicates whether processing was stopped due to an error, or intentionally canceled early.
virtual bool processClose(const char* /*element*/,physx::PxU32 /*depth*/,bool& isError)
{
if (NULL != mCurrentNode)
{
mCurrentNode = mCurrentNode->mParent;
return true;
}
isError = true;
return false;
}
// return true to continue processing the XML document, false to skip.
virtual bool processElement(
const char *elementName, // name of the element
const char *elementData, // element data, null if none
const shdfnd::FastXml::AttributePairs& attr, // attributes
PxI32 /*lineno*/)
{
XmlNode* newNode = allocateRepXNode( &mParseAllocator.mManager, elementName, elementData );
if ( mCurrentNode )
mCurrentNode->addChild( newNode );
mCurrentNode = newNode;
//Add the elements as children.
for( PxI32 item = 0; item < attr.getNbAttr(); item ++ )
{
XmlNode* node = allocateRepXNode( &mParseAllocator.mManager, attr.getKey(PxU32(item)), attr.getValue(PxU32(item)) );
mCurrentNode->addChild( node );
}
if ( mTopNode == NULL ) mTopNode = newNode;
return true;
}
XmlNode* getTopNode() { return mTopNode; }
virtual void * allocate(PxU32 size)
{
if ( size )
return mParseAllocator.allocate(size);
return NULL;
}
virtual void deallocate(void *mem)
{
if ( mem )
mParseAllocator.deallocate(reinterpret_cast<PxU8*>(mem));
}
private:
XmlParser& operator=(const XmlParser&);
};
struct RepXCollectionSharedData
{
PxProfileAllocatorWrapper mWrapper;
XmlMemoryAllocatorImpl mAllocator;
PxU32 mRefCount;
RepXCollectionSharedData( PxAllocatorCallback& inAllocator )
: mWrapper( inAllocator )
, mAllocator( inAllocator )
, mRefCount( 0 )
{
}
~RepXCollectionSharedData() {}
void addRef() { ++mRefCount;}
void release()
{
if ( mRefCount ) --mRefCount;
if ( !mRefCount ) { this->~RepXCollectionSharedData(); mWrapper.getAllocator().deallocate(this);}
}
};
struct SharedDataPtr
{
RepXCollectionSharedData* mData;
SharedDataPtr( RepXCollectionSharedData* inData )
: mData( inData )
{
mData->addRef();
}
SharedDataPtr( const SharedDataPtr& inOther )
: mData( inOther.mData )
{
mData->addRef();
}
SharedDataPtr& operator=( const SharedDataPtr& inOther );
~SharedDataPtr()
{
mData->release();
mData = NULL;
}
RepXCollectionSharedData* operator->() { return mData; }
const RepXCollectionSharedData* operator->() const { return mData; }
};
class RepXCollectionImpl : public RepXCollection, public PxUserAllocated
{
SharedDataPtr mSharedData;
XmlMemoryAllocatorImpl& mAllocator;
PxSerializationRegistry& mSerializationRegistry;
PxProfileArray<RepXCollectionItem> mCollection;
TMemoryPoolManager mSerializationManager;
MemoryBuffer mPropertyBuffer;
PxTolerancesScale mScale;
PxVec3 mUpVector;
const char* mVersionStr;
PxCollection* mPxCollection;
public:
RepXCollectionImpl( PxSerializationRegistry& inRegistry, PxAllocatorCallback& inAllocator, PxCollection& inPxCollection )
: mSharedData( &PX_NEW_REPX_SERIALIZER( RepXCollectionSharedData ))
, mAllocator( mSharedData->mAllocator )
, mSerializationRegistry( inRegistry )
, mCollection( mSharedData->mWrapper )
, mSerializationManager( inAllocator )
, mPropertyBuffer( &mSerializationManager )
, mScale(0.f, 0.f)
, mUpVector( 0,0,0 )
, mVersionStr( getLatestVersion() )
, mPxCollection( &inPxCollection )
{
PX_ASSERT( mScale.isValid() == false );
}
RepXCollectionImpl( PxSerializationRegistry& inRegistry, const RepXCollectionImpl& inSrc, const char* inNewVersion )
: mSharedData( inSrc.mSharedData )
, mAllocator( mSharedData->mAllocator )
, mSerializationRegistry( inRegistry )
, mCollection( mSharedData->mWrapper )
, mSerializationManager( mSharedData->mWrapper.getAllocator() )
, mPropertyBuffer( &mSerializationManager )
, mScale( inSrc.mScale )
, mUpVector( inSrc.mUpVector )
, mVersionStr( inNewVersion )
, mPxCollection( NULL )
{
}
virtual ~RepXCollectionImpl()
{
PxU32 numItems = mCollection.size();
for ( PxU32 idx = 0; idx < numItems; ++idx )
{
XmlNode* theNode = mCollection[idx].descriptor;
releaseNodeAndChildren( &mAllocator.mManager, theNode );
}
}
RepXCollectionImpl& operator=(const RepXCollectionImpl&);
virtual void destroy()
{
PxProfileAllocatorWrapper tempWrapper( mSharedData->mWrapper.getAllocator() );
this->~RepXCollectionImpl();
tempWrapper.getAllocator().deallocate(this);
}
virtual void setTolerancesScale(const PxTolerancesScale& inScale) { mScale = inScale; }
virtual PxTolerancesScale getTolerancesScale() const { return mScale; }
virtual void setUpVector( const PxVec3& inUpVector ) { mUpVector = inUpVector; }
virtual PxVec3 getUpVector() const { return mUpVector; }
PX_INLINE RepXCollectionItem findItemBySceneItem( const PxRepXObject& inObject ) const
{
//See if the object is in the collection
for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
if ( mCollection[idx].liveObject.serializable == inObject.serializable )
return mCollection[idx];
return RepXCollectionItem();
}
virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs )
{
PX_ASSERT( inObject.serializable );
PX_ASSERT( inObject.id );
if ( inObject.serializable == NULL || inObject.id == 0 )
return RepXAddToCollectionResult( RepXAddToCollectionResult::InvalidParameters );
PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( inObject.typeName );
if ( theSerializer == NULL )
return RepXAddToCollectionResult( RepXAddToCollectionResult::SerializerNotFound );
RepXCollectionItem existing = findItemBySceneItem( inObject );
if ( existing.liveObject.serializable )
return RepXAddToCollectionResult( RepXAddToCollectionResult::AlreadyInCollection, existing.liveObject.id );
XmlNodeWriter theXmlWriter( mAllocator, 1 );
XmlWriterImpl theRepXWriter( &theXmlWriter, &mPropertyBuffer );
{
SimpleXmlWriter::STagWatcher theWatcher( theXmlWriter, inObject.typeName );
writeProperty( theXmlWriter, mPropertyBuffer, "Id", inObject.id );
theSerializer->objectToFile( inObject, inCollection, theRepXWriter, mPropertyBuffer,inArgs );
}
mCollection.pushBack( RepXCollectionItem( inObject, theXmlWriter.getTopNode() ) );
return RepXAddToCollectionResult( RepXAddToCollectionResult::Success, inObject.id );
}
virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inCollection )
{
for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
{
RepXCollectionItem theItem( mCollection[idx] );
PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( theItem.liveObject.typeName );
if (theSerializer )
{
XmlNodeReader theReader( theItem.descriptor, mAllocator.getAllocator(), mAllocator.mManager );
XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() );
PxRepXObject theLiveObject = theSerializer->fileToObject( theReader, instantiationAllocator, inArgs, &inCollection );
if (theLiveObject.isValid())
{
const PxBase* s = reinterpret_cast<const PxBase*>( theLiveObject.serializable ) ;
inCollection.add( *const_cast<PxBase*>(s), PxSerialObjectId( theItem.liveObject.id ));
}
else
return false;
}
else
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL,
"PxSerialization::createCollectionFromXml: "
"PxRepXSerializer missing for type %s", theItem.liveObject.typeName);
return false;
}
}
return true;
}
void saveXmlNode( XmlNode* inNode, SimpleXmlWriter& inWriter )
{
XmlNode* theNode( inNode );
if ( theNode->mData && *theNode->mData && theNode->mFirstChild == NULL )
inWriter.writeContentTag( theNode->mName, theNode->mData );
else
{
inWriter.beginTag( theNode->mName );
if ( theNode->mData && *theNode->mData )
inWriter.addContent( theNode->mData );
for ( XmlNode* theChild = theNode->mFirstChild;
theChild != NULL;
theChild = theChild->mNextSibling )
saveXmlNode( theChild, inWriter );
inWriter.endTag();
}
}
virtual void save( PxOutputStream& inStream )
{
SimpleXmlWriterImpl<PxOutputStream> theWriter( inStream, mAllocator.getAllocator() );
theWriter.beginTag( "PhysXCollection" );
theWriter.addAttribute( "version", mVersionStr );
{
XmlWriterImpl theRepXWriter( &theWriter, &mPropertyBuffer );
writeProperty( theWriter, mPropertyBuffer, "UpVector", mUpVector );
theRepXWriter.addAndGotoChild( "Scale" );
writeAllProperties( &mScale, theRepXWriter, mPropertyBuffer, *mPxCollection);
theRepXWriter.leaveChild();
}
for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
{
RepXCollectionItem theItem( mCollection[idx] );
XmlNode* theNode( theItem.descriptor );
saveXmlNode( theNode, theWriter );
}
}
void load( PxInputData& inFileBuf, SerializationRegistry& s )
{
inFileBuf.seek(0);
XmlParser theParser( XmlParseArgs( &mAllocator, &mCollection ), mAllocator );
shdfnd::FastXml* theFastXml = shdfnd::createFastXml( &theParser );
theFastXml->processXml( inFileBuf );
XmlNode* theTopNode = theParser.getTopNode();
if ( theTopNode != NULL )
{
{
XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() );
XmlNodeReader theReader( theTopNode, mAllocator.getAllocator(), mAllocator.mManager );
readProperty( theReader, "UpVector", mUpVector );
if ( theReader.gotoChild( "Scale" ) )
{
readAllProperties( PxRepXInstantiationArgs( s.getPhysics() ), theReader, &mScale, instantiationAllocator, *mPxCollection);
theReader.leaveChild();
}
const char* verStr = NULL;
if ( theReader.read( "version", verStr ) )
mVersionStr = verStr;
}
for ( XmlNode* theChild = theTopNode->mFirstChild;
theChild != NULL;
theChild = theChild->mNextSibling )
{
if ( physx::Pxstricmp( theChild->mName, "scale" ) == 0
|| physx::Pxstricmp( theChild->mName, "version" ) == 0
|| physx::Pxstricmp( theChild->mName, "upvector" ) == 0 )
continue;
XmlNodeReader theReader( theChild, mAllocator.getAllocator(), mAllocator.mManager );
PxRepXObject theObject;
theObject.typeName = theChild->mName;
theObject.serializable = NULL;
PxSerialObjectId theId = 0;
theReader.read( "Id", theId );
theObject.id = theId;
mCollection.pushBack( RepXCollectionItem( theObject, theChild ) );
}
}
else
{
PxGetFoundation().error(PxErrorCode::eDEBUG_WARNING, PX_FL,
"Cannot parse any object from the input buffer, please check the input repx data.");
}
theFastXml->release();
}
virtual const char* getVersion() { return mVersionStr; }
virtual const RepXCollectionItem* begin() const
{
return mCollection.begin();
}
virtual const RepXCollectionItem* end() const
{
return mCollection.end();
}
virtual RepXCollection& createCollection( const char* inVersionStr )
{
PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator();
RepXCollectionImpl* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(RepXCollectionImpl), "createCollection", PX_FL)), RepXCollectionImpl) ( mSerializationRegistry, *this, inVersionStr );
return *retval;
}
//Performs a deep copy of the repx node.
virtual XmlNode* copyRepXNode( const XmlNode* srcNode )
{
return physx::Sn::copyRepXNode( &mAllocator.mManager, srcNode );
}
virtual void addCollectionItem( RepXCollectionItem inItem )
{
mCollection.pushBack( inItem );
}
virtual PxAllocatorCallback& getAllocator() { return mSharedData->mAllocator.getAllocator(); }
//Create a new repx node with this name. Its value is unset.
virtual XmlNode& createRepXNode( const char* name )
{
XmlNode* newNode = allocateRepXNode( &mSharedData->mAllocator.mManager, name, NULL );
return *newNode;
}
//Release this when finished.
virtual XmlReaderWriter& createNodeEditor()
{
PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator();
XmlReaderWriter* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(XmlNodeReader), "createNodeEditor", PX_FL)), XmlNodeReader) ( NULL, allocator, mAllocator.mManager );
return *retval;
}
};
const char* RepXCollection::getLatestVersion()
{
#define TOSTR_(x) #x
#define CONCAT_(a, b, c) TOSTR_(a.##b.##c)
#define MAKE_VERSION_STR(a,b,c) CONCAT_(a, b, c)
return MAKE_VERSION_STR(PX_PHYSICS_VERSION_MAJOR,PX_PHYSICS_VERSION_MINOR,PX_PHYSICS_VERSION_BUGFIX);
}
static RepXCollection* create(SerializationRegistry& s, PxAllocatorCallback& inAllocator, PxCollection& inCollection )
{
return PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(RepXCollectionImpl), "RepXCollection::create", PX_FL)), RepXCollectionImpl) ( s, inAllocator, inCollection );
}
static RepXCollection* create(SerializationRegistry& s, PxInputData &data, PxAllocatorCallback& inAllocator, PxCollection& inCollection )
{
RepXCollectionImpl* theCollection = static_cast<RepXCollectionImpl*>( create(s, inAllocator, inCollection ) );
theCollection->load( data, s );
return theCollection;
}
}
bool PxSerialization::serializeCollectionToXml( PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, const PxCookingParams* params, const PxCollection* externalRefs, PxXmlMiscParameter* inArgs )
{
if( !PxSerialization::isSerializable(collection, sr, const_cast<PxCollection*>(externalRefs)) )
return false;
bool bRet = true;
SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
PxRepXInstantiationArgs args( sn.getPhysics(), params );
PxCollection* tmpCollection = PxCreateCollection();
PX_ASSERT(tmpCollection);
tmpCollection->add( collection );
if(externalRefs)
{
tmpCollection->add(*const_cast<PxCollection*>(externalRefs));
}
PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
Sn::RepXCollection* theRepXCollection = Sn::create(sn, allocator, *tmpCollection );
if(inArgs != NULL)
{
theRepXCollection->setTolerancesScale(inArgs->scale);
theRepXCollection->setUpVector(inArgs->upVector);
}
PxU32 nbObjects = collection.getNbObjects();
if( nbObjects )
{
sortCollection( static_cast<Cm::Collection&>(collection), sn, true);
for( PxU32 i = 0; i < nbObjects; i++ )
{
PxBase& s = collection.getObject(i);
if( PxConcreteType::eSHAPE == s.getConcreteType() )
{
PxShape& shape = static_cast<PxShape&>(s);
if( shape.isExclusive() )
continue;
}
PxSerialObjectId id = collection.getId(s);
if(id == PX_SERIAL_OBJECT_ID_INVALID)
id = static_cast<PxSerialObjectId>( size_t( &s ));
PxRepXObject ro = PxCreateRepXObject( &s, id );
if ( ro.serializable == NULL || ro.id == 0 )
{
bRet = false;
break;
}
theRepXCollection->addRepXObjectToCollection( ro, tmpCollection, args );
}
}
tmpCollection->release();
theRepXCollection->save(outputStream);
theRepXCollection->destroy();
return bRet;
}
PxCollection* PxSerialization::createCollectionFromXml(PxInputData& inputData, const PxCookingParams& params, PxSerializationRegistry& sr, const PxCollection* externalRefs, PxStringTable* stringTable, PxXmlMiscParameter* outArgs)
{
SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
PxCollection* collection = PxCreateCollection();
PX_ASSERT(collection);
if( externalRefs )
collection->add(*const_cast<PxCollection*>(externalRefs));
PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
Sn::RepXCollection* theRepXCollection = Sn::create(sn, inputData, allocator, *collection);
theRepXCollection = &Sn::RepXUpgrader::upgradeCollection( *theRepXCollection );
PxRepXInstantiationArgs args( sn.getPhysics(), &params, stringTable );
if( !theRepXCollection->instantiateCollection(args, *collection) )
{
collection->release();
theRepXCollection->destroy();
return NULL;
}
if( externalRefs )
collection->remove(*const_cast<PxCollection*>(externalRefs));
if(outArgs != NULL)
{
outArgs->upVector = theRepXCollection->getUpVector();
outArgs->scale = theRepXCollection->getTolerancesScale();
}
theRepXCollection->destroy();
return collection;
}
}

View File

@@ -0,0 +1,117 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_SERIALIZER_H
#define SN_XML_SERIALIZER_H
#include "PxExtensionMetaDataObjects.h"
#include "SnXmlVisitorWriter.h"
namespace physx {
namespace Sn {
void writeHeightFieldSample( PxOutputStream& inStream, const PxHeightFieldSample& inSample )
{
PxU32 retval = 0;
PxU8* writePtr( reinterpret_cast< PxU8*>( &retval ) );
const PxU8* inPtr( reinterpret_cast<const PxU8*>( &inSample ) );
if ( isBigEndian() )
{
//Height field samples are a
//16 bit integer followed by two bytes.
//right now, data is 2 1 3 4
//We need a 32 bit integer that
//when read in by a LE system is 4 3 2 1.
//Thus, we need a BE integer that looks like:
//4 3 2 1
writePtr[0] = inPtr[3];
writePtr[1] = inPtr[2];
writePtr[2] = inPtr[0];
writePtr[3] = inPtr[1];
}
else
{
writePtr[0] = inPtr[0];
writePtr[1] = inPtr[1];
writePtr[2] = inPtr[2];
writePtr[3] = inPtr[3];
}
inStream << retval;
}
template<typename TDataType, typename TWriteOperator>
inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const void* inData, PxU32 inStride, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
{
PX_ASSERT( inStride == 0 || inStride == sizeof( TDataType ) );
PX_UNUSED( inStride );
writeBuffer( writer, tempBuffer
, inItemsPerLine, reinterpret_cast<const TDataType*>( inData )
, inCount, inPropName, inOperator );
}
template<typename TDataType, typename TWriteOperator>
inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxStridedData& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
{
writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator );
}
template<typename TDataType, typename TWriteOperator>
inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxTypedBoundedData<TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
{
writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator );
}
template<typename TDataType, typename TWriteOperator>
inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxBoundedData& inData, PxU32 inItemsPerLine, TWriteOperator inWriteOperator )
{
writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData, inData.count, inItemsPerLine, inWriteOperator );
}
template<typename TDataType, typename TWriteOperator>
inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inWriteOperator )
{
writeStrideBuffer<TDataType>(writer, tempBuffer
, inItemsPerLine, inData, PtrAccess<TDataType>
, inCount, inPropName, inData.stride(), inWriteOperator );
}
template<typename TDataType>
inline void writeStridedFlagsProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, const PxU32ToName* inTable )
{
writeStrideFlags<TDataType>(writer, tempBuffer
, inItemsPerLine, inData, PtrAccess<TDataType>
, inCount, inPropName, inTable );
}
}
}
#endif

View File

@@ -0,0 +1,214 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_SIMPLE_XML_WRITER_H
#define SN_XML_SIMPLE_XML_WRITER_H
#include "foundation/PxArray.h"
#include "SnXmlMemoryPoolStreams.h"
namespace physx { namespace Sn {
class XmlWriter
{
public:
struct STagWatcher
{
typedef XmlWriter TXmlWriterType;
TXmlWriterType& mWriter;
STagWatcher( const STagWatcher& inOther );
STagWatcher& operator-( const STagWatcher& inOther );
STagWatcher( TXmlWriterType& inWriter, const char* inTagName )
: mWriter( inWriter )
{
mWriter.beginTag( inTagName );
}
~STagWatcher() { mWriter.endTag(); }
};
virtual ~XmlWriter(){}
virtual void beginTag( const char* inTagname ) = 0;
virtual void endTag() = 0;
virtual void addAttribute( const char* inName, const char* inValue ) = 0;
virtual void writeContentTag( const char* inTag, const char* inContent ) = 0;
virtual void addContent( const char* inContent ) = 0;
virtual PxU32 tabCount() = 0;
};
template<typename TStreamType>
class XmlWriterImpl : public XmlWriter
{
PxProfileAllocatorWrapper mWrapper;
TStreamType& mStream;
XmlWriterImpl( const XmlWriterImpl& inOther );
XmlWriterImpl& operator=( const XmlWriterImpl& inOther );
PxProfileArray<const char*> mTags;
bool mTagOpen;
PxU32 mInitialTagDepth;
public:
XmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 )
: mWrapper( inAllocator )
, mStream( inStream )
, mTags( mWrapper )
, mTagOpen( false )
, mInitialTagDepth( inInitialTagDepth )
{
}
virtual ~XmlWriterImpl()
{
while( mTags.size() )
endTag();
}
PxU32 tabCount() { return mTags.size() + mInitialTagDepth; }
void writeTabs( PxU32 inSize )
{
inSize += mInitialTagDepth;
for ( PxU32 idx =0; idx < inSize; ++idx )
mStream << "\t";
}
void beginTag( const char* inTagname )
{
closeTag();
writeTabs(mTags.size());
mTags.pushBack( inTagname );
mStream << "<" << inTagname;
mTagOpen = true;
}
void addAttribute( const char* inName, const char* inValue )
{
PX_ASSERT( mTagOpen );
mStream << " " << inName << "=" << "\"" << inValue << "\"";
}
void closeTag(bool useNewline = true)
{
if ( mTagOpen )
{
mStream << " " << ">";
if (useNewline )
mStream << "\n";
}
mTagOpen = false;
}
void doEndOpenTag()
{
mStream << "</" << mTags.back() << ">" << "\n";
}
void endTag()
{
PX_ASSERT( mTags.size() );
if ( mTagOpen )
mStream << " " << "/>" << "\n";
else
{
writeTabs(mTags.size()-1);
doEndOpenTag();
}
mTagOpen = false;
mTags.popBack();
}
void addContent( const char* inContent )
{
closeTag(false);
mStream << inContent;
}
void writeContentTag( const char* inTag, const char* inContent )
{
beginTag( inTag );
addContent( inContent );
doEndOpenTag();
mTags.popBack();
}
void insertXml( const char* inXml )
{
closeTag();
mStream << inXml;
}
};
struct BeginTag
{
const char* mTagName;
BeginTag( const char* inTagName )
: mTagName( inTagName ) { }
};
struct EndTag
{
EndTag() {}
};
struct Att
{
const char* mAttName;
const char* mAttValue;
Att( const char* inAttName, const char* inAttValue )
: mAttName( inAttName )
, mAttValue( inAttValue ) { }
};
struct Content
{
const char* mContent;
Content( const char* inContent )
: mContent( inContent ) { }
};
struct ContentTag
{
const char* mTagName;
const char* mContent;
ContentTag( const char* inTagName, const char* inContent )
: mTagName( inTagName )
, mContent( inContent ) { }
};
inline XmlWriter& operator<<( XmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; }
inline XmlWriter& operator<<( XmlWriter& inWriter, const EndTag& inTag ) { inWriter.endTag(); return inWriter; }
inline XmlWriter& operator<<( XmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; }
inline XmlWriter& operator<<( XmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; }
inline XmlWriter& operator<<( XmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; }
inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName )
{
PxU8 data = 0;
tempBuffer.write( &data, sizeof(PxU8) );
inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) );
tempBuffer.clear();
}
template<typename TDataType>
inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue )
{
tempBuffer << inValue;
writeProperty( inWriter, tempBuffer, inPropName );
}
} }
#endif

View File

@@ -0,0 +1,277 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_STRING_TO_TYPE_H
#define SN_XML_STRING_TO_TYPE_H
#include "common/PxCoreUtilityTypes.h"
#include "PxFiltering.h"
#include "foundation/PxString.h"
#include <stdio.h>
#include <ctype.h>
//Remapping function name for gcc-based systems.
#ifndef _MSC_VER
#define _strtoui64 strtoull
#endif
namespace physx { namespace Sn {
template<typename TDataType>
struct StrToImpl
{
bool compile_error;
};
template<> struct StrToImpl<PxU64> {
//Id's (void ptrs) are written to file as unsigned
//64 bit integers, so this method gets called more
//often than one might think.
PX_INLINE void strto( PxU64& ioDatatype,const char*& ioData )
{
ioDatatype = _strtoui64( ioData, const_cast<char **>(&ioData), 10 );
}
};
PX_INLINE PxF32 strToFloat(const char *str,const char **nextScan)
{
PxF32 ret;
while ( *str && isspace(static_cast<unsigned char>(*str))) str++; // skip leading whitespace
char temp[256] = "";
char *dest = temp;
char *end = &temp[255];
const char *begin = str;
while ( *str && !isspace(static_cast<unsigned char>(*str)) && dest < end ) // copy the number up to the first whitespace or eos
{
*dest++ = *str++;
}
*dest = 0;
ret = PxF32(strtod(temp,&end));
if ( nextScan )
{
*nextScan = begin+(end-temp);
}
return ret;
}
template<> struct StrToImpl<PxU32> {
PX_INLINE void strto( PxU32& ioDatatype,const char*& ioData )
{
ioDatatype = static_cast<PxU32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
}
};
template<> struct StrToImpl<PxI32> {
PX_INLINE void strto( PxI32& ioDatatype,const char*& ioData )
{
ioDatatype = static_cast<PxI32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
}
};
template<> struct StrToImpl<PxU16> {
PX_INLINE void strto( PxU16& ioDatatype,const char*& ioData )
{
ioDatatype = static_cast<PxU16>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
}
};
PX_INLINE void eatwhite(const char*& ioData )
{
if ( ioData )
{
while( isspace( static_cast<unsigned char>(*ioData) ) )
++ioData;
}
}
// copy the source data to the dest buffer until the first whitespace is encountered.
// Do not overflow the buffer based on the bufferLen provided.
// Advance the input 'ioData' pointer so that it sits just at the next whitespace
PX_INLINE void nullTerminateWhite(const char*& ioData,char *buffer,PxU32 bufferLen)
{
if ( ioData )
{
char *eof = buffer+(bufferLen-1);
char *dest = buffer;
while( *ioData && !isspace(static_cast<unsigned char>(*ioData)) && dest < eof )
{
*dest++ = *ioData++;
}
*dest = 0;
}
}
inline void nonNullTerminateWhite(const char*& ioData )
{
if ( ioData )
{
while( *ioData && !isspace( static_cast<unsigned char>(*ioData) ) )
++ioData;
}
}
template<> struct StrToImpl<PxF32> {
inline void strto( PxF32& ioDatatype,const char*& ioData )
{
ioDatatype = strToFloat(ioData,&ioData);
}
};
template<> struct StrToImpl<void*> {
inline void strto( void*& ioDatatype,const char*& ioData )
{
PxU64 theData;
StrToImpl<PxU64>().strto( theData, ioData );
ioDatatype = reinterpret_cast<void*>( size_t( theData ) );
}
};
template<> struct StrToImpl<physx::PxVec3> {
inline void strto( physx::PxVec3& ioDatatype,const char*& ioData )
{
StrToImpl<PxF32>().strto( ioDatatype[0], ioData );
StrToImpl<PxF32>().strto( ioDatatype[1], ioData );
StrToImpl<PxF32>().strto( ioDatatype[2], ioData );
}
};
template<> struct StrToImpl<PxU8*> {
inline void strto( PxU8*& /*ioDatatype*/,const char*& /*ioData*/)
{
}
};
template<> struct StrToImpl<bool> {
inline void strto( bool& ioType,const char*& inValue )
{
ioType = physx::Pxstricmp( inValue, "true" ) == 0 ? true : false;
}
};
template<> struct StrToImpl<PxU8> {
PX_INLINE void strto( PxU8& ioType,const char* & inValue)
{
ioType = static_cast<PxU8>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
}
};
template<> struct StrToImpl<PxFilterData> {
PX_INLINE void strto( PxFilterData& ioType,const char*& inValue)
{
ioType.word0 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
ioType.word1 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
ioType.word2 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
ioType.word3 = static_cast<PxU32>( strtoul( inValue, NULL, 10 ) );
}
};
template<> struct StrToImpl<PxQuat> {
PX_INLINE void strto( PxQuat& ioType,const char*& inValue )
{
ioType.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
}
};
template<> struct StrToImpl<PxTransform> {
PX_INLINE void strto( PxTransform& ioType,const char*& inValue)
{
ioType.q.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.q.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.q.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.q.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.p[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.p[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.p[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
}
};
template<> struct StrToImpl<PxBounds3> {
PX_INLINE void strto( PxBounds3& ioType,const char*& inValue)
{
ioType.minimum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.minimum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.minimum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.maximum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.maximum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.maximum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
}
};
template<> struct StrToImpl<PxMetaDataPlane> {
PX_INLINE void strto( PxMetaDataPlane& ioType,const char*& inValue)
{
ioType.normal.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.normal.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.normal.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
ioType.distance = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
}
};
template<> struct StrToImpl<PxRigidDynamic*> {
PX_INLINE void strto( PxRigidDynamic*& /*ioDatatype*/,const char*& /*ioData*/)
{
}
};
template<typename TDataType>
inline void strto( TDataType& ioType,const char*& ioData )
{
if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData );
}
template<typename TDataType>
inline void strtoLong( TDataType& ioType,const char*& ioData )
{
if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData );
}
template<typename TDataType>
inline void stringToType( const char* inValue, TDataType& ioType )
{
const char* theValue( inValue );
return strto( ioType, theValue );
}
} }
#endif

View File

@@ -0,0 +1,975 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_VISITOR_READER_H
#define SN_XML_VISITOR_READER_H
#include "foundation/PxArray.h"
#include "foundation/PxUtilities.h"
#include "RepXMetaDataPropertyVisitor.h"
#include "SnPxStreamOperators.h"
#include "SnXmlMemoryPoolStreams.h"
#include "SnXmlReader.h"
#include "SnXmlImpl.h"
#include "SnXmlMemoryAllocator.h"
#include "SnXmlStringToType.h"
namespace physx { namespace Sn {
inline PxU32 findEnumByName( const char* inName, const PxU32ToName* inTable )
{
for ( PxU32 idx = 0; inTable[idx].mName != NULL; ++idx )
{
if ( physx::Pxstricmp( inTable[idx].mName, inName ) == 0 )
return inTable[idx].mValue;
}
return 0;
}
PX_INLINE void stringToFlagsType( const char* strData, XmlMemoryAllocator& alloc, PxU32& ioType, const PxU32ToName* inTable )
{
if ( inTable == NULL )
return;
ioType = 0;
if ( strData && *strData)
{
//Destructively parse the string to get out the different flags.
char* theValue = const_cast<char*>( copyStr( &alloc, strData ) );
char* theMarker = theValue;
char* theNext = theValue;
while( theNext && *theNext )
{
++theNext;
if( *theNext == '|' )
{
*theNext = 0;
++theNext;
ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) );
theMarker = theNext;
}
}
if ( theMarker && *theMarker )
ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) );
alloc.deallocate( reinterpret_cast<PxU8*>( theValue ) );
}
}
template<typename TDataType>
PX_INLINE void stringToEnumType( const char* strData, TDataType& ioType, const PxU32ToName* inTable )
{
ioType = static_cast<TDataType>( findEnumByName( strData, inTable ) );
}
template<typename TDataType>
PX_INLINE bool readProperty( XmlReader& inReader, const char* pname, TDataType& ioType )
{
const char* value;
if ( inReader.read( pname, value ) )
{
stringToType( value, ioType );
return true;
}
return false;
}
template<typename TObjType>
inline TObjType* findReferencedObject( PxCollection& collection, PxSerialObjectId id)
{
PX_ASSERT(id > 0);
TObjType* outObject = static_cast<TObjType*>(const_cast<PxBase*>(collection.find(id)));
if (outObject == NULL)
{
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
"PxSerialization::createCollectionFromXml: "
"Reference to ID %d cannot be resolved. Make sure externalRefs collection is specified if required and "
"check Xml file for completeness.",
id);
}
return outObject;
}
template<typename TObjType>
inline bool readReference( XmlReader& inReader, PxCollection& collection, TObjType*& outObject )
{
PxSerialObjectId theId;
const char* theValue = inReader.getCurrentItemValue();
strto( theId, theValue );
if( theId == 0)
{
// the NULL pointer is a valid pointer if the input id is 0
outObject = NULL;
return true;
}
else
{
outObject = findReferencedObject<TObjType>(collection, theId);
return outObject != NULL;
}
}
template<typename TObjType>
inline bool readReference( XmlReader& inReader, PxCollection& inCollection, const char* pname, TObjType*& outObject )
{
outObject = NULL;
PxSerialObjectId theId = 0;
if (readProperty ( inReader, pname, theId ) && theId )
{
outObject = findReferencedObject<TObjType>(inCollection, theId);
}
// the NULL pointer is a valid pointer if the input id is 0
return (outObject != NULL) || 0 == theId;
}
template<typename TEnumType, typename TStorageType>
inline bool readFlagsProperty( XmlReader& reader, XmlMemoryAllocator& allocator, const char* pname, const PxU32ToName* inConversions, PxFlags<TEnumType,TStorageType>& outFlags )
{
const char* value;
if ( reader.read( pname, value ) )
{
PxU32 tempValue = 0;
stringToFlagsType( value, allocator, tempValue, inConversions );
outFlags = PxFlags<TEnumType,TStorageType>(PxTo16(tempValue) );
return true;
}
return false;
}
template<typename TObjType, typename TReaderType, typename TInfoType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info);
template<typename TObjType, typename TReaderType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj);
template<typename TReaderType, typename TGeomType>
inline PxGeometry* parseGeometry( TReaderType& reader, TGeomType& /*inGeom*/)
{
PxAllocatorCallback& inAllocator = reader.mAllocator.getAllocator();
TGeomType* shape = PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(TGeomType), "parseGeometry", PX_FL)), TGeomType);
PxClassInfoTraits<TGeomType> info;
readComplexObj( reader, shape);
return shape;
}
template<typename TReaderType>
inline void parseShape( TReaderType& visitor, PxGeometry*& outResult, PxArray<PxMaterial*>& outMaterials)
{
XmlReader& theReader( visitor.mReader );
PxCollection& collection = visitor.mCollection;
visitor.pushCurrentContext();
if ( visitor.gotoTopName() )
{
visitor.pushCurrentContext();
if ( visitor.gotoChild( "Materials" ) )
{
for( bool matSuccess = visitor.gotoFirstChild(); matSuccess;
matSuccess = visitor.gotoNextSibling() )
{
PxMaterial* material = NULL;
if(!readReference<PxMaterial>( theReader, collection, material ))
visitor.mHadError = true;
if ( material )
outMaterials.pushBack( material );
}
}
visitor.popCurrentContext();
visitor.pushCurrentContext();
PxPlaneGeometry plane;
PxHeightFieldGeometry heightField;
PxSphereGeometry sphere;
PxTriangleMeshGeometry mesh;
PxConvexMeshGeometry convex;
PxBoxGeometry box;
PxCapsuleGeometry capsule;
if ( visitor.gotoChild( "Geometry" ) )
{
if ( visitor.gotoFirstChild() )
{
const char* geomTypeName = visitor.getCurrentItemName();
if ( physx::Pxstricmp( geomTypeName, "PxSphereGeometry" ) == 0 ) outResult = parseGeometry(visitor, sphere);
else if ( physx::Pxstricmp( geomTypeName, "PxPlaneGeometry" ) == 0 ) outResult = parseGeometry(visitor, plane);
else if ( physx::Pxstricmp( geomTypeName, "PxCapsuleGeometry" ) == 0 ) outResult = parseGeometry(visitor, capsule);
else if ( physx::Pxstricmp( geomTypeName, "PxBoxGeometry" ) == 0 ) outResult = parseGeometry(visitor, box);
else if ( physx::Pxstricmp( geomTypeName, "PxConvexMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, convex);
else if ( physx::Pxstricmp( geomTypeName, "PxTriangleMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, mesh);
else if ( physx::Pxstricmp( geomTypeName, "PxHeightFieldGeometry" ) == 0 ) outResult = parseGeometry(visitor, heightField);
else
PX_ASSERT( false );
}
}
visitor.popCurrentContext();
}
visitor.popCurrentContext();
return;
}
template<typename TReaderType, typename TObjType>
inline void readShapesProperty( TReaderType& visitor, TObjType* inObj, const PxRigidActorShapeCollection* inProp = NULL, bool isSharedShape = false )
{
PX_UNUSED(isSharedShape);
PX_UNUSED(inProp);
XmlReader& theReader( visitor.mReader );
PxCollection& collection( visitor.mCollection );
visitor.pushCurrentContext();
if ( visitor.gotoTopName() )
{
//uggh working around the shape collection api.
//read out materials and geometry
for ( bool success = visitor.gotoFirstChild(); success;
success = visitor.gotoNextSibling() )
{
if( 0 == physx::Pxstricmp( visitor.getCurrentItemName(), "PxShapeRef" ) )
{
PxShape* shape = NULL;
if(!readReference<PxShape>( theReader, collection, shape ))
visitor.mHadError = true;
if(shape)
inObj->attachShape( *shape );
}
else
{
PxArray<PxMaterial*> materials;
PxGeometry* geometry = NULL;
parseShape( visitor, geometry, materials);
PxShape* theShape = NULL;
if ( materials.size() )
{
theShape = visitor.mArgs.physics.createShape( *geometry, materials.begin(), PxTo16(materials.size()), true );
if ( theShape )
{
readComplexObj( visitor, theShape );
if(theShape)
{
inObj->attachShape(*theShape);
collection.add( *theShape );
}
}
}
switch(geometry->getType())
{
case PxGeometryType::eSPHERE :
static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry();
break;
case PxGeometryType::ePLANE :
static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry();
break;
case PxGeometryType::eCAPSULE :
static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry();
break;
case PxGeometryType::eBOX :
static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry();
break;
case PxGeometryType::eCONVEXCORE:
static_cast<PxConvexCoreGeometry*>(geometry)->~PxConvexCoreGeometry();
break;
case PxGeometryType::eCONVEXMESH :
static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry();
break;
case PxGeometryType::eTRIANGLEMESH :
static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry();
break;
case PxGeometryType::eHEIGHTFIELD :
static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry();
break;
case PxGeometryType::eTETRAHEDRONMESH :
static_cast<PxTetrahedronMeshGeometry*>(geometry)->~PxTetrahedronMeshGeometry();
break;
case PxGeometryType::ePARTICLESYSTEM:
static_cast<PxParticleSystemGeometry*>(geometry)->~PxParticleSystemGeometry();
break;
case PxGeometryType::eCUSTOM :
static_cast<PxCustomGeometry*>(geometry)->~PxCustomGeometry();
break;
case PxGeometryType::eGEOMETRY_COUNT:
case PxGeometryType::eINVALID:
PX_ASSERT(0);
}
visitor.mAllocator.getAllocator().deallocate(geometry);
}
}
}
visitor.popCurrentContext();
}
struct ReaderNameStackEntry : NameStackEntry
{
bool mValid;
ReaderNameStackEntry( const char* nm, bool valid ) : NameStackEntry(nm), mValid(valid) {}
};
typedef PxProfileArray<ReaderNameStackEntry> TReaderNameStack;
template<typename TObjType>
struct RepXVisitorReaderBase
{
protected:
RepXVisitorReaderBase<TObjType>& operator=(const RepXVisitorReaderBase<TObjType>&);
public:
TReaderNameStack& mNames;
PxProfileArray<PxU32>& mContexts;
PxRepXInstantiationArgs mArgs;
XmlReader& mReader;
TObjType* mObj;
XmlMemoryAllocator& mAllocator;
PxCollection& mCollection;
bool mValid;
bool& mHadError;
RepXVisitorReaderBase( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& hadError )
: mNames( names )
, mContexts( contexts )
, mArgs( args )
, mReader( reader )
, mObj( obj )
, mAllocator( alloc )
, mCollection( collection )
, mValid( true )
, mHadError(hadError)
{
}
RepXVisitorReaderBase( const RepXVisitorReaderBase& other )
: mNames( other.mNames )
, mContexts( other.mContexts )
, mArgs( other.mArgs )
, mReader( other.mReader )
, mObj( other.mObj )
, mAllocator( other.mAllocator )
, mCollection( other.mCollection )
, mValid( other.mValid )
, mHadError( other.mHadError )
{
}
void pushName( const char* name )
{
gotoTopName();
mNames.pushBack( ReaderNameStackEntry( name, mValid ) );
}
void pushBracketedName( const char* name ) { pushName( name ); }
void popName()
{
if ( mNames.size() )
{
if ( mNames.back().mOpen && mNames.back().mValid )
mReader.leaveChild();
mNames.popBack();
}
mValid = true;
if ( mNames.size() && mNames.back().mValid == false )
mValid = false;
}
void pushCurrentContext()
{
mContexts.pushBack( static_cast<PxU32>( mNames.size() ) );
}
void popCurrentContext()
{
if ( mContexts.size() )
{
PxU32 depth = mContexts.back();
PX_ASSERT( mNames.size() >= depth );
while( mNames.size() > depth )
popName();
mContexts.popBack();
}
}
bool updateLastEntryAfterOpen()
{
mNames.back().mValid = mValid;
mNames.back().mOpen = mValid;
return mValid;
}
bool gotoTopName()
{
if ( mNames.size() && mNames.back().mOpen == false )
{
if ( mValid )
mValid = mReader.gotoChild( mNames.back().mName );
updateLastEntryAfterOpen();
}
return mValid;
}
bool isValid() const { return mValid; }
bool gotoChild( const char* name )
{
pushName( name );
return gotoTopName();
}
bool gotoFirstChild()
{
pushName( "__child" );
if ( mValid ) mValid = mReader.gotoFirstChild();
return updateLastEntryAfterOpen();
}
bool gotoNextSibling()
{
bool retval = mValid;
if ( mValid ) retval = mReader.gotoNextSibling();
return retval;
}
const char* getCurrentItemName() { if (mValid ) return mReader.getCurrentItemName(); return ""; }
const char* topName() const
{
if ( mNames.size() ) return mNames.back().mName;
PX_ASSERT( false );
return "bad__repx__name";
}
const char* getCurrentValue()
{
const char* value = NULL;
if ( isValid() && mReader.read( topName(), value ) )
return value;
return NULL;
}
template<typename TDataType>
bool readProperty(TDataType& outType)
{
const char* value = getCurrentValue();
if ( value && *value )
{
stringToType( value, outType );
return true;
}
return false;
}
template<typename TDataType>
bool readExtendedIndexProperty(TDataType& outType)
{
const char* value = mReader.getCurrentItemValue();
if ( value && *value )
{
stringToType( value, outType );
return true;
}
return false;
}
template<typename TRefType>
bool readReference(TRefType*& outRef)
{
return physx::Sn::readReference<TRefType>( mReader, mCollection, topName(), outRef );
}
inline bool readProperty(const char*& outProp )
{
outProp = "";
const char* value = getCurrentValue();
if ( value && *value && mArgs.stringTable )
{
outProp = mArgs.stringTable->allocateStr( value );
return true;
}
return false;
}
inline bool readProperty(PxConvexMesh*& outProp )
{
return readReference<PxConvexMesh>( outProp );
}
inline bool readProperty(PxTriangleMesh*& outProp )
{
return readReference<PxTriangleMesh>( outProp );
}
inline bool readProperty(PxBVH33TriangleMesh*& outProp )
{
return readReference<PxBVH33TriangleMesh>( outProp );
}
inline bool readProperty(PxBVH34TriangleMesh*& outProp )
{
return readReference<PxBVH34TriangleMesh>( outProp );
}
inline bool readProperty(PxHeightField*& outProp )
{
return readReference<PxHeightField>( outProp );
}
inline bool readProperty( PxRigidActor *& outProp )
{
return readReference<PxRigidActor>( outProp );
}
template<typename TAccessorType>
void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
{
typedef typename TAccessorType::prop_type TPropertyType;
TPropertyType value;
if ( readProperty( value ) )
inProp.set( mObj, value );
}
template<typename TAccessorType>
void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions )
{
typedef typename TAccessorType::prop_type TPropertyType;
const char* strVal = getCurrentValue();
if ( strVal && *strVal )
{
TPropertyType pval;
stringToEnumType( strVal, pval, inConversions );
inProp.set( mObj, pval );
}
}
template<typename TAccessorType>
void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions )
{
typedef typename TAccessorType::prop_type TPropertyType;
typedef typename TPropertyType::InternalType TInternalType;
const char* strVal = getCurrentValue();
if ( strVal && *strVal )
{
PxU32 tempValue = 0;
stringToFlagsType( strVal, mAllocator, tempValue, inConversions );
inProp.set( mObj, TPropertyType(TInternalType( tempValue )));
}
}
template<typename TAccessorType, typename TInfoType>
void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
if ( gotoTopName() )
{
TPropertyType propVal = inProp.get( mObj );
readComplexObj( *this, &propVal, inInfo );
inProp.set( mObj, propVal );
}
}
//
// The D6 joint has been changed such that it is necessary to specify what kind of angular drive model to apply.
// Depending on that choice, it is not legal anymore to set/get drive parameters for certain angular drive types.
// In theory, only the expected entries should have been stored and no custom check should be needed, however,
// when dumping from a PVD file to RepX, the system just blindly dumps all drive types. Hence, it is necessary
// to filter out the invalid drive types still.
//
// Note: using partial template specialization because the compiler for aarch64 did not yet support in-class
// explicit specialization
//
typedef Vd::PxPvdIndexedPropertyAccessor<PxExtensionsPropertyInfoName::PxD6Joint_Drive, PxD6Joint, PxD6Drive::Enum, PxD6JointDrive> PxD6JointDriveAccessor;
template<typename TInfoType>
void complexProperty( PxU32* /*key*/, const PxD6JointDriveAccessor& inProp, TInfoType& inInfo )
{
typedef typename PxD6JointDriveAccessor::prop_type TPropertyType;
if ( gotoTopName() )
{
if (isD6JointDriveAccessAllowed(inProp.mIndex, mObj->getAngularDriveConfig()))
{
TPropertyType propVal = inProp.get( mObj );
readComplexObj( *this, &propVal, inInfo );
inProp.set( mObj, propVal );
}
}
}
template<typename TAccessorType, typename TInfoType>
void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
PxInlineArray<TPropertyType,5> theData;
this->pushCurrentContext();
if ( this->gotoTopName() )
{
for ( bool success = this->gotoFirstChild(); success;
success = this->gotoNextSibling() )
{
TPropertyType propVal;
readComplexObj( *this, &propVal, inInfo );
theData.pushBack(propVal);
}
}
this->popCurrentContext();
inProp.set( mObj, theData.begin(), theData.size() );
}
template<typename TAccessorType, typename TInfoType>
void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
this->pushCurrentContext();
if ( this->gotoTopName() )
{
PxU32 index = 0;
for ( bool success = this->gotoFirstChild(); success;
success = this->gotoNextSibling() )
{
TPropertyType propVal;
readComplexObj( *this, &propVal, inInfo );
inProp.set(mObj, index, propVal);
++index;
}
}
this->popCurrentContext();
}
template<typename TAccessorType, typename TInfoType>
void PxFixedSizeLookupTableProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
const_cast<TAccessorType&>(inProp).clear( mObj );
this->pushCurrentContext();
if ( this->gotoTopName() )
{
for ( bool success = this->gotoFirstChild(); success;
success = this->gotoNextSibling() )
{
TPropertyType propXVal;
readComplexObj( *this, &propXVal, inInfo );
if(this->gotoNextSibling())
{
TPropertyType propYVal;
readComplexObj( *this, &propYVal, inInfo );
const_cast<TAccessorType&>(inProp).addPair(mObj, propXVal, propYVal);
}
}
}
this->popCurrentContext();
}
void handleShapes( const PxRigidActorShapeCollection& inProp )
{
physx::Sn::readShapesProperty( *this, mObj, &inProp );
}
void handleRigidActorGlobalPose(const PxRigidActorGlobalPosePropertyInfo& inProp)
{
PxArticulationLink* link = mObj->template is<PxArticulationLink>();
bool isReducedCoordinateLink = (link != NULL);
if (!isReducedCoordinateLink)
{
PxRepXPropertyAccessor<PxPropertyInfoName::PxRigidActor_GlobalPose, PxRigidActor, const PxTransform &, PxTransform> theAccessor(inProp);
simpleProperty(PxPropertyInfoName::PxRigidActor_GlobalPose, theAccessor);
}
}
};
template<typename TObjType>
struct RepXVisitorReader : public RepXVisitorReaderBase<TObjType>
{
RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
: RepXVisitorReaderBase<TObjType>( names, contexts, args, reader, obj, alloc, collection, ret)
{
}
RepXVisitorReader( const RepXVisitorReader<TObjType>& other )
: RepXVisitorReaderBase<TObjType>( other )
{
}
};
// Specialized template to load dynamic rigid, to determine the kinematic state first
template<>
struct RepXVisitorReader<PxRigidDynamic> : public RepXVisitorReaderBase<PxRigidDynamic>
{
RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxRigidDynamic* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
: RepXVisitorReaderBase<PxRigidDynamic>( names, contexts, args, reader, obj, alloc, collection, ret)
{
}
RepXVisitorReader( const RepXVisitorReader<PxRigidDynamic>& other )
: RepXVisitorReaderBase<PxRigidDynamic>( other )
{
}
void handleShapes( const PxRigidActorShapeCollection& inProp )
{
// Need to read the parental actor to check if actor is kinematic
// in that case we need to apply the kinematic flag before a shape is set
XmlReaderWriter* parentReader = static_cast<XmlReaderWriter*>(mReader.getParentReader());
if(mObj)
{
const char* value;
if (parentReader->read( "RigidBodyFlags", value ))
{
if(strstr(value, "eKINEMATIC"))
{
mObj->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
}
}
}
physx::Sn::readShapesProperty( *this, mObj, &inProp );
parentReader->release();
}
template<typename TAccessorType>
void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
{
typedef typename TAccessorType::prop_type TPropertyType;
TPropertyType value;
if (readProperty(value))
{
// If the rigid body is kinematic, we cannot set the LinearVelocity or AngularVelocity
const bool kinematic = (mObj->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC);
if(kinematic && (inProp.mProperty.mKey == PxPropertyInfoName::PxRigidDynamic_LinearVelocity || inProp.mProperty.mKey == PxPropertyInfoName::PxRigidDynamic_AngularVelocity))
return;
inProp.set(mObj, value );
}
}
private:
RepXVisitorReader<PxRigidDynamic>& operator=(const RepXVisitorReader<PxRigidDynamic>&);
};
template<>
struct RepXVisitorReader<PxShape> : public RepXVisitorReaderBase<PxShape>
{
RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxShape* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret )
: RepXVisitorReaderBase<PxShape>( names, contexts, args, reader, obj, alloc, collection, ret )
{
}
RepXVisitorReader( const RepXVisitorReader<PxShape>& other )
: RepXVisitorReaderBase<PxShape>( other )
{
}
void handleShapeMaterials( const PxShapeMaterialsProperty& ) //these were handled during construction.
{
}
void handleGeomProperty( const PxShapeGeomProperty& )
{
}
private:
RepXVisitorReader<PxShape>& operator=(const RepXVisitorReader<PxShape>&);
};
template<>
struct RepXVisitorReader<PxArticulationLink> : public RepXVisitorReaderBase<PxArticulationLink>
{
RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulationLink* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret )
: RepXVisitorReaderBase<PxArticulationLink>( names, contexts, args, reader, obj, alloc, collection, ret )
{
}
RepXVisitorReader( const RepXVisitorReader<PxArticulationLink>& other )
: RepXVisitorReaderBase<PxArticulationLink>( other )
{
}
void handleIncomingJoint( const TIncomingJointPropType& prop )
{
pushName( "Joint" );
if ( gotoTopName() )
{
PxArticulationJointReducedCoordinate* theJoint = static_cast<PxArticulationJointReducedCoordinate*>((prop.get(mObj)));
readComplexObj(*this, theJoint);
//Add joint to PxCollection, since PxArticulation requires PxArticulationLink and joint.
mCollection.add(*theJoint);
}
popName();
}
private:
RepXVisitorReader<PxArticulationLink>& operator=(const RepXVisitorReader<PxArticulationLink>&);
};
template<typename ArticulationType>
inline void readProperty( RepXVisitorReaderBase<ArticulationType>& inSerializer, ArticulationType* inObj, const PxArticulationLinkCollectionProp&)
{
PxProfileAllocatorWrapper theWrapper( inSerializer.mAllocator.getAllocator() );
PxCollection& collection( inSerializer.mCollection );
TArticulationLinkLinkMap linkRemapMap( theWrapper );
inSerializer.pushCurrentContext();
if( inSerializer.gotoTopName() )
{
for ( bool links = inSerializer.gotoFirstChild();
links != false;
links = inSerializer.gotoNextSibling() )
{
//Need enough information to create the link...
PxSerialObjectId theParentPtr = 0;
const PxArticulationLink* theParentLink = NULL;
if ( inSerializer.mReader.read( "Parent", theParentPtr ) )
{
const TArticulationLinkLinkMap::Entry* theRemappedParent( linkRemapMap.find( theParentPtr ) );
//If we have a valid at write time, we had better have a valid parent at read time.
PX_ASSERT( theRemappedParent );
theParentLink = theRemappedParent->second;
}
PxArticulationLink* newLink = inObj->createLink( const_cast<PxArticulationLink*>( theParentLink ), PxTransform(PxIdentity) );
PxSerialObjectId theIdPtr = 0;
inSerializer.mReader.read( "Id", theIdPtr );
linkRemapMap.insert( theIdPtr, newLink );
readComplexObj( inSerializer, newLink );
//Add link to PxCollection, since PxArticulation requires PxArticulationLink and joint.
collection.add( *newLink, theIdPtr );
}
}
inSerializer.popCurrentContext();
}
template<>
struct RepXVisitorReader<PxArticulationReducedCoordinate> : public RepXVisitorReaderBase<PxArticulationReducedCoordinate>
{
RepXVisitorReader(TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulationReducedCoordinate* obj
, XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
: RepXVisitorReaderBase<PxArticulationReducedCoordinate>(names, contexts, args, reader, obj, alloc, collection, ret)
{}
RepXVisitorReader(const RepXVisitorReader<PxArticulationReducedCoordinate>& other)
: RepXVisitorReaderBase<PxArticulationReducedCoordinate>(other)
{}
void handleArticulationLinks(const PxArticulationLinkCollectionProp& inProp)
{
physx::Sn::readProperty(*this, mObj, inProp);
}
};
template<typename TObjType, typename TInfoType>
inline bool readAllProperties( PxRepXInstantiationArgs args, TReaderNameStack& names, PxProfileArray<PxU32>& contexts, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection, TInfoType& info )
{
bool hadError = false;
RepXVisitorReader<TObjType> theReader( names, contexts, args, reader, obj, alloc, collection, hadError);
RepXPropertyFilter<RepXVisitorReader<TObjType> > theOp( theReader );
info.visitBaseProperties( theOp );
info.visitInstanceProperties( theOp );
return !hadError;
}
//
// Setting the angular drive config has to happen before setting any drive (because it resets drive parameters
// for angular drives). However, when the angular drive config feature got introduced, binary compatibility
// requirements did not allow to place the corresponding setter/getter in front of the drive param setter/getter.
// Thus this ugly temporary workaround to hardcode the desired order of operations. With the next major release,
// the public API methods can be re-arranged and then it should be possible to undo this sad workaround.
//
template<>
inline bool readAllProperties( PxRepXInstantiationArgs args, TReaderNameStack& names, PxProfileArray<PxU32>& contexts, XmlReader& reader, PxD6Joint* obj, XmlMemoryAllocator& alloc, PxCollection& collection, PxD6JointGeneratedInfo& info )
{
bool hadError = false;
RepXVisitorReader<PxD6Joint> theReader( names, contexts, args, reader, obj, alloc, collection, hadError);
RepXPropertyFilter<RepXVisitorReader<PxD6Joint> > theOp( theReader );
info.visitBaseProperties( theOp );
{
PxU32 inStartIndex = 0;
theOp( info.Motion, inStartIndex + 0 );
theOp( info.TwistAngle, inStartIndex + 1 );
theOp( info.Twist, inStartIndex + 2 );
theOp( info.SwingYAngle, inStartIndex + 3 );
theOp( info.SwingZAngle, inStartIndex + 4 );
theOp( info.DistanceLimit, inStartIndex + 5 );
theOp( info.LinearLimit, inStartIndex + 6 );
theOp( info.TwistLimit, inStartIndex + 7 );
theOp( info.SwingLimit, inStartIndex + 8 );
theOp( info.PyramidSwingLimit, inStartIndex + 9 );
theOp( info.AngularDriveConfig, inStartIndex + 10 );
theOp( info.Drive, inStartIndex + 11 );
theOp( info.DrivePosition, inStartIndex + 12 );
theOp( info.ConcreteTypeName, inStartIndex + 13 );
}
return !hadError;
}
template<typename TObjType>
inline bool readAllProperties( PxRepXInstantiationArgs args, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection )
{
PxProfileAllocatorWrapper wrapper( alloc.getAllocator() );
TReaderNameStack names( wrapper );
PxProfileArray<PxU32> contexts( wrapper );
PxClassInfoTraits<TObjType> info;
return readAllProperties( args, names, contexts, reader, obj, alloc, collection, info.Info );
}
template<typename TObjType, typename TReaderType, typename TInfoType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info)
{
if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info ))
oldVisitor.mHadError = true;
}
template<typename TObjType, typename TReaderType, typename TInfoType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const TInfoType& info)
{
if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info ))
oldVisitor.mHadError = true;
}
template<typename TObjType, typename TReaderType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const PxUnknownClassInfo& /*info*/)
{
const char* value = oldVisitor.mReader.getCurrentItemValue();
if ( value && *value )
{
stringToType( value, *inObj );
return;
}
oldVisitor.mHadError = true;
}
template<typename TObjType, typename TReaderType>
inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj)
{
PxClassInfoTraits<TObjType> info;
if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info.Info ))
oldVisitor.mHadError = true;
}
} }
#endif

View File

@@ -0,0 +1,828 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_VISITOR_WRITER_H
#define SN_XML_VISITOR_WRITER_H
#include "foundation/PxInlineArray.h"
#include "RepXMetaDataPropertyVisitor.h"
#include "SnPxStreamOperators.h"
#include "SnXmlMemoryPoolStreams.h"
#include "SnXmlWriter.h"
#include "SnXmlImpl.h"
#include "foundation/PxStrideIterator.h"
#include "PxExtensionMetaDataObjects.h"
namespace physx { namespace Sn {
template<typename TDataType>
inline void writeReference( XmlWriter& writer, PxCollection& inCollection, const char* inPropName, const TDataType* inDatatype )
{
const PxBase* s = static_cast<const PxBase*>( inDatatype ) ;
if( inDatatype && !inCollection.contains( *const_cast<PxBase*>(s) ))
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL,
"PxSerialization::serializeCollectionToXml: Reference \"%s\" could not be resolved.", inPropName);
}
PxSerialObjectId theId = 0;
if( s )
{
theId = inCollection.getId( *s );
if( theId == 0 )
theId = static_cast<uint64_t>(size_t(inDatatype));
}
writer.write( inPropName, PxCreateRepXObject( inDatatype, theId ) );
}
inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& inBuffer, const char* inProp )
{
PxU8 data = 0;
inBuffer.write( &data, sizeof(PxU8) );
inWriter.write( inProp, reinterpret_cast<const char*>( inBuffer.mBuffer ) );
inBuffer.clear();
}
template<typename TDataType>
inline void writeProperty( XmlWriter& inWriter, PxCollection&, MemoryBuffer& inBuffer, const char* inPropName, TDataType inValue )
{
inBuffer << inValue;
writeProperty( inWriter, inBuffer, inPropName );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxConvexMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxConvexMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxTriangleMesh* inDatatype )
{
if (inDatatype->getConcreteType() == PxConcreteType::eTRIANGLE_MESH_BVH33)
{
const PxBVH33TriangleMesh* dataType = inDatatype->is<PxBVH33TriangleMesh>();
writeReference(writer, inCollection, inPropName, dataType);
}
else if (inDatatype->getConcreteType() == PxConcreteType::eTRIANGLE_MESH_BVH34)
{
const PxBVH34TriangleMesh* dataType = inDatatype->is<PxBVH34TriangleMesh>();
writeReference(writer, inCollection, inPropName, dataType);
}
else
{
PX_ASSERT(0);
}
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxTriangleMesh* inDatatype )
{
if (inDatatype->getConcreteType() == PxConcreteType::eTRIANGLE_MESH_BVH33)
{
PxBVH33TriangleMesh* dataType = inDatatype->is<PxBVH33TriangleMesh>();
writeReference(writer, inCollection, inPropName, dataType);
}
else if (inDatatype->getConcreteType() == PxConcreteType::eTRIANGLE_MESH_BVH34)
{
PxBVH34TriangleMesh* dataType = inDatatype->is<PxBVH34TriangleMesh>();
writeReference(writer, inCollection, inPropName, dataType);
}
else
{
PX_ASSERT(0);
}
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH33TriangleMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH33TriangleMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH34TriangleMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH34TriangleMesh* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxHeightField* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxHeightField* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxRigidActor* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeProperty(XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxArticulationReducedCoordinate* inDatatype)
{
writeReference(writer, inCollection, inPropName, inDatatype);
}
inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxRigidActor* inDatatype )
{
writeReference( writer, inCollection, inPropName, inDatatype );
}
inline void writeFlagsProperty( XmlWriter& inWriter, MemoryBuffer& tempBuf, const char* inPropName, PxU32 inFlags, const PxU32ToName* inTable )
{
if ( inTable )
{
PxU32 flagValue( inFlags );
if ( flagValue )
{
for ( PxU32 idx =0; inTable[idx].mName != NULL; ++idx )
{
if ( (inTable[idx].mValue & flagValue) == inTable[idx].mValue )
{
if ( tempBuf.mWriteOffset != 0 )
tempBuf << "|";
tempBuf << inTable[idx].mName;
}
}
writeProperty( inWriter, tempBuf, inPropName );
}
else
{
if ( tempBuf.mWriteOffset != 0 )
tempBuf << "|";
tempBuf << "0";
writeProperty( inWriter, tempBuf, inPropName );
}
}
}
inline void writeFlagsBuffer( MemoryBuffer& tempBuf, PxU32 flagValue, const PxU32ToName* inTable )
{
PX_ASSERT(inTable);
bool added = false;
if ( flagValue )
{
for ( PxU32 item =0; inTable[item].mName != NULL; ++item )
{
if ( (inTable[item].mValue & flagValue) != 0 )
{
if ( added )
tempBuf << "|";
tempBuf << inTable[item].mName;
added = true;
}
}
}
}
inline void writePxVec3( PxOutputStream& inStream, const PxVec3& inVec ) { inStream << inVec; }
template<typename TDataType>
inline const TDataType& PtrAccess( const TDataType* inPtr, PxU32 inIndex )
{
return inPtr[inIndex];
}
template<typename TDataType>
inline void BasicDatatypeWrite( PxOutputStream& inStream, const TDataType& item ) { inStream << item; }
template<typename TObjType, typename TAccessOperator, typename TWriteOperator>
inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
, PxU32 inObjPerLine, const TObjType* inObjType, TAccessOperator inAccessOperator
, PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator )
{
if ( inBufSize && inObjType )
{
for ( PxU32 idx = 0; idx < inBufSize; ++idx )
{
if ( idx && ( idx % inObjPerLine == 0 ) )
inTempBuffer << "\n\t\t\t";
else
inTempBuffer << " ";
inOperator( inTempBuffer, inAccessOperator( inObjType, idx ) );
}
writeProperty( inWriter, inTempBuffer, inPropName );
}
}
template<typename TDataType, typename TAccessOperator, typename TWriteOperator>
inline void writeStrideBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
, PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator inAccessOperator
, PxU32 inBufSize, const char* inPropName, PxU32 /*inStride*/, TWriteOperator inOperator )
{
#if PX_SWITCH
const auto *dat = &inData[0];
if (inBufSize && dat != NULL)
#else
if ( inBufSize && &inData[0])
#endif
{
for ( PxU32 idx = 0; idx < inBufSize; ++idx )
{
if ( idx && ( idx % inObjPerLine == 0 ) )
inTempBuffer << "\n\t\t\t";
else
inTempBuffer << " ";
inOperator( inTempBuffer, inAccessOperator( &inData[idx], 0 ) );
}
writeProperty( inWriter, inTempBuffer, inPropName );
}
}
template<typename TDataType, typename TAccessOperator>
inline void writeStrideFlags( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
, PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator /*inAccessOperator*/
, PxU32 inBufSize, const char* inPropName, const PxU32ToName* inTable)
{
#if PX_SWITCH
const auto *dat = &inData[0];
if (inBufSize && dat != NULL)
#else
if ( inBufSize && &inData[0])
#endif
{
for ( PxU32 idx = 0; idx < inBufSize; ++idx )
{
writeFlagsBuffer(inTempBuffer, inData[idx], inTable);
if ( idx && ( idx % inObjPerLine == 0 ) )
inTempBuffer << "\n\t\t\t";
else
inTempBuffer << " ";
}
writeProperty( inWriter, inTempBuffer, inPropName );
}
}
template<typename TDataType, typename TWriteOperator>
inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
, PxU32 inObjPerLine, const TDataType* inBuffer
, PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator )
{
writeBuffer( inWriter, inTempBuffer, inObjPerLine, inBuffer, PtrAccess<TDataType>, inBufSize, inPropName, inOperator );
}
template<typename TEnumType>
inline void writeEnumProperty( XmlWriter& inWriter, const char* inPropName, TEnumType inEnumValue, const PxU32ToName* inConversions )
{
PxU32 theValue = static_cast<PxU32>( inEnumValue );
for ( const PxU32ToName* conv = inConversions; conv->mName != NULL; ++conv )
if ( conv->mValue == theValue ) inWriter.write( inPropName, conv->mName );
}
template<typename TObjType, typename TWriterType, typename TInfoType>
inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const TInfoType& info);
template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType >
void handleComplexCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo )
{
PxU32 count( inProp.size( visitor.mObj ) );
if ( count )
{
PxInlineArray<TCollectionType*,5> theData;
theData.resize( count );
inProp.get( visitor.mObj, theData.begin(), count );
for( PxU32 idx =0; idx < count; ++idx )
{
visitor.pushName( childName );
handleComplexObj( visitor, theData[idx], inInfo );
visitor.popName();
}
}
}
template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType >
void handleBufferCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo )
{
PxU32 count( inProp.size( visitor.mObj ) );
if ( count )
{
PxInlineArray<TCollectionType*,5> theData;
theData.resize( count );
inProp.get( visitor.mObj, theData.begin());
for( PxU32 idx =0; idx < count; ++idx )
{
visitor.pushName( childName );
handleComplexObj( visitor, theData[idx], inInfo );
visitor.popName();
}
}
}
template<typename TVisitor>
void handleShapes( TVisitor& visitor, const PxRigidActorShapeCollection& inProp )
{
PxShapeGeneratedInfo theInfo;
PxU32 count( inProp.size( visitor.mObj ) );
if ( count )
{
PxInlineArray<PxShape*,5> theData;
theData.resize( count );
inProp.get( visitor.mObj, theData.begin(), count );
for( PxU32 idx = 0; idx < count; ++idx )
{
const PxShape* shape = theData[idx];
visitor.pushName( "PxShape" );
if( !shape->isExclusive() )
{
writeReference( visitor.mWriter, visitor.mCollection, "PxShapeRef", shape );
}
else
{
handleComplexObj( visitor, shape, theInfo );
}
visitor.popName();
}
}
}
template<typename TVisitor>
void handleShapeMaterials( TVisitor& visitor, const PxShapeMaterialsProperty& inProp )
{
PxU32 count( inProp.size( visitor.mObj ) );
if ( count )
{
PxInlineArray<PxMaterial*,5> theData;
theData.resize( count );
inProp.get( visitor.mObj, theData.begin(), count );
visitor.pushName( "PxMaterialRef" );
for( PxU32 idx =0; idx < count; ++idx )
writeReference( visitor.mWriter, visitor.mCollection, "PxMaterialRef", theData[idx] );
visitor.popName();
}
}
template<typename TObjType>
struct RepXVisitorWriterBase
{
TNameStack& mNameStack;
XmlWriter& mWriter;
const TObjType* mObj;
MemoryBuffer& mTempBuffer;
PxCollection& mCollection;
RepXVisitorWriterBase( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection )
: mNameStack( ns )
, mWriter( writer )
, mObj( obj )
, mTempBuffer( buf )
, mCollection( collection )
{
}
RepXVisitorWriterBase( const RepXVisitorWriterBase<TObjType>& other )
: mNameStack( other.mNameStack )
, mWriter( other.mWriter )
, mObj( other.mObj )
, mTempBuffer( other.mTempBuffer )
, mCollection( other.mCollection )
{
}
RepXVisitorWriterBase& operator=( const RepXVisitorWriterBase& ){ PX_ASSERT( false ); return *this; }
void gotoTopName()
{
if ( mNameStack.size() && mNameStack.back().mOpen == false )
{
mWriter.addAndGotoChild( mNameStack.back().mName );
mNameStack.back().mOpen = true;
}
}
void pushName( const char* inName )
{
gotoTopName();
mNameStack.pushBack( inName );
}
void pushBracketedName( const char* inName ) { pushName( inName ); }
void popName()
{
if ( mNameStack.size() )
{
if ( mNameStack.back().mOpen )
mWriter.leaveChild();
mNameStack.popBack();
}
}
const char* topName() const
{
if ( mNameStack.size() ) return mNameStack.back().mName;
PX_ASSERT( false );
return "bad__repx__name";
}
template<typename TAccessorType>
void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
{
typedef typename TAccessorType::prop_type TPropertyType;
TPropertyType propVal = inProp.get( mObj );
writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
}
template<typename TAccessorType>
void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions )
{
writeEnumProperty( mWriter, topName(), inProp.get( mObj ), inConversions );
}
template<typename TAccessorType>
void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions )
{
writeFlagsProperty( mWriter, mTempBuffer, topName(), inProp.get( mObj ), inConversions );
}
template<typename TAccessorType, typename TInfoType>
void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
TPropertyType propVal = inProp.get( mObj );
handleComplexObj( *this, &propVal, inInfo );
}
//
// The D6 joint has been changed such that it is necessary to specify what kind of angular drive model to apply.
// Depending on that choice, it is not legal anymore to set/get drive parameters for certain angular drive types.
// The serialization system, however, just blindly tries to get all drive parameters.
//
// Note: using partial template specialization because the compiler for aarch64 did not yet support in-class
// explicit specialization
//
typedef Vd::PxPvdIndexedPropertyAccessor<PxExtensionsPropertyInfoName::PxD6Joint_Drive, PxD6Joint, PxD6Drive::Enum, PxD6JointDrive> PxD6JointDriveAccessor;
template<typename TInfoType>
void complexProperty( PxU32* /*key*/, const PxD6JointDriveAccessor& inProp, TInfoType& inInfo )
{
if (isD6JointDriveAccessAllowed(inProp.mIndex, mObj->getAngularDriveConfig()))
{
typedef typename PxD6JointDriveAccessor::prop_type TPropertyType;
TPropertyType propVal = inProp.get( mObj );
handleComplexObj( *this, &propVal, inInfo );
}
}
template<typename TAccessorType, typename TInfoType>
void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
{
typedef typename TAccessorType::prop_type TPropertyType;
PxU32 count( inProp.size( mObj ) );
PxInlineArray<TPropertyType,5> theData;
theData.resize( count );
PxClassInfoTraits<TInfoType> theTraits;
PX_UNUSED(theTraits);
PxU32 numItems = inProp.get( mObj, theData.begin(), count );
PX_ASSERT( numItems == count );
for( PxU32 idx =0; idx < numItems; ++idx )
{
pushName( inProp.name() );
handleComplexObj( *this, &theData[idx], inInfo );
popName();
}
}
template<typename TAccessorType, typename TInfoType>
void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& /*inInfo */)
{
typedef typename TAccessorType::prop_type TPropertyType;
PxU32 count( inProp.size( mObj ) );
PxInlineArray<TPropertyType,5> theData;
theData.resize( count );
for(PxU32 i = 0; i < count; ++i)
{
char buffer[32] = { 0 };
sprintf( buffer, "id_%u", i );
pushName( buffer );
TPropertyType propVal = inProp.get( mObj, i );
TInfoType& infoType = PxClassInfoTraits<TPropertyType>().Info;
handleComplexObj(*this, &propVal, infoType);
popName();
}
}
template<typename TAccessorType, typename TInfoType>
void PxFixedSizeLookupTableProperty( PxU32* /*key*/, TAccessorType& inProp, TInfoType& /*inInfo */)
{
typedef typename TAccessorType::prop_type TPropertyType;
PxU32 count( inProp.size( mObj ) );
PxU32 index = 0;
for(PxU32 i = 0; i < count; ++i)
{
char buffer[32] = { 0 };
sprintf( buffer, "id_%u", index++ );
pushName( buffer );
TPropertyType propVal = inProp.getX( mObj , i);
writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
popName();
sprintf( buffer, "id_%u", index++ );
pushName( buffer );
propVal = inProp.getY( mObj , i);
writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
popName();
}
}
void handleShapes( const PxRigidActorShapeCollection& inProp )
{
physx::Sn::handleShapes( *this, inProp );
}
void handleShapeMaterials( const PxShapeMaterialsProperty& inProp )
{
physx::Sn::handleShapeMaterials( *this, inProp );
}
void handleRigidActorGlobalPose(const PxRigidActorGlobalPosePropertyInfo& inProp)
{
PxRepXPropertyAccessor<PxPropertyInfoName::PxRigidActor_GlobalPose, PxRigidActor, const PxTransform &, PxTransform> theAccessor(inProp);
simpleProperty(PxPropertyInfoName::PxRigidActor_GlobalPose, theAccessor);
}
};
template<typename TObjType>
struct RepXVisitorWriter : RepXVisitorWriterBase<TObjType>
{
RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection )
: RepXVisitorWriterBase<TObjType>( ns, writer, obj, buf, collection )
{
}
RepXVisitorWriter( const RepXVisitorWriter<TObjType>& other )
: RepXVisitorWriterBase<TObjType>( other )
{
}
};
template<>
struct RepXVisitorWriter<PxArticulationLink> : RepXVisitorWriterBase<PxArticulationLink>
{
RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxArticulationLink* obj, MemoryBuffer& buf, PxCollection& collection )
: RepXVisitorWriterBase<PxArticulationLink>( ns, writer, obj, buf, collection )
{
}
RepXVisitorWriter( const RepXVisitorWriter<PxArticulationLink>& other )
: RepXVisitorWriterBase<PxArticulationLink>( other )
{
}
void handleIncomingJoint( const TIncomingJointPropType& prop )
{
const PxArticulationJointReducedCoordinate* joint( prop.get( mObj ) );
if (joint)
{
pushName( "Joint" );
handleComplexObj( *this, joint, PxArticulationJointReducedCoordinateGeneratedInfo());
popName();
}
}
};
typedef PxProfileHashMap< const PxSerialObjectId, const PxArticulationLink* > TArticulationLinkLinkMap;
static void recurseAddLinkAndChildren( const PxArticulationLink* inLink, PxInlineArray<const PxArticulationLink*, 64>& ioLinks )
{
ioLinks.pushBack( inLink );
PxInlineArray<PxArticulationLink*, 8> theChildren;
PxU32 childCount( inLink->getNbChildren() );
theChildren.resize( childCount );
inLink->getChildren( theChildren.begin(), childCount );
for ( PxU32 idx = 0; idx < childCount; ++idx )
recurseAddLinkAndChildren( theChildren[idx], ioLinks );
}
template<>
struct RepXVisitorWriter<PxArticulationReducedCoordinate> : RepXVisitorWriterBase<PxArticulationReducedCoordinate>
{
TArticulationLinkLinkMap& mArticulationLinkParents;
RepXVisitorWriter(TNameStack& ns, XmlWriter& writer, const PxArticulationReducedCoordinate* inArticulation, MemoryBuffer& buf, PxCollection& collection, TArticulationLinkLinkMap* artMap = NULL)
: RepXVisitorWriterBase<PxArticulationReducedCoordinate>(ns, writer, inArticulation, buf, collection)
, mArticulationLinkParents(*artMap)
{
PxInlineArray<PxArticulationLink*, 64, PxProfileWrapperReflectionAllocator<PxArticulationLink*> > linkList(PxProfileWrapperReflectionAllocator<PxArticulationLink*>(buf.mManager->getWrapper()));
PxU32 numLinks = inArticulation->getNbLinks();
linkList.resize(numLinks);
inArticulation->getLinks(linkList.begin(), numLinks);
for (PxU32 idx = 0; idx < numLinks; ++idx)
{
const PxArticulationLink* theLink(linkList[idx]);
PxInlineArray<PxArticulationLink*, 64> theChildList;
PxU32 numChildren = theLink->getNbChildren();
theChildList.resize(numChildren);
theLink->getChildren(theChildList.begin(), numChildren);
for (PxU32 childIdx = 0; childIdx < numChildren; ++childIdx)
mArticulationLinkParents.insert(static_cast<uint64_t>(size_t(theChildList[childIdx])), theLink);
}
}
RepXVisitorWriter(const RepXVisitorWriter<PxArticulationReducedCoordinate>& other)
: RepXVisitorWriterBase<PxArticulationReducedCoordinate>(other)
, mArticulationLinkParents(other.mArticulationLinkParents)
{
}
template<typename TAccessorType, typename TInfoType>
void complexProperty(PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo)
{
typedef typename TAccessorType::prop_type TPropertyType;
TPropertyType propVal = inProp.get(mObj);
handleComplexObj(*this, &propVal, inInfo);
}
void writeArticulationLink(const PxArticulationLink* inLink)
{
pushName("PxArticulationLink");
gotoTopName();
const TArticulationLinkLinkMap::Entry* theParentPtr = mArticulationLinkParents.find(static_cast<uint64_t>(size_t(inLink)));
if (theParentPtr != NULL)
writeProperty(mWriter, mCollection, mTempBuffer, "Parent", theParentPtr->second);
writeProperty(mWriter, mCollection, mTempBuffer, "Id", inLink);
PxArticulationLinkGeneratedInfo info;
handleComplexObj(*this, inLink, info);
popName();
}
void handleArticulationLinks(const PxArticulationLinkCollectionProp& inProp)
{
//topologically sort the links as per my discussion with Dilip because
//links aren't guaranteed to have the parents before the children in the
//overall link list and it is unlikely to be done by beta 1.
PxU32 count(inProp.size(mObj));
if (count)
{
PxInlineArray<PxArticulationLink*, 64> theLinks;
theLinks.resize(count);
inProp.get(mObj, theLinks.begin(), count);
PxInlineArray<const PxArticulationLink*, 64> theSortedLinks;
for (PxU32 idx = 0; idx < count; ++idx)
{
const PxArticulationLink* theLink(theLinks[idx]);
if (mArticulationLinkParents.find(static_cast<uint64_t>(size_t(theLink))) == NULL)
recurseAddLinkAndChildren(theLink, theSortedLinks);
}
PX_ASSERT(theSortedLinks.size() == count);
for (PxU32 idx = 0; idx < count; ++idx)
writeArticulationLink(theSortedLinks[idx]);
popName();
}
}
private:
RepXVisitorWriter<PxArticulationReducedCoordinate>& operator=(const RepXVisitorWriter<PxArticulationReducedCoordinate>&);
};
template<>
struct RepXVisitorWriter<PxShape> : RepXVisitorWriterBase<PxShape>
{
RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxShape* obj, MemoryBuffer& buf, PxCollection& collection )
: RepXVisitorWriterBase<PxShape>( ns, writer, obj, buf, collection )
{
}
RepXVisitorWriter( const RepXVisitorWriter<PxShape>& other )
: RepXVisitorWriterBase<PxShape>( other )
{
}
template<typename GeometryType>
inline void writeGeomProperty( const PxShapeGeomProperty& inProp, const char* inTypeName )
{
pushName( "Geometry" );
pushName( inTypeName );
GeometryType theType;
inProp.getGeometry( mObj, theType );
PxClassInfoTraits<GeometryType> theTraits;
PxU32 count = theTraits.Info.totalPropertyCount();
if(count)
{
handleComplexObj( *this, &theType, theTraits.Info);
}
else
{
writeProperty(mWriter, mTempBuffer, inTypeName);
}
popName();
popName();
}
void handleGeomProperty( const PxShapeGeomProperty& inProp )
{
switch( mObj->getGeometry().getType() )
{
case PxGeometryType::eSPHERE: writeGeomProperty<PxSphereGeometry>( inProp, "PxSphereGeometry" ); break;
case PxGeometryType::ePLANE: writeGeomProperty<PxPlaneGeometry>( inProp, "PxPlaneGeometry" ); break;
case PxGeometryType::eCAPSULE: writeGeomProperty<PxCapsuleGeometry>( inProp, "PxCapsuleGeometry" ); break;
case PxGeometryType::eBOX: writeGeomProperty<PxBoxGeometry>( inProp, "PxBoxGeometry" ); break;
case PxGeometryType::eCONVEXMESH: writeGeomProperty<PxConvexMeshGeometry>( inProp, "PxConvexMeshGeometry" ); break;
case PxGeometryType::eTRIANGLEMESH: writeGeomProperty<PxTriangleMeshGeometry>( inProp, "PxTriangleMeshGeometry" ); break;
case PxGeometryType::eHEIGHTFIELD: writeGeomProperty<PxHeightFieldGeometry>( inProp, "PxHeightFieldGeometry" ); break;
case PxGeometryType::eTETRAHEDRONMESH: writeGeomProperty<PxTetrahedronMeshGeometry>( inProp, "PxTetrahedronMeshGeometry" ); break;
default:
PX_ASSERT( false );
}
}
};
template<typename TObjType>
inline void writeAllProperties( TNameStack& inNameStack, const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
{
RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection );
RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor );
PxClassInfoTraits<TObjType> info;
info.Info.visitBaseProperties( theOp );
info.Info.visitInstanceProperties( theOp );
}
template<typename TObjType>
inline void writeAllProperties( TNameStack& inNameStack, TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
{
RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection );
RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor );
PxClassInfoTraits<TObjType> info;
info.Info.visitBaseProperties( theOp );
info.Info.visitInstanceProperties( theOp );
}
template<typename TObjType>
inline void writeAllProperties( const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
{
TNameStack theNames( buffer.mManager->getWrapper() );
writeAllProperties( theNames, inObj, writer, buffer, collection );
}
template<typename TObjType, typename TWriterType, typename TInfoType>
inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const TInfoType& /*info*/)
{
writeAllProperties( oldVisitor.mNameStack, inObj, oldVisitor.mWriter, oldVisitor.mTempBuffer, oldVisitor.mCollection );
}
template<typename TObjType, typename TWriterType>
inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const PxUnknownClassInfo& /*info*/)
{
writeProperty( oldVisitor.mWriter, oldVisitor.mCollection, oldVisitor.mTempBuffer, oldVisitor.topName(), *inObj );
}
} }
#endif

View File

@@ -0,0 +1,57 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SN_XML_WRITER_H
#define SN_XML_WRITER_H
#include "foundation/PxSimpleTypes.h"
namespace physx {
struct PxRepXObject;
/**
* Writer used by extensions to write elements to a file or database
*/
class PX_DEPRECATED XmlWriter
{
protected:
virtual ~XmlWriter(){}
public:
/** Write a key-value pair into the current item */
virtual void write( const char* inName, const char* inData ) = 0;
/** Write an object id into the current item */
virtual void write( const char* inName, const PxRepXObject& inLiveObject ) = 0;
/** Add a child that then becomes the current context */
virtual void addAndGotoChild( const char* inName ) = 0;
/** Leave the current child */
virtual void leaveChild() = 0;
};
}
#endif