Init
This commit is contained in:
434
physx/snippets/snippetloadcollection/SnippetLoadCollection.cpp
Normal file
434
physx/snippets/snippetloadcollection/SnippetLoadCollection.cpp
Normal file
@ -0,0 +1,434 @@
|
||||
//
|
||||
// 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-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
// ****************************************************************************
|
||||
// This snippet illustrates loading xml or binary serialized collections and instantiating the objects in a scene.
|
||||
//
|
||||
// It only compiles and runs on authoring platforms (windows, osx and linux).
|
||||
// The snippet supports connecting to PVD in order to display the scene.
|
||||
//
|
||||
// It is a simple command-line tool supporting the following options::
|
||||
// SnippetLoadCollection [--pvdhost=<ip address> ] [--pvdport=<ip port> ] [--pvdtimeout=<time ms> ] [--generateExampleFiles] <filename>...
|
||||
//
|
||||
// --pvdhost=<ip address> Defines ip address of PVD, default is 127.0.0.1
|
||||
// --pvdport=<ip port> Defines ip port of PVD, default is 5425
|
||||
// --pvdtimeout=<time ms> Defines time out of PVD, default is 10
|
||||
// --generateExampleFiles Generates a set of example files
|
||||
// <filename>... Input files containing serialized collections (either xml or binary)
|
||||
//
|
||||
// Multiple collection files can be specified. The snippet is currently restricted to load a list of collections which obey
|
||||
// the following rule: The first collection needs to be complete. All following collections - if any - may only maintain
|
||||
// dependencies to objects in the first collection.
|
||||
//
|
||||
// The set of example files that can be generated consists of
|
||||
// collection.xml|collection.bin: Can be used individually.
|
||||
// collectionA.xml|collectionA.bin: Can also be used individually but only contain materials and shapes without actors.
|
||||
// collectionB.xml|collectionB.bin: Need to be used together with collectionA files. The actors contained in collectionB
|
||||
// maintain references to objects in the collectionA.
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
#include "PxPhysicsAPI.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../snippetcommon/SnippetPrint.h"
|
||||
#include "../snippetcommon/SnippetPVD.h"
|
||||
#include "../snippetutils/SnippetUtils.h"
|
||||
|
||||
#define MAX_INPUT_FILES 16
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxDefaultAllocator gAllocator;
|
||||
PxDefaultErrorCallback gErrorCallback;
|
||||
|
||||
PxFoundation* gFoundation = NULL;
|
||||
PxPhysics* gPhysics = NULL;
|
||||
PxCooking* gCooking = NULL;
|
||||
PxSerializationRegistry* gSerializationRegistry = NULL;
|
||||
|
||||
PxDefaultCpuDispatcher* gDispatcher = NULL;
|
||||
PxScene* gScene = NULL;
|
||||
|
||||
PxPvd* gPvd = NULL;
|
||||
|
||||
PxU8* gMemBlocks[MAX_INPUT_FILES];
|
||||
PxU32 gNbMemBlocks = 0;
|
||||
|
||||
struct CmdLineParameters
|
||||
{
|
||||
const char* pvdhost;
|
||||
PxU32 pvdport;
|
||||
PxU32 pvdtimeout;
|
||||
const char* inputFiles[MAX_INPUT_FILES];
|
||||
PxU32 nbFiles;
|
||||
bool generateExampleFiles;
|
||||
|
||||
CmdLineParameters() :
|
||||
pvdhost(PVD_HOST)
|
||||
, pvdport(5425)
|
||||
, pvdtimeout(10)
|
||||
, nbFiles(0)
|
||||
, generateExampleFiles(false)
|
||||
{}
|
||||
} gParameters;
|
||||
|
||||
static bool match(const char* opt, const char* ref)
|
||||
{
|
||||
std::string s1(opt);
|
||||
std::string s2(ref);
|
||||
return !s1.compare(0, s2.length(), s2);
|
||||
}
|
||||
|
||||
static void printHelpMsg()
|
||||
{
|
||||
printf("SnippetLoadCollection usage:\n"
|
||||
"SnippetLoadCollection "
|
||||
"[--pvdhost=<ip address> ] "
|
||||
"[--pvdport=<ip port> ]"
|
||||
"[--pvdtimeout=<time ms> ] "
|
||||
"[--generateExampleFiles]"
|
||||
"<filename>...\n\n"
|
||||
"Load binary or xml serialized collections and instatiate the objects in a PhysX scene.\n");
|
||||
|
||||
printf("--pvdhost=<ip address> \n");
|
||||
printf(" Defines ip address of PVD, default is 127.0.0.1 \n");
|
||||
|
||||
printf("--pvdport=<ip port> \n");
|
||||
printf(" Defines ip port of PVD, default is 5425\n");
|
||||
|
||||
printf("--pvdtimeout=<time ms> \n");
|
||||
printf(" Defines timeout of PVD, default is 10\n");
|
||||
|
||||
printf("--generateExampleFiles\n");
|
||||
printf(" Generates a set of example files\n");
|
||||
|
||||
printf("<filename>...\n");
|
||||
printf(" Input files (xml or binary), if a collection contains shared objects, it needs to be provided with the first file. \n\n");
|
||||
|
||||
}
|
||||
|
||||
static bool parseCommandLine(CmdLineParameters& result, int argc, const char *const*argv)
|
||||
{
|
||||
if( argc <= 1 )
|
||||
{
|
||||
printHelpMsg();
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; ++i)
|
||||
{
|
||||
if(argv[i][0] != '-' || argv[i][1] != '-')
|
||||
{
|
||||
if (result.nbFiles < MAX_INPUT_FILES)
|
||||
{
|
||||
result.inputFiles[result.nbFiles++] = argv[i];
|
||||
}
|
||||
else
|
||||
printf( "[WARNING] more input files are specified than supported (maximum %d). Ignoring the file %s\n", MAX_INPUT_FILES, argv[i] );
|
||||
}
|
||||
else if(match(argv[i], "--pvdhost="))
|
||||
{
|
||||
const char* hostStr = argv[i] + strlen("--pvdhost=");
|
||||
if(hostStr)
|
||||
result.pvdhost = hostStr;
|
||||
}
|
||||
else if(match(argv[i], "--pvdport="))
|
||||
{
|
||||
const char* portStr = argv[i] + strlen("--pvdport=");
|
||||
if (portStr)
|
||||
result.pvdport = PxU32(atoi(portStr));
|
||||
}
|
||||
else if(match(argv[i], "--pvdtimeout="))
|
||||
{
|
||||
const char* timeoutStr = argv[i] + strlen("--pvdtimeout=");
|
||||
if (timeoutStr)
|
||||
result.pvdtimeout = PxU32(atoi(timeoutStr));
|
||||
}
|
||||
else if(match(argv[i], "--generateExampleFiles"))
|
||||
{
|
||||
result.generateExampleFiles = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "[ERROR] Unknown command line parameter \"%s\"\n", argv[i] );
|
||||
printHelpMsg();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(result.nbFiles == 0 && !result.generateExampleFiles)
|
||||
{
|
||||
printf( "[ERROR] parameter missing.\n" );
|
||||
printHelpMsg();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool checkFile(bool& isBinary, const char* filename)
|
||||
{
|
||||
PxDefaultFileInputData fileStream(filename);
|
||||
if (fileStream.getLength() == 0)
|
||||
{
|
||||
printf( "[ERROR] input file %s can't be opened!\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
char testString[17];
|
||||
fileStream.read(testString, 16);
|
||||
testString[16] = 0;
|
||||
|
||||
if (strcmp("SEBD", testString) == 0)
|
||||
{
|
||||
isBinary = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp("<PhysXCollection", testString) == 0)
|
||||
{
|
||||
isBinary = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
printf( "[ERROR] input file %s seems neither an xml nor a binary serialized collection file!\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
static PxCollection* deserializeCollection(PxInputData& inputData, bool isBinary, PxCollection* sharedCollection, PxSerializationRegistry& sr)
|
||||
{
|
||||
PxCollection* collection = NULL;
|
||||
if(isBinary)
|
||||
{
|
||||
PxU32 length = inputData.getLength();
|
||||
PxU8* memBlock = static_cast<PxU8*>(malloc(length+PX_SERIAL_FILE_ALIGN-1));
|
||||
gMemBlocks[gNbMemBlocks++] = memBlock;
|
||||
void* alignedBlock = reinterpret_cast<void*>((size_t(memBlock)+PX_SERIAL_FILE_ALIGN-1)&~(PX_SERIAL_FILE_ALIGN-1));
|
||||
inputData.read(alignedBlock, length);
|
||||
collection = PxSerialization::createCollectionFromBinary(alignedBlock, sr, sharedCollection);
|
||||
}
|
||||
else
|
||||
{
|
||||
collection = PxSerialization::createCollectionFromXml(inputData, *gCooking, sr, sharedCollection);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
void initPhysics()
|
||||
{
|
||||
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
|
||||
|
||||
gPvd = PxCreatePvd(*gFoundation);
|
||||
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
|
||||
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
|
||||
|
||||
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
|
||||
PxInitExtensions(*gPhysics, gPvd);
|
||||
|
||||
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
|
||||
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
|
||||
gDispatcher = PxDefaultCpuDispatcherCreate(1);
|
||||
sceneDesc.cpuDispatcher = gDispatcher;
|
||||
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
|
||||
gScene = gPhysics->createScene(sceneDesc);
|
||||
|
||||
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
|
||||
if(pvdClient)
|
||||
{
|
||||
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
|
||||
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
|
||||
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
|
||||
}
|
||||
|
||||
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
|
||||
|
||||
gSerializationRegistry = PxSerialization::createSerializationRegistry(*gPhysics);
|
||||
|
||||
}
|
||||
|
||||
void cleanupPhysics()
|
||||
{
|
||||
PX_RELEASE(gSerializationRegistry);
|
||||
PX_RELEASE(gScene);
|
||||
PX_RELEASE(gDispatcher);
|
||||
PxCloseExtensions();
|
||||
|
||||
PX_RELEASE(gPhysics); // releases of all objects
|
||||
PX_RELEASE(gCooking);
|
||||
|
||||
for(PxU32 i=0; i<gNbMemBlocks; i++)
|
||||
free(gMemBlocks[i]); // now that the objects have been released, it's safe to release the space they occupy
|
||||
|
||||
if(gPvd)
|
||||
{
|
||||
PxPvdTransport* transport = gPvd->getTransport();
|
||||
gPvd->release(); gPvd = NULL;
|
||||
PX_RELEASE(transport);
|
||||
}
|
||||
|
||||
PX_RELEASE(gFoundation);
|
||||
|
||||
printf("SnippetLoadCollection done.\n");
|
||||
}
|
||||
|
||||
static void serializeCollection(PxCollection& collection, PxCollection* externalRefs, const char* filename, bool toBinary)
|
||||
{
|
||||
PxDefaultFileOutputStream outputStream(filename);
|
||||
if (!outputStream.isValid())
|
||||
{
|
||||
printf( "[ERROR] Could not open file %s!\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
bool bret;
|
||||
if (toBinary)
|
||||
{
|
||||
bret = PxSerialization::serializeCollectionToBinary(outputStream, collection, *gSerializationRegistry, externalRefs);
|
||||
}
|
||||
else
|
||||
{
|
||||
bret = PxSerialization::serializeCollectionToXml(outputStream, collection, *gSerializationRegistry, NULL, externalRefs);
|
||||
}
|
||||
|
||||
if(bret)
|
||||
printf( "Generated: \"%s\"\n", filename);
|
||||
else
|
||||
printf( "[ERROR] Failure when generating %s!\n", filename);
|
||||
}
|
||||
|
||||
static void generateExampleFiles()
|
||||
{
|
||||
PxCollection* collection = PxCreateCollection();
|
||||
PxCollection* collectionA = PxCreateCollection();
|
||||
PxCollection* collectionB = PxCreateCollection();
|
||||
PX_ASSERT( (collection != NULL) && (collectionA != NULL) && (collectionB != NULL) );
|
||||
|
||||
PxMaterial *material = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
|
||||
PX_ASSERT( material );
|
||||
PxShape* planeShape = gPhysics->createShape(PxPlaneGeometry(), *material);
|
||||
PxShape* boxShape = gPhysics->createShape(PxBoxGeometry(2.f, 2.f, 2.f), *material);
|
||||
PxRigidStatic* rigidStatic = PxCreateStatic(*gPhysics, PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxHalfPi, PxVec3(0.f, 0.f, 1.f))), *planeShape);
|
||||
PxRigidDynamic* rigidDynamic = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(0.f, 2.f, 0.f)), *boxShape, 1.f);
|
||||
|
||||
collection->add(*material);
|
||||
collection->add(*planeShape);
|
||||
collection->add(*boxShape);
|
||||
collection->add(*rigidStatic);
|
||||
collection->add(*rigidDynamic);
|
||||
PxSerialization::complete(*collection, *gSerializationRegistry);
|
||||
PX_ASSERT(PxSerialization::isSerializable(*collection, *gSerializationRegistry));
|
||||
|
||||
collectionA->add(*material);
|
||||
collectionA->add(*planeShape);
|
||||
collectionA->add(*boxShape);
|
||||
PxSerialization::complete(*collectionA, *gSerializationRegistry);
|
||||
PxSerialization::createSerialObjectIds(*collectionA, PxSerialObjectId(1));
|
||||
PX_ASSERT(PxSerialization::isSerializable(*collectionA, *gSerializationRegistry));
|
||||
|
||||
collectionB->add(*rigidStatic);
|
||||
collectionB->add(*rigidDynamic);
|
||||
PxSerialization::complete(*collectionB, *gSerializationRegistry, collectionA);
|
||||
PX_ASSERT(PxSerialization::isSerializable(*collectionB, *gSerializationRegistry, collectionA));
|
||||
|
||||
serializeCollection(*collection, NULL, "collection.xml", false);
|
||||
serializeCollection(*collectionA, NULL, "collectionA.xml", false);
|
||||
serializeCollection(*collectionB, collectionA, "collectionB.xml", false);
|
||||
serializeCollection(*collection, NULL, "collection.bin", true);
|
||||
serializeCollection(*collectionA, NULL, "collectionA.bin", true);
|
||||
serializeCollection(*collectionB, collectionA, "collectionB.bin", true);
|
||||
|
||||
collection->release();
|
||||
collectionA->release();
|
||||
collectionB->release();
|
||||
}
|
||||
|
||||
int snippetMain(int argc, const char *const* argv)
|
||||
{
|
||||
if(!parseCommandLine(gParameters, argc, argv))
|
||||
return 1;
|
||||
|
||||
initPhysics();
|
||||
|
||||
if(gParameters.generateExampleFiles)
|
||||
generateExampleFiles();
|
||||
|
||||
// collection that may have shared objects
|
||||
PxCollection* firstCollection = NULL;
|
||||
|
||||
for(PxU32 i=0; i<gParameters.nbFiles; i++)
|
||||
{
|
||||
const char* filename = gParameters.inputFiles[i];
|
||||
|
||||
bool isBinary;
|
||||
bool validFile = checkFile(isBinary, filename);
|
||||
|
||||
if (!validFile)
|
||||
break;
|
||||
|
||||
PxDefaultFileInputData inputStream(filename);
|
||||
PxCollection* collection = deserializeCollection(inputStream, isBinary, firstCollection, *gSerializationRegistry);
|
||||
if (!collection)
|
||||
{
|
||||
printf( "[ERROR] deserialization failure! filename: %s\n", filename);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Loaded: \"%s\"\n", filename);
|
||||
}
|
||||
|
||||
gScene->addCollection(*collection);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
firstCollection = collection;
|
||||
}
|
||||
else
|
||||
{
|
||||
collection->release();
|
||||
}
|
||||
}
|
||||
|
||||
if (firstCollection)
|
||||
firstCollection->release();
|
||||
|
||||
for (unsigned i = 0; i < 20; i++)
|
||||
{
|
||||
gScene->simulate(1.0f/60.0f);
|
||||
gScene->fetchResults(true);
|
||||
}
|
||||
|
||||
cleanupPhysics();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user