diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/mesh/GuTriangleMesh.cpp | |
| download | physx-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/GeomUtils/src/mesh/GuTriangleMesh.cpp')
| -rw-r--r-- | PhysX_3.4/Source/GeomUtils/src/mesh/GuTriangleMesh.cpp | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/mesh/GuTriangleMesh.cpp b/PhysX_3.4/Source/GeomUtils/src/mesh/GuTriangleMesh.cpp new file mode 100644 index 00000000..be47d3e1 --- /dev/null +++ b/PhysX_3.4/Source/GeomUtils/src/mesh/GuTriangleMesh.cpp @@ -0,0 +1,457 @@ +// 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 "PsIntrinsics.h" +#include "GuMidphaseInterface.h" +#include "GuSerialize.h" +#include "GuMeshFactory.h" +#include "CmRenderOutput.h" +#include "PxVisualizationParameter.h" +#include "GuConvexEdgeFlags.h" +#include "GuBox.h" +#include "PxMeshScale.h" +#include "CmUtils.h" + +using namespace physx; + +namespace physx +{ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static PxConcreteType::Enum gTable[] = { PxConcreteType::eTRIANGLE_MESH_BVH33, + PxConcreteType::eTRIANGLE_MESH_BVH34 + }; + +Gu::TriangleMesh::TriangleMesh(GuMeshFactory& factory, TriangleMeshData& d) +: PxTriangleMesh(PxType(gTable[d.mType]), PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) +, mNbVertices (d.mNbVertices) +, mNbTriangles (d.mNbTriangles) +, mVertices (d.mVertices) +, mTriangles (d.mTriangles) +, mAABB (d.mAABB) +, mExtraTrigData (d.mExtraTrigData) +, mGeomEpsilon (d.mGeomEpsilon) +, mFlags (d.mFlags) +, mMaterialIndices (d.mMaterialIndices) +, mFaceRemap (d.mFaceRemap) +, mAdjacencies (d.mAdjacencies) + +, mMeshFactory (&factory) + +, mGRB_triIndices (d.mGRB_triIndices) + +, mGRB_triAdjacencies (d.mGRB_triAdjacencies) +, mGRB_vertValency (d.mGRB_vertValency) +, mGRB_adjVertStart (d.mGRB_adjVertStart) +, mGRB_adjVertices (d.mGRB_adjVertices) + +, mGRB_meshAdjVerticiesTotal (d.mGRB_meshAdjVerticiesTotal) +, mGRB_faceRemap (d.mGRB_faceRemap) +, mGRB_BV32Tree (d.mGRB_BV32Tree) +{ + // this constructor takes ownership of memory from the data object + d.mVertices = 0; + d.mTriangles = 0; + d.mExtraTrigData = 0; + d.mFaceRemap = 0; + d.mAdjacencies = 0; + d.mMaterialIndices = 0; + + d.mGRB_triIndices = 0; + + d.mGRB_triAdjacencies = 0; + d.mGRB_vertValency = 0; + d.mGRB_adjVertStart = 0; + d.mGRB_adjVertices = 0; + d.mGRB_faceRemap = 0; + d.mGRB_BV32Tree = 0; + + // PT: 'getPaddedBounds()' is only safe if we make sure the bounds member is followed by at least 32bits of data + PX_COMPILE_TIME_ASSERT(PX_OFFSET_OF(Gu::TriangleMesh, mExtraTrigData)>=PX_OFFSET_OF(Gu::TriangleMesh, mAABB)+4); + +} + +Gu::TriangleMesh::~TriangleMesh() +{ + if(getBaseFlags() & PxBaseFlag::eOWNS_MEMORY) + { + PX_FREE_AND_RESET(mExtraTrigData); + PX_FREE_AND_RESET(mFaceRemap); + PX_FREE_AND_RESET(mAdjacencies); + PX_FREE_AND_RESET(mMaterialIndices); + PX_FREE_AND_RESET(mTriangles); + PX_FREE_AND_RESET(mVertices); + + PX_FREE_AND_RESET(mGRB_triIndices); + + PX_FREE_AND_RESET(mGRB_triAdjacencies); + PX_FREE_AND_RESET(mGRB_vertValency); + PX_FREE_AND_RESET(mGRB_adjVertStart); + PX_FREE_AND_RESET(mGRB_adjVertices); + PX_FREE_AND_RESET(mGRB_faceRemap); + + BV32Tree* bv32Tree = reinterpret_cast<BV32Tree*>(mGRB_BV32Tree); + PX_DELETE_AND_RESET(bv32Tree); + + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// PT: used to be automatic but making it manual saves bytes in the internal mesh + +void Gu::TriangleMesh::exportExtraData(PxSerializationContext& stream) +{ + //PX_DEFINE_DYNAMIC_ARRAY(TriangleMesh, mVertices, PxField::eVEC3, mNbVertices, Ps::PxFieldFlag::eSERIALIZE), + if(mVertices) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mVertices, mNbVertices * sizeof(PxVec3)); + } + + if(mTriangles) + { + const PxU32 triangleSize = mFlags & PxTriangleMeshFlag::e16_BIT_INDICES ? sizeof(PxU16) : sizeof(PxU32); + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mTriangles, mNbTriangles * 3 * triangleSize); + } + + //PX_DEFINE_DYNAMIC_ARRAY(TriangleMesh, mExtraTrigData, PxField::eBYTE, mNbTriangles, Ps::PxFieldFlag::eSERIALIZE), + if(mExtraTrigData) + { + // PT: it might not be needed to 16-byte align this array of PxU8.... + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mExtraTrigData, mNbTriangles * sizeof(PxU8)); + } + + if(mMaterialIndices) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mMaterialIndices, mNbTriangles * sizeof(PxU16)); + } + + if(mFaceRemap) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mFaceRemap, mNbTriangles * sizeof(PxU32)); + } + + if(mAdjacencies) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mAdjacencies, mNbTriangles * sizeof(PxU32) * 3); + } +} + +void Gu::TriangleMesh::importExtraData(PxDeserializationContext& context) +{ + // PT: vertices are followed by indices, so it will be safe to V4Load vertices from a deserialized binary file + if(mVertices) + mVertices = context.readExtraData<PxVec3, PX_SERIAL_ALIGN>(mNbVertices); + + if(mTriangles) + { + if(mFlags & PxTriangleMeshFlag::e16_BIT_INDICES) + mTriangles = context.readExtraData<PxU16, PX_SERIAL_ALIGN>(3*mNbTriangles); + else + mTriangles = context.readExtraData<PxU32, PX_SERIAL_ALIGN>(3*mNbTriangles); + } + + if(mExtraTrigData) + mExtraTrigData = context.readExtraData<PxU8, PX_SERIAL_ALIGN>(mNbTriangles); + + if(mMaterialIndices) + mMaterialIndices = context.readExtraData<PxU16, PX_SERIAL_ALIGN>(mNbTriangles); + + if(mFaceRemap) + mFaceRemap = context.readExtraData<PxU32, PX_SERIAL_ALIGN>(mNbTriangles); + + if(mAdjacencies) + mAdjacencies = context.readExtraData<PxU32, PX_SERIAL_ALIGN>(3*mNbTriangles); +} + +void Gu::TriangleMesh::onRefCountZero() +{ + if(mMeshFactory->removeTriangleMesh(*this)) + { + const PxType type = getConcreteType(); + GuMeshFactory* mf = mMeshFactory; + Cm::deletePxBase(this); + mf->notifyFactoryListener(this, type); + 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::TriangleMesh::release: double deletion detected!"); +} +//~PX_SERIALIZATION + +void Gu::TriangleMesh::release() +{ + decRefCount(); +} + +#if PX_ENABLE_DYNAMIC_MESH_RTREE +PxVec3 * Gu::TriangleMesh::getVerticesForModification() +{ + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxTriangleMesh::getVerticesForModification() is only supported for meshes with PxMeshMidPhase::eBVHDynamic."); + + return NULL; +} + +PxBounds3 Gu::TriangleMesh::refitBVH() +{ + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxTriangleMesh::refitBVH() is only supported for meshes with PxMeshMidPhase::eBVHDynamic."); + + return PxBounds3(mAABB.getMin(), mAABB.getMax()); +} +#endif + +#if PX_ENABLE_DEBUG_VISUALIZATION + +static void getTriangle(const Gu::TriangleMesh&, PxU32 i, PxVec3* wp, const PxVec3* vertices, const void* indices, bool has16BitIndices) +{ + PxU32 ref0, ref1, ref2; + + if(!has16BitIndices) + { + const PxU32* dtriangles = reinterpret_cast<const PxU32*>(indices); + ref0 = dtriangles[i*3+0]; + ref1 = dtriangles[i*3+1]; + ref2 = dtriangles[i*3+2]; + } + else + { + const PxU16* wtriangles = reinterpret_cast<const PxU16*>(indices); + ref0 = wtriangles[i*3+0]; + ref1 = wtriangles[i*3+1]; + ref2 = wtriangles[i*3+2]; + } + + wp[0] = vertices[ref0]; + wp[1] = vertices[ref1]; + wp[2] = vertices[ref2]; +} + +static void getTriangle(const Gu::TriangleMesh& mesh, PxU32 i, PxVec3* wp, const PxVec3* vertices, const void* indices, const Cm::Matrix34& absPose, bool has16BitIndices) +{ + PxVec3 localVerts[3]; + getTriangle(mesh, i, localVerts, vertices, indices, has16BitIndices); + + wp[0] = absPose.transform(localVerts[0]); + wp[1] = absPose.transform(localVerts[1]); + wp[2] = absPose.transform(localVerts[2]); +} + +static void visualizeActiveEdges(Cm::RenderOutput& out, const Gu::TriangleMesh& mesh, PxU32 nbTriangles, const PxU32* results, const Cm::Matrix34& absPose, const PxMat44& midt) +{ + const PxU8* extraTrigData = mesh.getExtraTrigData(); + PX_ASSERT(extraTrigData); + + const PxVec3* vertices = mesh.getVerticesFast(); + const void* indices = mesh.getTrianglesFast(); + + const PxU32 ecolor = PxU32(PxDebugColor::eARGB_YELLOW); + const bool has16Bit = mesh.has16BitIndices(); + for(PxU32 i=0; i<nbTriangles; i++) + { + const PxU32 index = results ? results[i] : i; + + PxVec3 wp[3]; + getTriangle(mesh, index, wp, vertices, indices, absPose, has16Bit); + + const PxU32 flags = extraTrigData[index]; + + if(flags & Gu::ETD_CONVEX_EDGE_01) + { + out << midt << ecolor << Cm::RenderOutput::LINES << wp[0] << wp[1]; + } + if(flags & Gu::ETD_CONVEX_EDGE_12) + { + out << midt << ecolor << Cm::RenderOutput::LINES << wp[1] << wp[2]; + } + if(flags & Gu::ETD_CONVEX_EDGE_20) + { + out << midt << ecolor << Cm::RenderOutput::LINES << wp[0] << wp[2]; + } + } +} + +void Gu::TriangleMesh::debugVisualize( + Cm::RenderOutput& out, const PxTransform& pose, const PxMeshScale& scaling, const PxBounds3& cullbox, + const PxU64 mask, const PxReal fscale, const PxU32 numMaterials) const +{ + PX_UNUSED(numMaterials); + + //bool cscale = !!(mask & ((PxU64)1 << PxVisualizationParameter::eCULL_BOX)); + const PxU64 cullBoxMask = PxU64(1) << PxVisualizationParameter::eCULL_BOX; + bool cscale = ((mask & cullBoxMask) == cullBoxMask); + + const PxMat44 midt(PxIdentity); + const Cm::Matrix34 absPose(PxMat33(pose.q) * scaling.toMat33(), pose.p); + + PxU32 nbTriangles = getNbTrianglesFast(); + const PxU32 nbVertices = getNbVerticesFast(); + const PxVec3* vertices = getVerticesFast(); + const void* indices = getTrianglesFast(); + + const PxDebugColor::Enum colors[] = + { + PxDebugColor::eARGB_BLACK, + PxDebugColor::eARGB_RED, + PxDebugColor::eARGB_GREEN, + PxDebugColor::eARGB_BLUE, + PxDebugColor::eARGB_YELLOW, + PxDebugColor::eARGB_MAGENTA, + PxDebugColor::eARGB_CYAN, + PxDebugColor::eARGB_WHITE, + PxDebugColor::eARGB_GREY, + PxDebugColor::eARGB_DARKRED, + PxDebugColor::eARGB_DARKGREEN, + PxDebugColor::eARGB_DARKBLUE, + }; + + const PxU32 colorCount = sizeof(colors)/sizeof(PxDebugColor::Enum); + + if(cscale) + { + const Gu::Box worldBox( + (cullbox.maximum + cullbox.minimum)*0.5f, + (cullbox.maximum - cullbox.minimum)*0.5f, + PxMat33(PxIdentity)); + + // PT: TODO: use the callback version here to avoid allocating this huge array + PxU32* results = reinterpret_cast<PxU32*>(PX_ALLOC_TEMP(sizeof(PxU32)*nbTriangles, "tmp triangle indices")); + LimitedResults limitedResults(results, nbTriangles, 0); + Midphase::intersectBoxVsMesh(worldBox, *this, pose, scaling, &limitedResults); + nbTriangles = limitedResults.mNbResults; + + if (fscale) + { + const PxU32 fcolor = PxU32(PxDebugColor::eARGB_DARKRED); + + for (PxU32 i=0; i<nbTriangles; i++) + { + const PxU32 index = results[i]; + PxVec3 wp[3]; + getTriangle(*this, index, wp, vertices, indices, absPose, has16BitIndices()); + + const PxVec3 center = (wp[0] + wp[1] + wp[2]) / 3.0f; + PxVec3 normal = (wp[0] - wp[1]).cross(wp[0] - wp[2]); + PX_ASSERT(!normal.isZero()); + normal = normal.getNormalized(); + + out << midt << fcolor << + Cm::DebugArrow(center, normal * fscale); + } + } + + if (mask & (PxU64(1) << PxVisualizationParameter::eCOLLISION_SHAPES)) + { + const PxU32 scolor = PxU32(PxDebugColor::eARGB_MAGENTA); + + out << midt << scolor; // PT: no need to output this for each segment! + + PxDebugLine* segments = out.reserveSegments(nbTriangles*3); + for(PxU32 i=0; i<nbTriangles; i++) + { + const PxU32 index = results[i]; + PxVec3 wp[3]; + getTriangle(*this, index, wp, vertices, indices, absPose, has16BitIndices()); + segments[0] = PxDebugLine(wp[0], wp[1], scolor); + segments[1] = PxDebugLine(wp[1], wp[2], scolor); + segments[2] = PxDebugLine(wp[2], wp[0], scolor); + segments+=3; + } + } + + if ((mask & (PxU64(1) << PxVisualizationParameter::eCOLLISION_EDGES)) && mExtraTrigData) + visualizeActiveEdges(out, *this, nbTriangles, results, absPose, midt); + + PX_FREE(results); + } + else + { + if (fscale) + { + const PxU32 fcolor = PxU32(PxDebugColor::eARGB_DARKRED); + + for (PxU32 i=0; i<nbTriangles; i++) + { + PxVec3 wp[3]; + getTriangle(*this, i, wp, vertices, indices, absPose, has16BitIndices()); + + const PxVec3 center = (wp[0] + wp[1] + wp[2]) / 3.0f; + PxVec3 normal = (wp[0] - wp[1]).cross(wp[0] - wp[2]); + PX_ASSERT(!normal.isZero()); + normal = normal.getNormalized(); + + out << midt << fcolor << + Cm::DebugArrow(center, normal * fscale); + } + } + + if (mask & (PxU64(1) << PxVisualizationParameter::eCOLLISION_SHAPES)) + { + PxU32 scolor = PxU32(PxDebugColor::eARGB_MAGENTA); + + out << midt << scolor; // PT: no need to output this for each segment! + + PxVec3* transformed = reinterpret_cast<PxVec3*>(PX_ALLOC(sizeof(PxVec3)*nbVertices, "PxVec3")); + for(PxU32 i=0;i<nbVertices;i++) + transformed[i] = absPose.transform(vertices[i]); + + PxDebugLine* segments = out.reserveSegments(nbTriangles*3); + for (PxU32 i=0; i<nbTriangles; i++) + { + PxVec3 wp[3]; + getTriangle(*this, i, wp, transformed, indices, has16BitIndices()); + const PxU32 localMaterialIndex = getTriangleMaterialIndex(i); + scolor = colors[localMaterialIndex % colorCount]; + + segments[0] = PxDebugLine(wp[0], wp[1], scolor); + segments[1] = PxDebugLine(wp[1], wp[2], scolor); + segments[2] = PxDebugLine(wp[2], wp[0], scolor); + segments+=3; + } + + PX_FREE(transformed); + } + + if ((mask & (PxU64(1) << PxVisualizationParameter::eCOLLISION_EDGES)) && mExtraTrigData) + visualizeActiveEdges(out, *this, nbTriangles, NULL, absPose, midt); + } +} + +#endif // #if PX_ENABLE_DEBUG_VISUALIZATION + +} // namespace physx |