aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp')
-rw-r--r--PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp493
1 files changed, 493 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp b/PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp
new file mode 100644
index 00000000..e793b48f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXCooking/src/Cooking.cpp
@@ -0,0 +1,493 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 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/PxErrorCallback.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+#include "PsFPU.h"
+#include "CmPhysXCommon.h"
+#include "PxPhysXConfig.h"
+#include "PxSimpleTriangleMesh.h"
+#include "PxTriangleMeshDesc.h"
+#include "PxConvexMeshDesc.h"
+#include "PxCooking.h"
+#include "Cooking.h"
+#include "mesh/TriangleMeshBuilder.h"
+#include "GuConvexMesh.h"
+#include "ConvexMeshBuilder.h"
+#include "InflationConvexHullLib.h"
+#include "QuickHullConvexHullLib.h"
+#include "CmIO.h"
+#include "PxHeightFieldDesc.h"
+#include "GuHeightField.h"
+#include "HeightFieldCooking.h"
+#include "common/PxPhysicsInsertionCallback.h"
+#include "CmUtils.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+using namespace physx;
+using namespace Gu;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Cooking::setParams(const PxCookingParams& params)
+{
+ mParams = params;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const PxCookingParams& Cooking::getParams()
+{
+ return mParams;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool Cooking::platformMismatch()
+{
+ // Get current endianness (the one for the platform where cooking is performed)
+ PxI8 currentEndian = Ps::littleEndian();
+
+ bool mismatch = true;
+ switch(mParams.targetPlatform)
+ {
+ case PxPlatform::ePC:
+ mismatch = currentEndian!=1; // The PC files must be little endian
+ break;
+ case PxPlatform::eARM:
+ mismatch = currentEndian!=1;
+ break;
+ }
+ return mismatch;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Cooking::release()
+{
+ delete this;
+
+ Ps::Foundation::decRefCount();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Cooking::validateTriangleMesh(const PxTriangleMeshDesc& desc)
+{
+ // cooking code does lots of float bitwise reinterpretation that generates exceptions
+ PX_FPU_GUARD;
+
+ if(!desc.isValid())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Cooking::validateTriangleMesh: user-provided triangle mesh descriptor is invalid!");
+ return false;
+ }
+
+ // PT: validation code doesn't look at midphase data, so ideally we wouldn't build the midphase structure at all here.
+ BV4TriangleMeshBuilder builder(mParams);
+ return builder.loadFromDesc(desc, NULL, true /*doValidate*/);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool Cooking::cookTriangleMesh(TriangleMeshBuilder& builder, const PxTriangleMeshDesc& desc, PxOutputStream& stream, PxTriangleMeshCookingResult::Enum* condition)
+{
+ // cooking code does lots of float bitwise reinterpretation that generates exceptions
+ PX_FPU_GUARD;
+
+ if (condition)
+ *condition = PxTriangleMeshCookingResult::eSUCCESS;
+ if(!builder.loadFromDesc(desc, condition, false))
+ {
+ if (condition)
+ *condition = PxTriangleMeshCookingResult::eFAILURE;
+ return false;
+ }
+
+ builder.save(stream, platformMismatch(), mParams);
+ return true;
+}
+
+bool Cooking::cookTriangleMesh(const PxTriangleMeshDesc& desc, PxOutputStream& stream, PxTriangleMeshCookingResult::Enum* condition)
+{
+ if((mParams.midphaseDesc.getType() == PxMeshMidPhase::eINVALID) || (mParams.midphaseDesc.getType() == PxMeshMidPhase::eBVH33))
+ {
+ RTreeTriangleMeshBuilder builder(mParams);
+ return cookTriangleMesh(builder, desc, stream, condition);
+ }
+ else
+ {
+ BV4TriangleMeshBuilder builder(mParams);
+ return cookTriangleMesh(builder, desc, stream, condition);
+ }
+}
+
+PxTriangleMesh* Cooking::createTriangleMesh(TriangleMeshBuilder& builder, const PxTriangleMeshDesc& desc, PxPhysicsInsertionCallback& insertionCallback)
+{
+ // cooking code does lots of float bitwise reinterpretation that generates exceptions
+ PX_FPU_GUARD;
+
+ if(!builder.loadFromDesc(desc, NULL, false))
+ return NULL;
+
+ // check if the indices can be moved from 32bits to 16bits
+ if(!(mParams.meshPreprocessParams & PxMeshPreprocessingFlag::eFORCE_32BIT_INDICES))
+ builder.checkMeshIndicesSize();
+
+ PxConcreteType::Enum type;
+ if(builder.getMidphaseID()==PxMeshMidPhase::eBVH33)
+ type = PxConcreteType::eTRIANGLE_MESH_BVH33;
+ else
+ type = PxConcreteType::eTRIANGLE_MESH_BVH34;
+
+ return static_cast<PxTriangleMesh*>(insertionCallback.buildObjectFromData(type, &builder.getMeshData()));
+}
+
+PxTriangleMesh* Cooking::createTriangleMesh(const PxTriangleMeshDesc& desc, PxPhysicsInsertionCallback& insertionCallback)
+{
+ if((mParams.midphaseDesc.getType() == PxMeshMidPhase::eINVALID) || (mParams.midphaseDesc.getType() == PxMeshMidPhase::eBVH33))
+ {
+ RTreeTriangleMeshBuilder builder(mParams);
+ return createTriangleMesh(builder, desc, insertionCallback);
+ }
+ else
+ {
+ BV4TriangleMeshBuilder builder(mParams);
+ return createTriangleMesh(builder, desc, insertionCallback);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cook convex mesh from given desc, internal function to be shared between create/cook convex mesh
+bool Cooking::cookConvexMeshInternal(const PxConvexMeshDesc& desc_, ConvexMeshBuilder& meshBuilder, ConvexHullLib* hullLib,
+ PxConvexMeshCookingResult::Enum* condition)
+{
+ if (condition)
+ *condition = PxConvexMeshCookingResult::eFAILURE;
+
+ if (!desc_.isValid())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Cooking::cookConvexMesh: user-provided convex mesh descriptor is invalid!");
+ return false;
+ }
+
+ if (mParams.areaTestEpsilon <= 0.0f)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Cooking::cookConvexMesh: user-provided convex mesh areaTestEpsilon is invalid!");
+ return false;
+ }
+
+ PxConvexMeshDesc desc = desc_;
+ bool polygonsLimitReached = false;
+
+ // the convex will be cooked from provided points
+ if (desc_.flags & PxConvexFlag::eCOMPUTE_CONVEX)
+ {
+ PX_ASSERT(hullLib);
+
+ PxConvexMeshCookingResult::Enum res = hullLib->createConvexHull();
+ if (res == PxConvexMeshCookingResult::eSUCCESS || res == PxConvexMeshCookingResult::ePOLYGONS_LIMIT_REACHED)
+ {
+ if (res == PxConvexMeshCookingResult::ePOLYGONS_LIMIT_REACHED)
+ polygonsLimitReached = true;
+
+ hullLib->fillConvexMeshDesc(desc);
+ }
+ else
+ {
+ if (res == PxConvexMeshCookingResult::eZERO_AREA_TEST_FAILED)
+ {
+ *condition = PxConvexMeshCookingResult::eZERO_AREA_TEST_FAILED;
+ }
+
+ return false;
+ }
+ }
+
+ if (desc.points.count >= 256)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Cooking::cookConvexMesh: user-provided hull must have less than 256 vertices!");
+ return false;
+ }
+
+ if (!meshBuilder.build(desc, mParams.gaussMapLimit, false, hullLib ? false : true))
+ {
+ return false;
+ }
+
+ if (condition)
+ {
+ *condition = polygonsLimitReached ? PxConvexMeshCookingResult::ePOLYGONS_LIMIT_REACHED : PxConvexMeshCookingResult::eSUCCESS;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// cook convex mesh from given desc, save the results into stream
+bool Cooking::cookConvexMesh(const PxConvexMeshDesc& desc_, PxOutputStream& stream, PxConvexMeshCookingResult::Enum* condition)
+{
+ PX_FPU_GUARD;
+ // choose cooking library if needed
+ ConvexHullLib* hullLib = NULL;
+ PxConvexMeshDesc desc = desc_;
+
+ if(desc_.flags & PxConvexFlag::eCOMPUTE_CONVEX)
+ {
+ const PxU32 gpuMaxVertsLimit = 64;
+
+ // GRB supports 64 verts max
+ if(desc_.flags & PxConvexFlag::eGPU_COMPATIBLE)
+ {
+ desc.vertexLimit = gpuMaxVertsLimit;
+ }
+
+ if(mParams.convexMeshCookingType == PxConvexMeshCookingType::eINFLATION_INCREMENTAL_HULL)
+ {
+ hullLib = PX_NEW(InflationConvexHullLib) (desc, mParams);
+ }
+ else
+ {
+ hullLib = PX_NEW(QuickHullConvexHullLib) (desc, mParams);
+ }
+ }
+
+ ConvexMeshBuilder meshBuilder(mParams.buildGPUData);
+ if(!cookConvexMeshInternal(desc,meshBuilder,hullLib , condition))
+ {
+ if(hullLib)
+ PX_DELETE(hullLib);
+ return false;
+ }
+
+ // save the cooked results into stream
+ if(!meshBuilder.save(stream, platformMismatch()))
+ {
+ if (condition)
+ {
+ *condition = PxConvexMeshCookingResult::eFAILURE;
+ }
+ if(hullLib)
+ PX_DELETE(hullLib);
+ return false;
+ }
+
+ if(hullLib)
+ PX_DELETE(hullLib);
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// cook convex mesh from given desc, copy the results into internal convex mesh
+// and insert the mesh into PxPhysics
+PxConvexMesh* Cooking::createConvexMesh(const PxConvexMeshDesc& desc, PxPhysicsInsertionCallback& insertionCallback)
+{
+ PX_FPU_GUARD;
+ // choose cooking library if needed
+ ConvexHullLib* hullLib = NULL;
+ if(desc.flags & PxConvexFlag::eCOMPUTE_CONVEX)
+ {
+ if (mParams.convexMeshCookingType == PxConvexMeshCookingType::eINFLATION_INCREMENTAL_HULL)
+ {
+ hullLib = PX_NEW(InflationConvexHullLib) (desc, mParams);
+ }
+ else
+ {
+ hullLib = PX_NEW(QuickHullConvexHullLib) (desc, mParams);
+ }
+ }
+
+ // cook the mesh
+ ConvexMeshBuilder meshBuilder(mParams.buildGPUData);
+ if (!cookConvexMeshInternal(desc, meshBuilder, hullLib, NULL))
+ {
+ if(hullLib)
+ PX_DELETE(hullLib);
+ return NULL;
+ }
+
+ // copy the constructed data into the new mesh
+ Gu::ConvexHullData meshData;
+ meshBuilder.copy(meshData);
+
+ // insert into physics
+ Gu::ConvexMesh* convexMesh = static_cast<Gu::ConvexMesh*>(insertionCallback.buildObjectFromData(PxConcreteType::eCONVEX_MESH, &meshData));
+ if (!convexMesh)
+ {
+ if (hullLib)
+ PX_DELETE(hullLib);
+ return NULL;
+ }
+
+ convexMesh->setMass(meshBuilder.getMass());
+ convexMesh->setInertia(meshBuilder.getInertia());
+ if(meshBuilder.getBigConvexData())
+ {
+ convexMesh->setBigConvexData(meshBuilder.getBigConvexData());
+ meshBuilder.setBigConvexData(NULL);
+ }
+
+ if(hullLib)
+ PX_DELETE(hullLib);
+ return convexMesh;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+bool Cooking::validateConvexMesh(const PxConvexMeshDesc& desc)
+{
+ ConvexMeshBuilder mesh(mParams.buildGPUData);
+ return mesh.build(desc, mParams.gaussMapLimit, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool Cooking::computeHullPolygons(const PxSimpleTriangleMesh& mesh, PxAllocatorCallback& inCallback,PxU32& nbVerts, PxVec3*& vertices,
+ PxU32& nbIndices, PxU32*& indices, PxU32& nbPolygons, PxHullPolygon*& hullPolygons)
+{
+ PxVec3* geometry = reinterpret_cast<PxVec3*>(PxAlloca(sizeof(PxVec3)*mesh.points.count));
+ Cooking::gatherStrided(mesh.points.data, geometry, mesh.points.count, sizeof(PxVec3), mesh.points.stride);
+
+ PxU32* topology = reinterpret_cast<PxU32*>(PxAlloca(sizeof(PxU32)*3*mesh.triangles.count));
+ if (mesh.flags & PxMeshFlag::e16_BIT_INDICES)
+ {
+ // conversion; 16 bit index -> 32 bit index & stride
+ PxU32* dest = topology;
+ const PxU32* pastLastDest = topology + 3*mesh.triangles.count;
+ const PxU8* source = reinterpret_cast<const PxU8*>(mesh.triangles.data);
+ while (dest < pastLastDest)
+ {
+ const PxU16 * trig16 = reinterpret_cast<const PxU16*>(source);
+ *dest++ = trig16[0];
+ *dest++ = trig16[1];
+ *dest++ = trig16[2];
+ source += mesh.triangles.stride;
+ }
+ }
+ else
+ {
+ Cooking::gatherStrided(mesh.triangles.data, topology, mesh.triangles.count, sizeof(PxU32) * 3, mesh.triangles.stride);
+ }
+
+ ConvexMeshBuilder meshBuilder(mParams.buildGPUData);
+ if(!meshBuilder.computeHullPolygons(mesh.points.count,geometry,mesh.triangles.count,topology,inCallback, nbVerts, vertices,nbIndices,indices,nbPolygons,hullPolygons))
+ return false;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool Cooking::cookHeightField(const PxHeightFieldDesc& desc, PxOutputStream& stream)
+{
+ PX_FPU_GUARD;
+
+ if(!desc.isValid())
+ {
+ #if PX_CHECKED
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Cooking::createHeightField: user-provided heightfield descriptor is invalid!");
+ #endif
+ return false;
+ }
+
+ Gu::HeightField hf(NULL);
+
+ if(!hf.loadFromDesc(desc))
+ {
+ hf.releaseMemory();
+ return false;
+ }
+
+ if (!saveHeightField(hf, stream, platformMismatch()))
+ {
+ hf.releaseMemory();
+ return false;
+ }
+
+ hf.releaseMemory();
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PxHeightField* Cooking::createHeightField(const PxHeightFieldDesc& desc, PxPhysicsInsertionCallback& insertionCallback)
+{
+ PX_FPU_GUARD;
+
+ if(!desc.isValid())
+ {
+ #if PX_CHECKED
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Cooking::createHeightField: user-provided heightfield descriptor is invalid!");
+ #endif
+ return NULL;
+ }
+
+ Gu::HeightField* hf;
+ PX_NEW_SERIALIZED(hf, Gu::HeightField)(NULL);
+
+ if(!hf->loadFromDesc(desc))
+ {
+ PX_DELETE(hf);
+ return NULL;
+ }
+
+ // create heightfield and set the HF data
+ Gu::HeightField* heightField = static_cast<Gu::HeightField*>(insertionCallback.buildObjectFromData(PxConcreteType::eHEIGHTFIELD, &hf->mData));
+ if(!heightField)
+ {
+ PX_DELETE(hf);
+ return NULL;
+ }
+
+ // copy the Gu::HeightField variables
+ heightField->mSampleStride = hf->mSampleStride;
+ heightField->mNbSamples = hf->mNbSamples;
+ heightField->mMinHeight = hf->mMinHeight;
+ heightField->mMaxHeight = hf->mMaxHeight;
+ heightField->mModifyCount = hf->mModifyCount;
+
+ PX_DELETE(hf);
+ return heightField;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+PxCooking* PxCreateCooking(PxU32 /*version*/, PxFoundation& foundation, const PxCookingParams& params)
+{
+ PX_ASSERT(static_cast<Ps::Foundation*>(&foundation) == &Ps::Foundation::getInstance());
+ PX_UNUSED(foundation);
+
+ Ps::Foundation::incRefCount();
+
+ return PX_NEW(Cooking)(params);
+}
+