aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp456
1 files changed, 456 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp b/PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp
new file mode 100644
index 00000000..53d67504
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/convex/GuConvexMesh.cpp
@@ -0,0 +1,456 @@
+// 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 "PxVisualizationParameter.h"
+#include "PsIntrinsics.h"
+#include "CmPhysXCommon.h"
+#include "CmRenderOutput.h"
+#include "PsMathUtils.h"
+#include "GuConvexMesh.h"
+#include "GuTriangle32.h"
+#include "GuBigConvexData2.h"
+#include "GuSerialize.h"
+#include "GuMeshFactory.h"
+#include "CmUtils.h"
+#include "PxMeshScale.h"
+#include "PsAllocator.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+using namespace Gu;
+
+// PX_SERIALIZATION
+#include "PsIntrinsics.h"
+//~PX_SERIALIZATION
+
+bool Gu::ConvexMesh::getPolygonData(PxU32 i, PxHullPolygon& data) const
+{
+ if(i>=mHullData.mNbPolygons)
+ return false;
+
+ const HullPolygonData& poly = mHullData.mPolygons[i];
+ data.mPlane[0] = poly.mPlane.n.x;
+ data.mPlane[1] = poly.mPlane.n.y;
+ data.mPlane[2] = poly.mPlane.n.z;
+ data.mPlane[3] = poly.mPlane.d;
+ data.mNbVerts = poly.mNbVerts;
+ data.mIndexBase = poly.mVRef8;
+ return true;
+}
+
+/// ======================================
+
+static void initConvexHullData(Gu::ConvexHullData& data)
+{
+ data.mAABB.setEmpty();
+ data.mCenterOfMass = PxVec3(0);
+ data.mNbEdges = PxBitAndWord();
+ data.mNbHullVertices = 0;
+ data.mNbPolygons = 0;
+ data.mPolygons = NULL;
+ data.mBigConvexRawData = NULL;
+ data.mInternal.mRadius = 0.0f;
+ data.mInternal.mExtents[0] = data.mInternal.mExtents[1] = data.mInternal.mExtents[2] = 0.0f;
+}
+
+Gu::ConvexMesh::ConvexMesh()
+: PxConvexMesh(PxConcreteType::eCONVEX_MESH, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mNb (0)
+, mBigConvexData (NULL)
+, mMass (0)
+, mInertia (PxMat33(PxIdentity))
+{
+ initConvexHullData(mHullData);
+}
+
+Gu::ConvexMesh::ConvexMesh(GuMeshFactory& factory, ConvexHullData& data)
+: PxConvexMesh(PxConcreteType::eCONVEX_MESH, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mNb(0)
+, mBigConvexData(NULL)
+, mMass(0)
+, mInertia(PxMat33(PxIdentity))
+, mMeshFactory(&factory)
+{
+ mHullData = data;
+}
+
+Gu::ConvexMesh::~ConvexMesh()
+{
+// PX_SERIALIZATION
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+//~PX_SERIALIZATION
+ {
+ PX_DELETE_POD(mHullData.mPolygons);
+ PX_DELETE_AND_RESET(mBigConvexData);
+ }
+}
+
+bool Gu::ConvexMesh::isGpuCompatible() const
+{
+ return mHullData.mNbHullVertices <= 64 &&
+ mHullData.mPolygons[0].mNbVerts < 32 &&
+ mHullData.mNbEdges.isBitSet();
+}
+
+// PX_SERIALIZATION
+void Gu::ConvexMesh::exportExtraData(PxSerializationContext& stream)
+{
+ stream.alignData(PX_SERIAL_ALIGN);
+ const PxU32 bufferSize = computeBufferSize(mHullData, getNb());
+ stream.writeData(mHullData.mPolygons, bufferSize);
+
+ if(mBigConvexData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mBigConvexData, sizeof(BigConvexData));
+
+ mBigConvexData->exportExtraData(stream);
+ }
+}
+
+void Gu::ConvexMesh::importExtraData(PxDeserializationContext& context)
+{
+ const PxU32 bufferSize = computeBufferSize(mHullData, getNb());
+ mHullData.mPolygons = reinterpret_cast<Gu::HullPolygonData*>(context.readExtraData<PxU8, PX_SERIAL_ALIGN>(bufferSize));
+
+ if(mBigConvexData)
+ {
+ mBigConvexData = context.readExtraData<BigConvexData, PX_SERIAL_ALIGN>();
+ new(mBigConvexData)BigConvexData(PxEmpty);
+ mBigConvexData->importExtraData(context);
+ mHullData.mBigConvexRawData = &mBigConvexData->mData;
+ }
+}
+
+Gu::ConvexMesh* Gu::ConvexMesh::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ ConvexMesh* obj = new (address) ConvexMesh(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(ConvexMesh);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+static bool convexHullLoad(Gu::ConvexHullData& data, PxInputStream& stream, PxBitAndDword& bufferSize)
+{
+ PxU32 version;
+ bool Mismatch;
+ if(!ReadHeader('C', 'L', 'H', 'L', version, Mismatch, stream))
+ return false;
+
+ if(!ReadHeader('C', 'V', 'H', 'L', version, Mismatch, stream))
+ return false;
+
+ PxU32 Nb;
+
+ // Import figures
+ {
+ PxU32 tmp[4];
+ ReadDwordBuffer(tmp, 4, Mismatch, stream);
+ data.mNbHullVertices = Ps::to8(tmp[0]);
+ data.mNbEdges = Ps::to16(tmp[1]);
+ data.mNbPolygons = Ps::to8(tmp[2]);
+ Nb = tmp[3];
+ }
+
+ //AM: In practice the old aligner approach wastes 20 bytes and there is no reason to 20 byte align this data.
+ //I changed the code to just 4 align for the time being.
+ //On consoles if anything we will need to make this stuff 16 byte align vectors to have any sense, which will have to be done by padding data structures.
+ PX_ASSERT(sizeof(Gu::HullPolygonData) % sizeof(PxReal) == 0); //otherwise please pad it.
+ PX_ASSERT(sizeof(PxVec3) % sizeof(PxReal) == 0);
+
+ PxU32 bytesNeeded = computeBufferSize(data, Nb);
+
+ PX_FREE(data.mPolygons); // Load() can be called for an existing convex mesh. In that case we need to free
+ // the memory first.
+
+ bufferSize = Nb;
+ void* mDataMemory = PX_ALLOC(bytesNeeded, "ConvexHullData data");
+
+ PxU8* address = reinterpret_cast<PxU8*>(mDataMemory);
+
+ data.mPolygons = reinterpret_cast<Gu::HullPolygonData*>(address); address += sizeof(Gu::HullPolygonData) * data.mNbPolygons;
+ PxVec3* mDataHullVertices = reinterpret_cast<PxVec3*>(address); address += sizeof(PxVec3) * data.mNbHullVertices;
+ PxU8* mDataFacesByEdges8 = address; address += sizeof(PxU8) * data.mNbEdges * 2;
+ PxU8* mDataFacesByVertices8 = address; address += sizeof(PxU8) * data.mNbHullVertices * 3;
+ PxU16* mEdges = reinterpret_cast<PxU16*>(address); address += data.mNbEdges.isBitSet() ? (sizeof(PxU16) * data.mNbEdges * 2) : 0;
+ PxU8* mDataVertexData8 = address; address += sizeof(PxU8) * Nb; // PT: leave that one last, so that we don't need to serialize "Nb"
+
+ PX_ASSERT(!(size_t(mDataHullVertices) % sizeof(PxReal)));
+ PX_ASSERT(!(size_t(data.mPolygons) % sizeof(PxReal)));
+ PX_ASSERT(size_t(address)<=size_t(mDataMemory)+bytesNeeded);
+
+ // Import vertices
+ readFloatBuffer(&mDataHullVertices->x, PxU32(3*data.mNbHullVertices), Mismatch, stream);
+
+ if(version<=6)
+ {
+ PxU16 useUnquantizedNormals = readWord(Mismatch, stream);
+ PX_UNUSED(useUnquantizedNormals);
+ }
+
+ // Import polygons
+ stream.read(data.mPolygons, data.mNbPolygons*sizeof(Gu::HullPolygonData));
+
+ if(Mismatch)
+ {
+ for(PxU32 i=0;i<data.mNbPolygons;i++)
+ flipData(data.mPolygons[i]);
+ }
+
+ stream.read(mDataVertexData8, Nb);
+ stream.read(mDataFacesByEdges8, PxU32(data.mNbEdges*2));
+ if(version <= 5)
+ {
+ //KS - we need to compute faces-by-vertices here
+
+ bool noPlaneShift = false;
+ for(PxU32 i=0; i< data.mNbHullVertices; ++i)
+ {
+ PxU32 count = 0;
+ PxU8 inds[3];
+ for(PxU32 j=0; j<data.mNbPolygons; ++j)
+ {
+ Gu::HullPolygonData& polygon = data.mPolygons[j];
+ for(PxU32 k=0; k< polygon.mNbVerts; ++k)
+ {
+ PxU8 index = mDataVertexData8[polygon.mVRef8 + k];
+ if(i == index)
+ {
+ //Found a polygon
+ inds[count++] = Ps::to8(j);
+ break;
+ }
+ }
+ if(count == 3)
+ break;
+ }
+ //We have 3 indices
+ //PX_ASSERT(count == 3);
+ //Do something here
+ if(count == 3)
+ {
+ mDataFacesByVertices8[i*3+0] = inds[0];
+ mDataFacesByVertices8[i*3+1] = inds[1];
+ mDataFacesByVertices8[i*3+2] = inds[2];
+ }
+ else
+ {
+ noPlaneShift = true;
+ break;
+ }
+ }
+
+
+ if(noPlaneShift)
+ {
+ for(PxU32 a = 0; a < data.mNbHullVertices; ++a)
+ {
+ mDataFacesByVertices8[a*3] = 0xFF;
+ mDataFacesByVertices8[a*3+1] = 0xFF;
+ mDataFacesByVertices8[a*3+2] = 0xFF;
+ }
+ }
+
+ }
+ else
+ stream.read(mDataFacesByVertices8, PxU32(data.mNbHullVertices * 3));
+
+ if (data.mNbEdges.isBitSet())
+ {
+ if (version <= 7)
+ {
+ for (PxU32 a = 0; a < PxU32(data.mNbEdges * 2); ++a)
+ {
+ mEdges[a] = 0xFFFF;
+ }
+ }
+ else
+ {
+ readWordBuffer(mEdges, PxU32(data.mNbEdges * 2), Mismatch, stream);
+ }
+ }
+ return true;
+}
+
+bool Gu::ConvexMesh::load(PxInputStream& stream)
+{
+ // Import header
+ PxU32 version;
+ bool mismatch;
+ if(!readHeader('C', 'V', 'X', 'M', version, mismatch, stream))
+ return false;
+
+ // Check if old (incompatible) mesh format is loaded
+ if (version < PX_CONVEX_VERSION)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Loading convex mesh failed: "
+ "Deprecated mesh cooking format.");
+ return false;
+ }
+
+ // Import serialization flags
+ PxU32 serialFlags = readDword(mismatch, stream);
+ PX_UNUSED(serialFlags);
+
+ if(!convexHullLoad(mHullData, stream, mNb))
+ return false;
+
+ // Import local bounds
+ float tmp[8];
+ readFloatBuffer(tmp, 8, mismatch, stream);
+// geomEpsilon = tmp[0];
+ mHullData.mAABB = PxBounds3(PxVec3(tmp[1], tmp[2], tmp[3]), PxVec3(tmp[4],tmp[5],tmp[6]));
+
+ // Import mass info
+ mMass = tmp[7];
+ if(mMass!=-1.0f)
+ {
+ readFloatBuffer(&mInertia(0,0), 9, mismatch, stream);
+ readFloatBuffer(&mHullData.mCenterOfMass.x, 3, mismatch, stream);
+ }
+
+ // Import gaussmaps
+ PxF32 gaussMapFlag = readFloat(mismatch, stream);
+ if(gaussMapFlag != -1.0f)
+ {
+ PX_ASSERT(gaussMapFlag == 1.0f); //otherwise file is corrupt
+
+ PX_DELETE_AND_RESET(mBigConvexData);
+ PX_NEW_SERIALIZED(mBigConvexData,BigConvexData);
+
+ if(mBigConvexData)
+ {
+ mBigConvexData->Load(stream);
+ mHullData.mBigConvexRawData = &mBigConvexData->mData;
+ }
+ }
+
+/*
+ printf("\n\n");
+ printf("COM: %f %f %f\n", massInfo.centerOfMass.x, massInfo.centerOfMass.y, massInfo.centerOfMass.z);
+ printf("BND: %f %f %f\n", mHullData.aabb.getCenter().x, mHullData.aabb.getCenter().y, mHullData.aabb.getCenter().z);
+ printf("CNT: %f %f %f\n", mHullData.mCenterxx.x, mHullData.mCenterxx.y, mHullData.mCenterxx.z);
+ printf("COM-BND: %f BND-CNT: %f, CNT-COM: %f\n", (massInfo.centerOfMass - mHullData.aabb.getCenter()).magnitude(), (mHullData.aabb.getCenter() - mHullData.mCenterxx).magnitude(), (mHullData.mCenterxx - massInfo.centerOfMass).magnitude());
+*/
+
+// TEST_INTERNAL_OBJECTS
+ mHullData.mInternal.mRadius = readFloat(mismatch, stream);
+ mHullData.mInternal.mExtents[0] = readFloat(mismatch, stream);
+ mHullData.mInternal.mExtents[1] = readFloat(mismatch, stream);
+ mHullData.mInternal.mExtents[2] = readFloat(mismatch, stream);
+
+ PX_ASSERT(PxVec3(mHullData.mInternal.mExtents[0], mHullData.mInternal.mExtents[1], mHullData.mInternal.mExtents[2]).isFinite());
+ PX_ASSERT(mHullData.mInternal.mExtents[0] != 0.0f);
+ PX_ASSERT(mHullData.mInternal.mExtents[1] != 0.0f);
+ PX_ASSERT(mHullData.mInternal.mExtents[2] != 0.0f);
+//~TEST_INTERNAL_OBJECTS
+ return true;
+}
+
+
+
+void Gu::ConvexMesh::release()
+{
+ decRefCount();
+}
+
+void Gu::ConvexMesh::onRefCountZero()
+{
+ if ((!getBufferSize()) || mMeshFactory->removeConvexMesh(*this)) // when the mesh failed to load properly, it will not have been added to the convex array
+ {
+ GuMeshFactory* mf = mMeshFactory;
+ Cm::deletePxBase(this);
+ mf->notifyFactoryListener(this, PxConcreteType::eCONVEX_MESH);
+ return;
+ }
+
+ // PT: if we reach this point, we didn't find the mesh in the Physics object => don't delete!
+ // This prevents deleting the object twice.
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Gu::ConvexMesh::release: double deletion detected!");
+}
+
+void Gu::ConvexMesh::acquireReference()
+{
+ incRefCount();
+}
+
+PxU32 Gu::ConvexMesh::getReferenceCount() const
+{
+ return getRefCount();
+}
+
+void Gu::ConvexMesh::getMassInformation(PxReal& mass, PxMat33& localInertia, PxVec3& localCenterOfMass) const
+{
+ mass = Gu::ConvexMesh::getMass();
+ localInertia = Gu::ConvexMesh::getInertia();
+ localCenterOfMass = Gu::ConvexMesh::getHull().mCenterOfMass;
+}
+
+PxBounds3 Gu::ConvexMesh::getLocalBounds() const
+{
+ PX_ASSERT(mHullData.mAABB.isValid());
+ return PxBounds3::centerExtents(mHullData.mAABB.mCenter, mHullData.mAABB.mExtents);
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "CmMatrix34.h"
+#include "GuDebug.h"
+void Gu::ConvexMesh::debugVisualize(Cm::RenderOutput& out, const PxTransform& pose, const PxMeshScale& scale) const
+{
+ const PxU32 scolor = PxU32(PxDebugColor::eARGB_MAGENTA);
+
+ const PxVec3* vertices = mHullData.getHullVertices();
+ const PxU8* indexBuffer = mHullData.getVertexData8();
+ const PxU32 nbPolygons = getNbPolygonsFast();
+
+ const PxMat44 m44(PxMat33(pose.q) * scale.toMat33(), pose.p);
+
+ out << m44 << scolor; // PT: no need to output this for each segment!
+
+ for (PxU32 i = 0; i < nbPolygons; i++)
+ {
+ const PxU32 pnbVertices = mHullData.mPolygons[i].mNbVerts;
+
+ PxVec3 begin = m44.transform(vertices[indexBuffer[0]]); // PT: transform it only once before the loop starts
+ for (PxU32 j = 1; j < pnbVertices; j++)
+ {
+ PxVec3 end = m44.transform(vertices[indexBuffer[j]]);
+ out.outputSegment(begin, end);
+ begin = end;
+ }
+ out.outputSegment(begin, m44.transform(vertices[indexBuffer[0]]));
+
+ indexBuffer += pnbVertices;
+ }
+}
+
+#endif