feat(physics): wire physx sdk into build
This commit is contained in:
73
engine/third_party/physx/source/physxextensions/src/ExtBroadPhase.cpp
vendored
Normal file
73
engine/third_party/physx/source/physxextensions/src/ExtBroadPhase.cpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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/PxBounds3.h"
|
||||
#include "foundation/PxErrorCallback.h"
|
||||
#include "foundation/PxFoundation.h"
|
||||
#include "extensions/PxBroadPhaseExt.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxU32 PxBroadPhaseExt::createRegionsFromWorldBounds(PxBounds3* regions, const PxBounds3& globalBounds, PxU32 nbSubdiv, PxU32 upAxis)
|
||||
{
|
||||
PX_CHECK_MSG(globalBounds.isValid(), "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid bounds provided!");
|
||||
PX_CHECK_MSG(upAxis<3, "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid up-axis provided!");
|
||||
|
||||
const PxVec3& min = globalBounds.minimum;
|
||||
const PxVec3& max = globalBounds.maximum;
|
||||
const float dx = (max.x - min.x) / float(nbSubdiv);
|
||||
const float dy = (max.y - min.y) / float(nbSubdiv);
|
||||
const float dz = (max.z - min.z) / float(nbSubdiv);
|
||||
PxU32 nbRegions = 0;
|
||||
PxVec3 currentMin, currentMax;
|
||||
for(PxU32 j=0;j<nbSubdiv;j++)
|
||||
{
|
||||
for(PxU32 i=0;i<nbSubdiv;i++)
|
||||
{
|
||||
if(upAxis==0)
|
||||
{
|
||||
currentMin = PxVec3(min.x, min.y + dy * float(i), min.z + dz * float(j));
|
||||
currentMax = PxVec3(max.x, min.y + dy * float(i+1), min.z + dz * float(j+1));
|
||||
}
|
||||
else if(upAxis==1)
|
||||
{
|
||||
currentMin = PxVec3(min.x + dx * float(i), min.y, min.z + dz * float(j));
|
||||
currentMax = PxVec3(min.x + dx * float(i+1), max.y, min.z + dz * float(j+1));
|
||||
}
|
||||
else if(upAxis==2)
|
||||
{
|
||||
currentMin = PxVec3(min.x + dx * float(i), min.y + dy * float(j), min.z);
|
||||
currentMax = PxVec3(min.x + dx * float(i+1), min.y + dy * float(j+1), max.z);
|
||||
}
|
||||
|
||||
regions[nbRegions++] = PxBounds3(currentMin, currentMax);
|
||||
}
|
||||
}
|
||||
return nbRegions;
|
||||
}
|
||||
232
engine/third_party/physx/source/physxextensions/src/ExtCollection.cpp
vendored
Normal file
232
engine/third_party/physx/source/physxextensions/src/ExtCollection.cpp
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
// 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 "geometry/PxConvexMesh.h"
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
#include "geometry/PxHeightField.h"
|
||||
#include "extensions/PxJoint.h"
|
||||
#include "extensions/PxConstraintExt.h"
|
||||
#include "extensions/PxCollectionExt.h"
|
||||
#include "PxShape.h"
|
||||
#include "PxMaterial.h"
|
||||
#include "PxArticulationReducedCoordinate.h"
|
||||
#include "PxAggregate.h"
|
||||
#include "PxPhysics.h"
|
||||
#include "PxScene.h"
|
||||
#include "PxPruningStructure.h"
|
||||
|
||||
|
||||
#include "foundation/PxArray.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void PxCollectionExt::releaseObjects(PxCollection& collection, bool releaseExclusiveShapes)
|
||||
{
|
||||
PxArray<PxBase*> releasableObjects;
|
||||
|
||||
for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
|
||||
{
|
||||
PxBase* s = &collection.getObject(i);
|
||||
// pruning structure must be released before its actors
|
||||
if(s->is<PxPruningStructure>())
|
||||
{
|
||||
if(!releasableObjects.empty())
|
||||
{
|
||||
PxBase* first = releasableObjects[0];
|
||||
releasableObjects.pushBack(first);
|
||||
releasableObjects[0] = s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->isReleasable() && (releaseExclusiveShapes || !s->is<PxShape>() || !s->is<PxShape>()->isExclusive()))
|
||||
releasableObjects.pushBack(s);
|
||||
}
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < releasableObjects.size(); ++i)
|
||||
releasableObjects[i]->release();
|
||||
|
||||
while (collection.getNbObjects() > 0)
|
||||
collection.remove(collection.getObject(0));
|
||||
}
|
||||
|
||||
|
||||
void PxCollectionExt::remove(PxCollection& collection, PxType concreteType, PxCollection* to)
|
||||
{
|
||||
PxArray<PxBase*> removeObjects;
|
||||
|
||||
for (PxU32 i = 0; i < collection.getNbObjects(); i++)
|
||||
{
|
||||
PxBase& object = collection.getObject(i);
|
||||
if(concreteType == object.getConcreteType())
|
||||
{
|
||||
if(to)
|
||||
to->add(object);
|
||||
|
||||
removeObjects.pushBack(&object);
|
||||
}
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < removeObjects.size(); ++i)
|
||||
collection.remove(*removeObjects[i]);
|
||||
}
|
||||
|
||||
PxCollection* PxCollectionExt::createCollection(PxPhysics& physics)
|
||||
{
|
||||
PxCollection* collection = PxCreateCollection();
|
||||
if (!collection)
|
||||
return NULL;
|
||||
|
||||
// Collect convexes
|
||||
{
|
||||
PxArray<PxConvexMesh*> objects(physics.getNbConvexMeshes());
|
||||
const PxU32 nb = physics.getConvexMeshes(objects.begin(), objects.size());
|
||||
PX_ASSERT(nb == objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
// Collect triangle meshes
|
||||
{
|
||||
PxArray<PxTriangleMesh*> objects(physics.getNbTriangleMeshes());
|
||||
const PxU32 nb = physics.getTriangleMeshes(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb == objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
// Collect heightfields
|
||||
{
|
||||
PxArray<PxHeightField*> objects(physics.getNbHeightFields());
|
||||
const PxU32 nb = physics.getHeightFields(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb == objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
// Collect materials
|
||||
{
|
||||
PxArray<PxMaterial*> objects(physics.getNbMaterials());
|
||||
const PxU32 nb = physics.getMaterials(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb == objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
// Collect shapes
|
||||
{
|
||||
PxArray<PxShape*> objects(physics.getNbShapes());
|
||||
const PxU32 nb = physics.getShapes(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb == objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
PxCollection* PxCollectionExt::createCollection(PxScene& scene)
|
||||
{
|
||||
PxCollection* collection = PxCreateCollection();
|
||||
if (!collection)
|
||||
return NULL;
|
||||
|
||||
// Collect actors
|
||||
{
|
||||
PxActorTypeFlags selectionFlags = PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC;
|
||||
|
||||
|
||||
PxArray<PxActor*> objects(scene.getNbActors(selectionFlags));
|
||||
const PxU32 nb = scene.getActors(selectionFlags, objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb==objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
|
||||
// Collect constraints
|
||||
{
|
||||
PxArray<PxConstraint*> objects(scene.getNbConstraints());
|
||||
const PxU32 nb = scene.getConstraints(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb==objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
{
|
||||
PxU32 typeId;
|
||||
PxJoint* joint = reinterpret_cast<PxJoint*>(objects[i]->getExternalReference(typeId));
|
||||
if(typeId == PxConstraintExtIDs::eJOINT)
|
||||
collection->add(*joint);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect articulations
|
||||
{
|
||||
PxArray<PxArticulationReducedCoordinate*> objects(scene.getNbArticulations());
|
||||
const PxU32 nb = scene.getArticulations(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb==objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
// Collect aggregates
|
||||
{
|
||||
PxArray<PxAggregate*> objects(scene.getNbAggregates());
|
||||
const PxU32 nb = scene.getAggregates(objects.begin(), objects.size());
|
||||
|
||||
PX_ASSERT(nb==objects.size());
|
||||
PX_UNUSED(nb);
|
||||
|
||||
for(PxU32 i=0;i<objects.size();i++)
|
||||
collection->add(*objects[i]);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
424
engine/third_party/physx/source/physxextensions/src/ExtConstraintHelper.h
vendored
Normal file
424
engine/third_party/physx/source/physxextensions/src/ExtConstraintHelper.h
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
// 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 EXT_CONSTRAINT_HELPER_H
|
||||
#define EXT_CONSTRAINT_HELPER_H
|
||||
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "foundation/PxMat33.h"
|
||||
#include "foundation/PxSIMDHelpers.h"
|
||||
#include "extensions/PxD6Joint.h"
|
||||
#include "ExtJointData.h"
|
||||
#include "foundation/PxVecMath.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
namespace joint
|
||||
{
|
||||
PX_FORCE_INLINE void applyNeighborhoodOperator(const PxTransform32& cA2w, PxTransform32& cB2w)
|
||||
{
|
||||
if(cA2w.q.dot(cB2w.q)<0.0f) // minimum dist quat (equiv to flipping cB2bB.q, which we don't use anywhere)
|
||||
cB2w.q = -cB2w.q;
|
||||
}
|
||||
|
||||
/*
|
||||
\brief Transform the two joint frames into the world frame using the global poses of the associated actors.
|
||||
|
||||
\param[out] cA2w joint frame associated with body 0 expressed in the world frame
|
||||
ie if g0 is the global pose of actor 0 then cA2w = g0 * jointFrame_0.
|
||||
\param[out] cB2w joint frame associated with body 1 expressed in the world frame
|
||||
ie if g1 is the global pose of actor 1 then cB2w = g1 * jointFrame_1.
|
||||
\param[in] data contains cmLocalPose^-1 * jointFrame for each body.
|
||||
\param[in] bA2w pose of the centre of mass of body 0 expressed in the world frame.
|
||||
\param[in] bB2w pose of the centre of mass of body 1 expressed in the world frame.
|
||||
|
||||
\note b2w = g*cmLocalPose so we have g = b2w*cmLocalPose^-1.
|
||||
We therefore have g * jointFrame = b2w * cmLocalPose^-1 * jointFrame = b2w * data.c2b
|
||||
*/
|
||||
PX_INLINE void computeJointFrames(PxTransform32& cA2w, PxTransform32& cB2w, const JointData& data, const PxTransform& bA2w, const PxTransform& bB2w)
|
||||
{
|
||||
PX_ASSERT(bA2w.isValid() && bB2w.isValid());
|
||||
|
||||
//cA2w = bA2w * (cMassLocalPose0^-1 * jointFrame0)
|
||||
//cB2w = bB2w * (cMassLocalPose1^-1 * jointFrame1)
|
||||
aos::transformMultiply<false, true>(cA2w, bA2w, data.c2b[0]);
|
||||
aos::transformMultiply<false, true>(cB2w, bB2w, data.c2b[1]);
|
||||
|
||||
PX_ASSERT(cA2w.isValid() && cB2w.isValid());
|
||||
}
|
||||
|
||||
PX_INLINE void computeJacobianAxes(PxVec3 row[3], const PxQuat& qa, const PxQuat& qb)
|
||||
{
|
||||
// Compute jacobian matrix for (qa* qb) [[* means conjugate in this expr]]
|
||||
// d/dt (qa* qb) = 1/2 L(qa*) R(qb) (omega_b - omega_a)
|
||||
// result is L(qa*) R(qb), where L(q) and R(q) are left/right q multiply matrix
|
||||
|
||||
const PxReal wa = qa.w, wb = qb.w;
|
||||
const PxVec3 va(qa.x,qa.y,qa.z), vb(qb.x,qb.y,qb.z);
|
||||
|
||||
const PxVec3 c = vb*wa + va*wb;
|
||||
const PxReal d0 = wa*wb;
|
||||
const PxReal d1 = va.dot(vb);
|
||||
const PxReal d = d0 - d1;
|
||||
|
||||
row[0] = (va * vb.x + vb * va.x + PxVec3(d, c.z, -c.y)) * 0.5f;
|
||||
row[1] = (va * vb.y + vb * va.y + PxVec3(-c.z, d, c.x)) * 0.5f;
|
||||
row[2] = (va * vb.z + vb * va.z + PxVec3(c.y, -c.x, d)) * 0.5f;
|
||||
|
||||
if((d0 + d1) != 0.0f) // check if relative rotation is 180 degrees which can lead to singular matrix
|
||||
return;
|
||||
else
|
||||
{
|
||||
row[0].x += PX_EPS_F32;
|
||||
row[1].y += PX_EPS_F32;
|
||||
row[2].z += PX_EPS_F32;
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Px1DConstraint* _linear(const PxVec3& axis, const PxVec3& ra, const PxVec3& rb, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c)
|
||||
{
|
||||
c->solveHint = PxU16(hint);
|
||||
c->linear0 = axis;
|
||||
c->angular0 = ra.cross(axis);
|
||||
c->linear1 = axis;
|
||||
c->angular1 = rb.cross(axis);
|
||||
c->geometricError = posErr;
|
||||
PX_ASSERT(c->linear0.isFinite());
|
||||
PX_ASSERT(c->linear1.isFinite());
|
||||
PX_ASSERT(c->angular0.isFinite());
|
||||
PX_ASSERT(c->angular1.isFinite());
|
||||
return c;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Px1DConstraint* _angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c)
|
||||
{
|
||||
c->solveHint = PxU16(hint);
|
||||
c->linear0 = PxVec3(0.0f);
|
||||
c->angular0 = axis;
|
||||
c->linear1 = PxVec3(0.0f);
|
||||
c->angular1 = axis;
|
||||
c->geometricError = posErr;
|
||||
c->flags |= Px1DConstraintFlag::eANGULAR_CONSTRAINT;
|
||||
return c;
|
||||
}
|
||||
|
||||
class ConstraintHelper
|
||||
{
|
||||
Px1DConstraint* mConstraints;
|
||||
Px1DConstraint* mCurrent;
|
||||
PX_ALIGN(16, PxVec3p mRa);
|
||||
PX_ALIGN(16, PxVec3p mRb);
|
||||
PX_ALIGN(16, PxVec3p mCA2w);
|
||||
PX_ALIGN(16, PxVec3p mCB2w);
|
||||
|
||||
public:
|
||||
ConstraintHelper(Px1DConstraint* c, const PxVec3& ra, const PxVec3& rb)
|
||||
: mConstraints(c), mCurrent(c), mRa(ra), mRb(rb) {}
|
||||
|
||||
/*PX_NOINLINE*/ ConstraintHelper(Px1DConstraint* c, PxConstraintInvMassScale& invMassScale,
|
||||
PxTransform32& cA2w, PxTransform32& cB2w, PxVec3p& body0WorldOffset,
|
||||
const JointData& data, const PxTransform& bA2w, const PxTransform& bB2w)
|
||||
: mConstraints(c), mCurrent(c)
|
||||
{
|
||||
using namespace aos;
|
||||
|
||||
V4StoreA(V4LoadA(&data.invMassScale.linear0), &invMassScale.linear0); //invMassScale = data.invMassScale;
|
||||
|
||||
computeJointFrames(cA2w, cB2w, data, bA2w, bB2w);
|
||||
|
||||
if(1)
|
||||
{
|
||||
const Vec4V cB2wV = V4LoadA(&cB2w.p.x);
|
||||
const Vec4V raV = V4Sub(cB2wV, V4LoadU(&bA2w.p.x)); // const PxVec3 ra = cB2w.p - bA2w.p;
|
||||
|
||||
V4StoreU(raV, &body0WorldOffset.x); // body0WorldOffset = ra;
|
||||
|
||||
V4StoreA(raV, &mRa.x); // mRa = ra;
|
||||
|
||||
V4StoreA(V4Sub(cB2wV, V4LoadU(&bB2w.p.x)), &mRb.x); // mRb = cB2w.p - bB2w.p;
|
||||
|
||||
V4StoreA(V4LoadA(&cA2w.p.x), &mCA2w.x); // mCA2w = cA2w.p;
|
||||
V4StoreA(cB2wV, &mCB2w.x); // mCB2w = cB2w.p;
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxVec3 ra = cB2w.p - bA2w.p;
|
||||
|
||||
body0WorldOffset = ra;
|
||||
|
||||
mRa = ra;
|
||||
|
||||
mRb = cB2w.p - bB2w.p;
|
||||
|
||||
mCA2w = cA2w.p;
|
||||
mCB2w = cB2w.p;
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getRa() const { return mRa; }
|
||||
PX_FORCE_INLINE const PxVec3& getRb() const { return mRb; }
|
||||
|
||||
// hard linear & angular
|
||||
PX_FORCE_INLINE void linearHard(const PxVec3& axis, PxReal posErr)
|
||||
{
|
||||
Px1DConstraint* c = linear(axis, posErr, PxConstraintSolveHint::eEQUALITY);
|
||||
c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void angularHard(const PxVec3& axis, PxReal posErr)
|
||||
{
|
||||
Px1DConstraint* c = angular(axis, posErr, PxConstraintSolveHint::eEQUALITY);
|
||||
c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
|
||||
}
|
||||
|
||||
// limited linear & angular
|
||||
PX_FORCE_INLINE void linearLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, const PxJointLimitParameters& limit)
|
||||
{
|
||||
if(!limit.isSoft() || ordinate > limitValue)
|
||||
addLimit(linear(axis, limitValue - ordinate, PxConstraintSolveHint::eNONE), limit);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, const PxJointLimitParameters& limit)
|
||||
{
|
||||
if(!limit.isSoft() || ordinate > limitValue)
|
||||
addLimit(angular(axis, limitValue - ordinate, PxConstraintSolveHint::eNONE), limit);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal error, const PxJointLimitParameters& limit)
|
||||
{
|
||||
addLimit(angular(axis, error, PxConstraintSolveHint::eNONE), limit);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void anglePair(PxReal angle, PxReal lower, PxReal upper, const PxVec3& axis, const PxJointLimitParameters& limit)
|
||||
{
|
||||
PX_ASSERT(lower<upper);
|
||||
const bool softLimit = limit.isSoft();
|
||||
|
||||
if(!softLimit || angle < lower)
|
||||
angularLimit(-axis, -(lower - angle), limit);
|
||||
if(!softLimit || angle > upper)
|
||||
angularLimit(axis, (upper - angle), limit);
|
||||
}
|
||||
|
||||
// driven linear & angular
|
||||
|
||||
PX_FORCE_INLINE void linear(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive)
|
||||
{
|
||||
addDrive(linear(axis, error, PxConstraintSolveHint::eNONE), velTarget, drive);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void angular(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive, PxConstraintSolveHint::Enum hint = PxConstraintSolveHint::eNONE)
|
||||
{
|
||||
addDrive(angular(axis, error, hint), velTarget, drive);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 getCount() const { return PxU32(mCurrent - mConstraints); }
|
||||
|
||||
void prepareLockedAxes(const PxQuat& qA, const PxQuat& qB, const PxVec3& cB2cAp, PxU32 lin, PxU32 ang, PxVec3& raOut, PxVec3& rbOut, PxVec3* axis=NULL)
|
||||
{
|
||||
Px1DConstraint* current = mCurrent;
|
||||
|
||||
PxVec3 errorVector(0.0f);
|
||||
|
||||
PxVec3 ra = mRa;
|
||||
PxVec3 rb = mRb;
|
||||
if(lin)
|
||||
{
|
||||
const PxMat33Padded axes(qA);
|
||||
if(axis)
|
||||
*axis = axes.column0;
|
||||
|
||||
if(lin&1) errorVector -= axes.column0 * cB2cAp.x;
|
||||
if(lin&2) errorVector -= axes.column1 * cB2cAp.y;
|
||||
if(lin&4) errorVector -= axes.column2 * cB2cAp.z;
|
||||
|
||||
ra += errorVector;
|
||||
|
||||
//Note that our convention is that C(s) = geometricError = (xA + rA) - (xB + rB)
|
||||
//where xA, xB are the positions of the two bodies in the world frame and rA, rB
|
||||
//are the vectors in the world frame from each body to the joint anchor.
|
||||
//We solve Jv + C(s)/dt = Jv + geometricError/dt = 0.
|
||||
//With GA, GB denoting the actor poses in world frame and LA, LB denoting the
|
||||
//associated joint frames we have: cB2cAp = [(GA*LA)^-1 * (GB*LB)].p
|
||||
//But cB2cAp = (GA*LA).q.getConjugate() * ((xB + rB) - (xA + rA))
|
||||
//To match our convention we want geometricError = (GA*LA).q.getConjugate() * ((xA + rA) - (xB + rB))
|
||||
//cB2cAp therefore has the wrong sign to be used directly as the geometric error.
|
||||
//We need to negate cB2cAp to ensure that we set geometricError with the correct sign.
|
||||
if(lin&1) _linear(axes.column0, ra, rb, -cB2cAp.x, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
if(lin&2) _linear(axes.column1, ra, rb, -cB2cAp.y, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
if(lin&4) _linear(axes.column2, ra, rb, -cB2cAp.z, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
}
|
||||
|
||||
if (ang)
|
||||
{
|
||||
const PxQuat qB2qA = qA.getConjugate() * qB;
|
||||
|
||||
PxVec3 row[3];
|
||||
computeJacobianAxes(row, qA, qB);
|
||||
if (ang & 1) _angular(row[0], -qB2qA.x, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
if (ang & 2) _angular(row[1], -qB2qA.y, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
if (ang & 4) _angular(row[2], -qB2qA.z, PxConstraintSolveHint::eEQUALITY, current++);
|
||||
}
|
||||
|
||||
raOut = ra;
|
||||
rbOut = rb;
|
||||
|
||||
for(Px1DConstraint* front = mCurrent; front < current; front++)
|
||||
front->flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
|
||||
|
||||
mCurrent = current;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Px1DConstraint* getConstraintRow()
|
||||
{
|
||||
return mCurrent++;
|
||||
}
|
||||
|
||||
private:
|
||||
PX_FORCE_INLINE Px1DConstraint* linear(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint)
|
||||
{
|
||||
return _linear(axis, mRa, mRb, posErr, hint, mCurrent++);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Px1DConstraint* angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint)
|
||||
{
|
||||
return _angular(axis, posErr, hint, mCurrent++);
|
||||
}
|
||||
|
||||
void addLimit(Px1DConstraint* c, const PxJointLimitParameters& limit)
|
||||
{
|
||||
PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eOUTPUT_FORCE);
|
||||
|
||||
if(limit.isSoft())
|
||||
{
|
||||
flags |= Px1DConstraintFlag::eSPRING;
|
||||
c->mods.spring.stiffness = limit.stiffness;
|
||||
c->mods.spring.damping = limit.damping;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->solveHint = PxConstraintSolveHint::eINEQUALITY;
|
||||
c->mods.bounce.restitution = limit.restitution;
|
||||
c->mods.bounce.velocityThreshold = limit.bounceThreshold;
|
||||
|
||||
if (c->geometricError > 0.0f)
|
||||
{
|
||||
flags |= Px1DConstraintFlag::eKEEPBIAS;
|
||||
// note: positive error is the scenario where the limit is not hit yet. It reflects the
|
||||
// distance to the limit. Using eKEEPBIAS feels unintuitive in general but what seems to
|
||||
// be solved with this is:
|
||||
//
|
||||
// imagine the following scenario: object o moving towards a limit with velocity v
|
||||
//
|
||||
// |
|
||||
// o---> v |
|
||||
// |
|
||||
//
|
||||
// and let's denote the following distances
|
||||
//
|
||||
// |<-------->| |v|*dt (travel distance assuming time step dt)
|
||||
// |<-------------->| |ge| (distance to limit = geometric error)
|
||||
//
|
||||
// furthermore, the sign convention is that v as drawn here is negative and ge is
|
||||
// positive. Since -v*dt is smaller than ge, the limit will not get hit in the dt time
|
||||
// step range. This means, the velocity after the sim step should not change and remain v.
|
||||
// For the solver this means no impulse should get applied.
|
||||
// The impulse applied by the solver is of the form:
|
||||
//
|
||||
// impulse = -r * ((v - vT) + ge/dt) (r is a positive scalar value)
|
||||
//
|
||||
// for this example, let's assume the target velocity vT is zero, so:
|
||||
//
|
||||
// impulse = -r * (v + ge/dt) (1)
|
||||
//
|
||||
// Without Px1DConstraintFlag::eKEEPBIAS, the part related to the geometric error is ignored
|
||||
// during velocity iterations:
|
||||
//
|
||||
// impulse = -r * v
|
||||
//
|
||||
// The solver will apply the resulting (positive) impulse and this will change the velocity
|
||||
// of the object. That would be wrong though because the object does not hit the limit yet
|
||||
// and the velocity should stay the same.
|
||||
//
|
||||
// Why does Px1DConstraintFlag::eKEEPBIAS prevent this from happening? In this case, equation
|
||||
// (1) applies and since -v*dt < ge, the resulting impulse will be negative ((v + ge/dt) is
|
||||
// positive). Limit constraints are inequality constraints and clamp the impulse in the range
|
||||
// [0, maxImpulse], thus the negative impulse will get clamped to zero and the velocity will
|
||||
// not change (as desired).
|
||||
//
|
||||
// Why then create this constraint at all? Imagine the same scenario but with a velocity
|
||||
// magnitude such that the limit gets hit in the dt time step range:
|
||||
//
|
||||
// |<--------------------->| |v|*dt
|
||||
// |<-------------->| |ge|
|
||||
//
|
||||
// (v + ge/dt) will be negative and the impulse positive. The impulse will get applied and
|
||||
// will make sure that the velocity is reduced by the right amount such that the object
|
||||
// stops at the limit (and does not breach it).
|
||||
}
|
||||
|
||||
if(limit.restitution>0.0f)
|
||||
flags |= Px1DConstraintFlag::eRESTITUTION;
|
||||
}
|
||||
|
||||
c->flags = flags;
|
||||
c->minImpulse = 0.0f;
|
||||
}
|
||||
|
||||
void addDrive(Px1DConstraint* c, PxReal velTarget, const PxD6JointDrive& drive)
|
||||
{
|
||||
c->velocityTarget = velTarget;
|
||||
|
||||
PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eSPRING | Px1DConstraintFlag::eHAS_DRIVE_LIMIT);
|
||||
|
||||
if(drive.flags & PxD6JointDriveFlag::eACCELERATION)
|
||||
flags |= Px1DConstraintFlag::eACCELERATION_SPRING;
|
||||
|
||||
if (drive.flags & PxD6JointDriveFlag::eOUTPUT_FORCE)
|
||||
flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
|
||||
|
||||
c->flags = flags;
|
||||
c->mods.spring.stiffness = drive.stiffness;
|
||||
c->mods.spring.damping = drive.damping;
|
||||
|
||||
c->minImpulse = -drive.forceLimit;
|
||||
c->maxImpulse = drive.forceLimit;
|
||||
|
||||
PX_ASSERT(c->linear0.isFinite());
|
||||
PX_ASSERT(c->angular0.isFinite());
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
42
engine/third_party/physx/source/physxextensions/src/ExtConvexCoreExt.cpp
vendored
Normal file
42
engine/third_party/physx/source/physxextensions/src/ExtConvexCoreExt.cpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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/PxConvexCoreExt.h"
|
||||
#include "GuConvexGeometry.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void PxConvexCoreExt::computeMassInfo(const PxConvexCoreGeometry& convex, PxReal& density1Mass, PxMat33& inertiaTensor, PxVec3& centerOfMass)
|
||||
{
|
||||
Gu::computeMassInfo(convex, density1Mass, inertiaTensor, centerOfMass);
|
||||
}
|
||||
|
||||
void PxConvexCoreExt::visualize(const PxConvexCoreGeometry& convex, const PxTransform& pose, bool drawCore, const PxBounds3& cullbox, PxRenderOutput& out)
|
||||
{
|
||||
Gu::visualize(convex, pose, drawCore, cullbox, out);
|
||||
}
|
||||
89
engine/third_party/physx/source/physxextensions/src/ExtConvexMeshExt.cpp
vendored
Normal file
89
engine/third_party/physx/source/physxextensions/src/ExtConvexMeshExt.cpp
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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/PxPlane.h"
|
||||
#include "geometry/PxConvexMeshGeometry.h"
|
||||
#include "geometry/PxConvexMesh.h"
|
||||
#include "extensions/PxConvexMeshExt.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static const PxReal gEpsilon = .01f;
|
||||
|
||||
PxU32 physx::PxFindFaceIndex(const PxConvexMeshGeometry& convexGeom, const PxTransform& pose,
|
||||
const PxVec3& impactPos, const PxVec3& unitDir)
|
||||
{
|
||||
PX_ASSERT(unitDir.isFinite());
|
||||
PX_ASSERT(unitDir.isNormalized());
|
||||
PX_ASSERT(impactPos.isFinite());
|
||||
PX_ASSERT(pose.isFinite());
|
||||
|
||||
const PxVec3 impact = impactPos - unitDir * gEpsilon;
|
||||
|
||||
const PxVec3 localPoint = pose.transformInv(impact);
|
||||
const PxVec3 localDir = pose.rotateInv(unitDir);
|
||||
|
||||
// Create shape to vertex scale transformation matrix
|
||||
const PxMeshScale& meshScale = convexGeom.scale;
|
||||
const PxMat33 rot(meshScale.rotation);
|
||||
PxMat33 shape2VertexSkew = rot.getTranspose();
|
||||
const PxMat33 diagonal = PxMat33::createDiagonal(PxVec3(1.0f / meshScale.scale.x, 1.0f / meshScale.scale.y, 1.0f / meshScale.scale.z));
|
||||
shape2VertexSkew = shape2VertexSkew * diagonal;
|
||||
shape2VertexSkew = shape2VertexSkew * rot;
|
||||
|
||||
const PxU32 nbPolys = convexGeom.convexMesh->getNbPolygons();
|
||||
PxU32 minIndex = 0;
|
||||
PxReal minD = PX_MAX_REAL;
|
||||
for (PxU32 j = 0; j < nbPolys; j++)
|
||||
{
|
||||
PxHullPolygon hullPolygon;
|
||||
convexGeom.convexMesh->getPolygonData(j, hullPolygon);
|
||||
|
||||
// transform hull plane into shape space
|
||||
PxPlane plane;
|
||||
const PxVec3 tmp = shape2VertexSkew.transformTranspose(PxVec3(hullPolygon.mPlane[0],hullPolygon.mPlane[1],hullPolygon.mPlane[2]));
|
||||
const PxReal denom = 1.0f / tmp.magnitude();
|
||||
plane.n = tmp * denom;
|
||||
plane.d = hullPolygon.mPlane[3] * denom;
|
||||
|
||||
PxReal d = plane.distance(localPoint);
|
||||
if (d < 0.0f)
|
||||
continue;
|
||||
|
||||
const PxReal tweak = plane.n.dot(localDir) * gEpsilon;
|
||||
d += tweak;
|
||||
|
||||
if (d < minD)
|
||||
{
|
||||
minIndex = j;
|
||||
minD = d;
|
||||
}
|
||||
}
|
||||
return minIndex;
|
||||
}
|
||||
|
||||
92
engine/third_party/physx/source/physxextensions/src/ExtCpuWorkerThread.cpp
vendored
Normal file
92
engine/third_party/physx/source/physxextensions/src/ExtCpuWorkerThread.cpp
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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 "task/PxTask.h"
|
||||
#include "ExtCpuWorkerThread.h"
|
||||
#include "ExtDefaultCpuDispatcher.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Ext::CpuWorkerThread::CpuWorkerThread() : mOwner(NULL), mThreadId(0)
|
||||
{
|
||||
}
|
||||
|
||||
Ext::CpuWorkerThread::~CpuWorkerThread()
|
||||
{
|
||||
}
|
||||
|
||||
#define HighPriority true
|
||||
#define RegularPriority false
|
||||
|
||||
void Ext::CpuWorkerThread::execute()
|
||||
{
|
||||
mThreadId = getId();
|
||||
|
||||
const PxDefaultCpuDispatcherWaitForWorkMode::Enum ownerWaitForWorkMode = mOwner->getWaitForWorkMode();
|
||||
|
||||
while(!quitIsSignalled())
|
||||
{
|
||||
if(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == ownerWaitForWorkMode)
|
||||
mOwner->resetWakeSignal();
|
||||
|
||||
// PT: look for high priority tasks first, across threads
|
||||
PxBaseTask* task = getJob<HighPriority>();
|
||||
if(!task)
|
||||
task = mOwner->fetchNextTask<HighPriority>();
|
||||
|
||||
// PT: then look for regular tasks
|
||||
if(!task)
|
||||
task = getJob<RegularPriority>();
|
||||
if(!task)
|
||||
task = mOwner->fetchNextTask<RegularPriority>();
|
||||
|
||||
if(task)
|
||||
{
|
||||
mOwner->runTask(*task);
|
||||
task->release();
|
||||
}
|
||||
else if(PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_THREAD == ownerWaitForWorkMode)
|
||||
{
|
||||
PxThread::yield();
|
||||
}
|
||||
else if(PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_PROCESSOR == ownerWaitForWorkMode)
|
||||
{
|
||||
const PxU32 pauseCounter = mOwner->getYieldProcessorCount();
|
||||
for(PxU32 j = 0; j < pauseCounter; j++)
|
||||
PxThread::yieldProcesor();
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == ownerWaitForWorkMode);
|
||||
mOwner->waitForWork();
|
||||
}
|
||||
}
|
||||
|
||||
quit();
|
||||
}
|
||||
81
engine/third_party/physx/source/physxextensions/src/ExtCpuWorkerThread.h
vendored
Normal file
81
engine/third_party/physx/source/physxextensions/src/ExtCpuWorkerThread.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// 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 EXT_CPU_WORKER_THREAD_H
|
||||
#define EXT_CPU_WORKER_THREAD_H
|
||||
|
||||
#include "foundation/PxThread.h"
|
||||
#include "ExtTaskQueueHelper.h"
|
||||
#include "ExtSharedQueueEntryPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
class DefaultCpuDispatcher;
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value.
|
||||
#endif // Because of the SList member I assume
|
||||
|
||||
class CpuWorkerThread : public PxThread
|
||||
{
|
||||
public:
|
||||
CpuWorkerThread();
|
||||
~CpuWorkerThread();
|
||||
|
||||
PX_FORCE_INLINE void initialize(DefaultCpuDispatcher* ownerDispatcher) { mOwner = ownerDispatcher; }
|
||||
PX_FORCE_INLINE PxThread::Id getWorkerThreadId() const { return mThreadId; }
|
||||
|
||||
template<const bool highPriorityT>
|
||||
PX_FORCE_INLINE PxBaseTask* getJob() { return mHelper.fetchTask<highPriorityT>(); }
|
||||
|
||||
void execute();
|
||||
|
||||
PX_FORCE_INLINE bool tryAcceptJobToLocalQueue(PxBaseTask& task, PxThread::Id taskSubmitionThread)
|
||||
{
|
||||
if(taskSubmitionThread == mThreadId)
|
||||
return mHelper.tryAcceptJobToQueue(task);
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
DefaultCpuDispatcher* mOwner;
|
||||
TaskQueueHelper mHelper;
|
||||
PxThread::Id mThreadId;
|
||||
};
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
994
engine/third_party/physx/source/physxextensions/src/ExtCustomGeometryExt.cpp
vendored
Normal file
994
engine/third_party/physx/source/physxextensions/src/ExtCustomGeometryExt.cpp
vendored
Normal file
@@ -0,0 +1,994 @@
|
||||
// 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/PxCustomGeometryExt.h"
|
||||
|
||||
#include <geometry/PxGeometryHelpers.h>
|
||||
#include <geometry/PxGeometryQuery.h>
|
||||
#include <geometry/PxMeshQuery.h>
|
||||
#include <geometry/PxTriangle.h>
|
||||
#include <geometry/PxTriangleMesh.h>
|
||||
#include <geometry/PxTriangleMeshGeometry.h>
|
||||
#include <geomutils/PxContactBuffer.h>
|
||||
#include <common/PxRenderOutput.h>
|
||||
#include <extensions/PxGjkQueryExt.h>
|
||||
#include <extensions/PxMassProperties.h>
|
||||
#include <PxImmediateMode.h>
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
using namespace Ext;
|
||||
#endif
|
||||
|
||||
static const PxU32 gCollisionShapeColor = PxU32(PxDebugColor::eARGB_MAGENTA);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const PxU32 MAX_TRIANGLES = 512;
|
||||
static const PxU32 MAX_TRIANGLE_CONTACTS = 6;
|
||||
const PxReal FACE_CONTACT_THRESHOLD = 0.99999f;
|
||||
|
||||
struct TrimeshContactFilter
|
||||
{
|
||||
PxU32 triCount;
|
||||
PxU32 triIndices[MAX_TRIANGLES];
|
||||
PxU32 triAdjacencies[MAX_TRIANGLES][3];
|
||||
PxU32 triContactCounts[MAX_TRIANGLES][2];
|
||||
PxContactPoint triContacts[MAX_TRIANGLES][MAX_TRIANGLE_CONTACTS];
|
||||
|
||||
TrimeshContactFilter() : triCount(0) {}
|
||||
|
||||
void addTriangleContacts(const PxContactPoint* points, PxU32 count, const PxU32 triIndex, const PxVec3 triVerts[3], const PxU32 triAdjacency[3])
|
||||
{
|
||||
if (triCount == MAX_TRIANGLES)
|
||||
return;
|
||||
|
||||
triIndices[triCount] = triIndex;
|
||||
PxU32& faceContactCount = triContactCounts[triCount][0];
|
||||
PxU32& edgeContactCount = triContactCounts[triCount][1];
|
||||
faceContactCount = edgeContactCount = 0;
|
||||
|
||||
for (PxU32 i = 0; i < 3; ++i)
|
||||
triAdjacencies[triCount][i] = triAdjacency[i];
|
||||
|
||||
PxVec3 triNormal = (triVerts[1] - triVerts[0]).cross(triVerts[2] - triVerts[0]).getNormalized();
|
||||
|
||||
for (PxU32 i = 0; i < count; ++i)
|
||||
{
|
||||
const PxContactPoint& point = points[i];
|
||||
bool faceContact = fabsf(point.normal.dot(triNormal)) > FACE_CONTACT_THRESHOLD;
|
||||
|
||||
if (faceContactCount + edgeContactCount < MAX_TRIANGLE_CONTACTS)
|
||||
{
|
||||
if (faceContact) triContacts[triCount][faceContactCount++] = point;
|
||||
else triContacts[triCount][MAX_TRIANGLE_CONTACTS - 1 - edgeContactCount++] = point;
|
||||
}
|
||||
}
|
||||
|
||||
++triCount;
|
||||
}
|
||||
|
||||
void writeToBuffer(PxContactBuffer& buffer)
|
||||
{
|
||||
for (PxU32 i = 0; i < triCount; ++i)
|
||||
{
|
||||
if (triContactCounts[i][1] > 0)
|
||||
{
|
||||
for (PxU32 j = 0; j < triCount; ++j)
|
||||
{
|
||||
if (triIndices[j] == triAdjacencies[i][0] || triIndices[j] == triAdjacencies[i][1] || triIndices[j] == triAdjacencies[i][2])
|
||||
{
|
||||
if (triContactCounts[j][0] > 0)
|
||||
{
|
||||
triContactCounts[i][1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PxU32 j = 0; j < triContactCounts[i][0]; ++j)
|
||||
buffer.contact(triContacts[i][j]);
|
||||
|
||||
for (PxU32 j = 0; j < triContactCounts[i][1]; ++j)
|
||||
buffer.contact(triContacts[i][MAX_TRIANGLE_CONTACTS - 1 - j]);
|
||||
}
|
||||
}
|
||||
|
||||
PX_NOCOPY(TrimeshContactFilter)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TriangleSupport : PxGjkQuery::Support
|
||||
{
|
||||
PxVec3 v0, v1, v2;
|
||||
PxReal margin;
|
||||
|
||||
TriangleSupport(const PxVec3& _v0, const PxVec3& _v1, const PxVec3& _v2, PxReal _margin)
|
||||
:
|
||||
v0(_v0), v1(_v1), v2(_v2), margin(_margin)
|
||||
{}
|
||||
|
||||
virtual PxReal getMargin() const
|
||||
{
|
||||
return margin;
|
||||
}
|
||||
virtual PxVec3 supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
float d0 = dir.dot(v0), d1 = dir.dot(v1), d2 = dir.dot(v2);
|
||||
return (d0 > d1 && d0 > d2) ? v0 : (d1 > d2) ? v1 : v2;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void drawArc(const PxVec3& center, const PxVec3& radius, const PxVec3& axis, PxReal angle, PxReal error, PxRenderOutput& out)
|
||||
{
|
||||
int sides = int(ceilf(angle / (2 * acosf(1.0f - error))));
|
||||
float step = angle / sides;
|
||||
out << PxRenderOutput::LINESTRIP;
|
||||
for (int i = 0; i <= sides; ++i)
|
||||
out << center + PxQuat(step * i, axis).rotate(radius);
|
||||
}
|
||||
static void drawCircle(const PxVec3& center, const PxVec3& radius, const PxVec3& axis, PxReal error, PxRenderOutput& out)
|
||||
{
|
||||
drawArc(center, radius, axis, PxTwoPi, error, out);
|
||||
}
|
||||
static void drawQuarterCircle(const PxVec3& center, const PxVec3& radius, const PxVec3& axis, PxReal error, PxRenderOutput& out)
|
||||
{
|
||||
drawArc(center, radius, axis, PxPiDivTwo, error, out);
|
||||
}
|
||||
static void drawLine(const PxVec3& s, const PxVec3& e, PxRenderOutput& out)
|
||||
{
|
||||
out << PxRenderOutput::LINES << s << e;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxBounds3 PxCustomGeometryExt::BaseConvexCallbacks::getLocalBounds(const PxGeometry&) const
|
||||
{
|
||||
const PxVec3 min(supportLocal(PxVec3(-1, 0, 0)).x, supportLocal(PxVec3(0, -1, 0)).y, supportLocal(PxVec3(0, 0, -1)).z);
|
||||
const PxVec3 max(supportLocal(PxVec3(1, 0, 0)).x, supportLocal(PxVec3(0, 1, 0)).y, supportLocal(PxVec3(0, 0, 1)).z);
|
||||
PxBounds3 bounds(min, max);
|
||||
bounds.fattenSafe(getMargin());
|
||||
return bounds;
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::BaseConvexCallbacks::generateContacts(const PxGeometry& geom0, const PxGeometry& geom1,
|
||||
const PxTransform& pose0, const PxTransform& pose1, const PxReal contactDistance, const PxReal meshContactMargin,
|
||||
const PxReal toleranceLength, PxContactBuffer& contactBuffer) const
|
||||
{
|
||||
struct ContactRecorder : immediate::PxContactRecorder
|
||||
{
|
||||
PxContactBuffer* contactBuffer;
|
||||
ContactRecorder(PxContactBuffer& _contactBuffer) : contactBuffer(&_contactBuffer) {}
|
||||
virtual bool recordContacts(const PxContactPoint* contactPoints, PxU32 nbContacts, PxU32 /*index*/)
|
||||
{
|
||||
for (PxU32 i = 0; i < nbContacts; ++i)
|
||||
contactBuffer->contact(contactPoints[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
contactRecorder(contactBuffer);
|
||||
|
||||
PxCache contactCache;
|
||||
|
||||
struct ContactCacheAllocator : PxCacheAllocator
|
||||
{
|
||||
PxU8 buffer[1024];
|
||||
ContactCacheAllocator() { PxMemSet(buffer, 0, sizeof(buffer)); }
|
||||
virtual PxU8* allocateCacheData(const PxU32 /*byteSize*/) { return reinterpret_cast<PxU8*>(size_t(buffer + 0xf) & ~0xf); }
|
||||
}
|
||||
contactCacheAllocator;
|
||||
|
||||
const PxTransform identityPose(PxIdentity);
|
||||
|
||||
switch (geom1.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
case PxGeometryType::eCAPSULE:
|
||||
case PxGeometryType::eBOX:
|
||||
case PxGeometryType::eCONVEXCORE:
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
PxGjkQueryExt::ConvexGeomSupport geomSupport(geom1);
|
||||
if (PxGjkQueryExt::generateContacts(*this, geomSupport, pose0, pose1, contactDistance, toleranceLength, contactBuffer))
|
||||
{
|
||||
PxGeometryHolder substituteGeom; PxTransform preTransform;
|
||||
if (useSubstituteGeometry(substituteGeom, preTransform, contactBuffer.contacts[contactBuffer.count - 1], pose0))
|
||||
{
|
||||
contactBuffer.count--;
|
||||
const PxGeometry* pGeom0 = &substituteGeom.any();
|
||||
const PxGeometry* pGeom1 = &geom1;
|
||||
// PT:: tag: scalar transform*transform
|
||||
PxTransform pose = pose0.transform(preTransform);
|
||||
immediate::PxGenerateContacts(&pGeom0, &pGeom1, &pose, &pose1, &contactCache, 1, contactRecorder,
|
||||
contactDistance, meshContactMargin, toleranceLength, contactCacheAllocator);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::ePLANE:
|
||||
{
|
||||
const PxPlane plane = PxPlane(1.0f, 0.0f, 0.0f, 0.0f).transform(pose1);
|
||||
const PxPlane localPlane = plane.inverseTransform(pose0);
|
||||
const PxVec3 point = supportLocal(-localPlane.n) - localPlane.n * margin;
|
||||
const float dist = localPlane.distance(point);
|
||||
if (dist < contactDistance)
|
||||
{
|
||||
const PxVec3 n = localPlane.n;
|
||||
const PxVec3 p = point - n * dist * 0.5f;
|
||||
PxContactPoint contact;
|
||||
contact.point = pose0.transform(p);
|
||||
contact.normal = pose0.rotate(n);
|
||||
contact.separation = dist;
|
||||
contactBuffer.contact(contact);
|
||||
PxGeometryHolder substituteGeom; PxTransform preTransform;
|
||||
if (useSubstituteGeometry(substituteGeom, preTransform, contactBuffer.contacts[contactBuffer.count - 1], pose0))
|
||||
{
|
||||
contactBuffer.count--;
|
||||
const PxGeometry* pGeom0 = &substituteGeom.any();
|
||||
const PxGeometry* pGeom1 = &geom1;
|
||||
// PT:: tag: scalar transform*transform
|
||||
PxTransform pose = pose0.transform(preTransform);
|
||||
immediate::PxGenerateContacts(&pGeom0, &pGeom1, &pose, &pose1, &contactCache, 1, contactRecorder,
|
||||
contactDistance, meshContactMargin, toleranceLength, contactCacheAllocator);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
case PxGeometryType::eHEIGHTFIELD:
|
||||
{
|
||||
// As a triangle has no thickness, we need to choose some collision margin - the distance
|
||||
// considered a touching contact. I set it as 1% of the custom shape minimum dimension.
|
||||
PxReal meshMargin = getLocalBounds(geom0).getDimensions().minElement() * 0.01f;
|
||||
TrimeshContactFilter contactFilter;
|
||||
bool hasAdjacency = (geom1.getType() != PxGeometryType::eTRIANGLEMESH || (static_cast<const PxTriangleMeshGeometry&>(geom1).triangleMesh->getTriangleMeshFlags() & PxTriangleMeshFlag::eADJACENCY_INFO));
|
||||
PxBoxGeometry boxGeom(getLocalBounds(geom0).getExtents() + PxVec3(contactDistance + meshMargin));
|
||||
PxU32 triangles[MAX_TRIANGLES];
|
||||
bool overflow = false;
|
||||
PxU32 triangleCount = (geom1.getType() == PxGeometryType::eTRIANGLEMESH) ?
|
||||
PxMeshQuery::findOverlapTriangleMesh(boxGeom, pose0, static_cast<const PxTriangleMeshGeometry&>(geom1), pose1, triangles, MAX_TRIANGLES, 0, overflow) :
|
||||
PxMeshQuery::findOverlapHeightField(boxGeom, pose0, static_cast<const PxHeightFieldGeometry&>(geom1), pose1, triangles, MAX_TRIANGLES, 0, overflow);
|
||||
if (overflow)
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_INFO, PX_FL, "PxCustomGeometryExt::BaseConvexCallbacks::generateContacts() Too many triangles.\n");
|
||||
for (PxU32 i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
PxTriangle tri; PxU32 adjacent[3];
|
||||
if (geom1.getType() == PxGeometryType::eTRIANGLEMESH)
|
||||
PxMeshQuery::getTriangle(static_cast<const PxTriangleMeshGeometry&>(geom1), pose1, triangles[i], tri, NULL, hasAdjacency ? adjacent : NULL);
|
||||
else
|
||||
PxMeshQuery::getTriangle(static_cast<const PxHeightFieldGeometry&>(geom1), pose1, triangles[i], tri, NULL, adjacent);
|
||||
TriangleSupport triSupport(tri.verts[0], tri.verts[1], tri.verts[2], meshMargin);
|
||||
if (PxGjkQueryExt::generateContacts(*this, triSupport, pose0, identityPose, contactDistance, toleranceLength, contactBuffer))
|
||||
{
|
||||
contactBuffer.contacts[contactBuffer.count - 1].internalFaceIndex1 = triangles[i];
|
||||
PxGeometryHolder substituteGeom; PxTransform preTransform;
|
||||
if (useSubstituteGeometry(substituteGeom, preTransform, contactBuffer.contacts[contactBuffer.count - 1], pose0))
|
||||
{
|
||||
contactBuffer.count--;
|
||||
const PxGeometry& geom = substituteGeom.any();
|
||||
// PT:: tag: scalar transform*transform
|
||||
PxTransform pose = pose0.transform(preTransform);
|
||||
PxGeometryQuery::generateTriangleContacts(geom, pose, tri.verts, triangles[i], contactDistance, meshMargin, toleranceLength, contactBuffer);
|
||||
}
|
||||
}
|
||||
if (hasAdjacency)
|
||||
{
|
||||
contactFilter.addTriangleContacts(contactBuffer.contacts, contactBuffer.count, triangles[i], tri.verts, adjacent);
|
||||
contactBuffer.count = 0;
|
||||
}
|
||||
}
|
||||
if (hasAdjacency)
|
||||
contactFilter.writeToBuffer(contactBuffer);
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eCUSTOM:
|
||||
{
|
||||
const PxCustomGeometry& customGeom1 = static_cast<const PxCustomGeometry&>(geom1);
|
||||
if (customGeom1.getCustomType() == CylinderCallbacks::TYPE() ||
|
||||
customGeom1.getCustomType() == ConeCallbacks::TYPE()) // It's a CustomConvex
|
||||
{
|
||||
BaseConvexCallbacks* custom1 = static_cast<BaseConvexCallbacks*>(customGeom1.callbacks);
|
||||
if (PxGjkQueryExt::generateContacts(*this, *custom1, pose0, pose1, contactDistance, toleranceLength, contactBuffer))
|
||||
{
|
||||
PxGeometryHolder substituteGeom; PxTransform preTransform;
|
||||
if (useSubstituteGeometry(substituteGeom, preTransform, contactBuffer.contacts[contactBuffer.count - 1], pose0))
|
||||
{
|
||||
contactBuffer.count--;
|
||||
|
||||
PxU32 oldCount = contactBuffer.count;
|
||||
|
||||
const PxGeometry* pGeom0 = &substituteGeom.any();
|
||||
const PxGeometry* pGeom1 = &geom1;
|
||||
// PT:: tag: scalar transform*transform
|
||||
PxTransform pose = pose0.transform(preTransform);
|
||||
immediate::PxGenerateContacts(&pGeom1, &pGeom0, &pose1, &pose, &contactCache, 1, contactRecorder,
|
||||
contactDistance, meshContactMargin, toleranceLength, contactCacheAllocator);
|
||||
|
||||
for (int i = oldCount; i < int(contactBuffer.count); ++i)
|
||||
contactBuffer.contacts[i].normal = -contactBuffer.contacts[i].normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxGeometry* pGeom0 = &geom0;
|
||||
const PxGeometry* pGeom1 = &geom1;
|
||||
immediate::PxGenerateContacts(&pGeom1, &pGeom0, &pose1, &pose0, &contactCache, 1, contactRecorder,
|
||||
contactDistance, meshContactMargin, toleranceLength, contactCacheAllocator);
|
||||
|
||||
for (int i = 0; i < int(contactBuffer.count); ++i)
|
||||
contactBuffer.contacts[i].normal = -contactBuffer.contacts[i].normal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return contactBuffer.count > 0;
|
||||
}
|
||||
|
||||
PxU32 PxCustomGeometryExt::BaseConvexCallbacks::raycast(const PxVec3& origin, const PxVec3& unitDir, const PxGeometry& geom, const PxTransform& pose,
|
||||
PxReal maxDist, PxHitFlags /*hitFlags*/, PxU32 /*maxHits*/, PxGeomRaycastHit* rayHits, PxU32 /*stride*/, PxRaycastThreadContext*) const
|
||||
{
|
||||
// When FLT_MAX is used as maxDist, it works bad with GJK algorithm.
|
||||
// Here I compute the maximum needed distance (wiseDist) as the diagonal
|
||||
// of the bounding box of both the geometry and the ray origin.
|
||||
PxBounds3 bounds = PxBounds3::transformFast(pose, getLocalBounds(geom));
|
||||
bounds.include(origin);
|
||||
PxReal wiseDist = PxMin(maxDist, bounds.getDimensions().magnitude());
|
||||
PxReal t;
|
||||
PxVec3 n, p;
|
||||
if (PxGjkQuery::raycast(*this, pose, origin, unitDir, wiseDist, t, n, p))
|
||||
{
|
||||
PxGeomRaycastHit& hit = *rayHits;
|
||||
hit.distance = t;
|
||||
hit.position = p;
|
||||
hit.normal = n;
|
||||
hit.flags |= PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::BaseConvexCallbacks::overlap(const PxGeometry& /*geom0*/, const PxTransform& pose0, const PxGeometry& geom1, const PxTransform& pose1, PxOverlapThreadContext*) const
|
||||
{
|
||||
switch (geom1.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
case PxGeometryType::eCAPSULE:
|
||||
case PxGeometryType::eBOX:
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
PxGjkQueryExt::ConvexGeomSupport geomSupport(geom1);
|
||||
if (PxGjkQuery::overlap(*this, geomSupport, pose0, pose1))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::BaseConvexCallbacks::sweep(const PxVec3& unitDir, const PxReal maxDist,
|
||||
const PxGeometry& geom0, const PxTransform& pose0, const PxGeometry& geom1, const PxTransform& pose1,
|
||||
PxGeomSweepHit& sweepHit, PxHitFlags /*hitFlags*/, const PxReal inflation, PxSweepThreadContext*) const
|
||||
{
|
||||
PxBounds3 bounds0 = PxBounds3::transformFast(pose0, getLocalBounds(geom0));
|
||||
|
||||
switch (geom1.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
case PxGeometryType::eCAPSULE:
|
||||
case PxGeometryType::eBOX:
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
// See comment in BaseConvexCallbacks::raycast
|
||||
PxBounds3 bounds; PxGeometryQuery::computeGeomBounds(bounds, geom1, pose1, 0, inflation);
|
||||
bounds.include(bounds0);
|
||||
PxReal wiseDist = PxMin(maxDist, bounds.getDimensions().magnitude());
|
||||
PxGjkQueryExt::ConvexGeomSupport geomSupport(geom1, inflation);
|
||||
PxReal t;
|
||||
PxVec3 n, p;
|
||||
if (PxGjkQuery::sweep(*this, geomSupport, pose0, pose1, unitDir, wiseDist, t, n, p))
|
||||
{
|
||||
sweepHit.distance = t;
|
||||
sweepHit.position = p;
|
||||
sweepHit.normal = n;
|
||||
sweepHit.flags = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// sweep against triangle meshes and height fields for CCD support
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
case PxGeometryType::eHEIGHTFIELD:
|
||||
{
|
||||
PxReal radius = getLocalBounds(geom0).getExtents().magnitude();
|
||||
PxGeometryHolder sweepGeom = PxSphereGeometry(radius + inflation);
|
||||
PxTransform sweepGeomPose = pose0;
|
||||
// for some reason, capsule can't have near zero height
|
||||
// [assert @ source\geomutils\src\intersection\GuIntersectionCapsuleTriangle.cpp(37)]
|
||||
// so I use capsule only if height is larger than 0.1% of radius
|
||||
if (maxDist > radius * 0.001f)
|
||||
{
|
||||
sweepGeom = PxCapsuleGeometry(radius + inflation, maxDist * 0.5f);
|
||||
sweepGeomPose = PxTransform(pose0.p - unitDir * maxDist * 0.5f, PxShortestRotation(PxVec3(1, 0, 0), unitDir));
|
||||
}
|
||||
PxU32 triangles[MAX_TRIANGLES];
|
||||
bool overflow = false;
|
||||
PxU32 triangleCount = (geom1.getType() == PxGeometryType::eTRIANGLEMESH) ?
|
||||
PxMeshQuery::findOverlapTriangleMesh(sweepGeom.any(), sweepGeomPose, static_cast<const PxTriangleMeshGeometry&>(geom1), pose1, triangles, MAX_TRIANGLES, 0, overflow) :
|
||||
PxMeshQuery::findOverlapHeightField(sweepGeom.any(), sweepGeomPose, static_cast<const PxHeightFieldGeometry&>(geom1), pose1, triangles, MAX_TRIANGLES, 0, overflow);
|
||||
if(overflow)
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_INFO, PX_FL, "PxCustomGeometryExt::BaseConvexCallbacks::sweep() Too many triangles.\n");
|
||||
sweepHit.distance = PX_MAX_F32;
|
||||
const PxTransform identityPose(PxIdentity);
|
||||
for (PxU32 i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
PxTriangle tri;
|
||||
if (geom1.getType() == PxGeometryType::eTRIANGLEMESH)
|
||||
PxMeshQuery::getTriangle(static_cast<const PxTriangleMeshGeometry&>(geom1), pose1, triangles[i], tri);
|
||||
else
|
||||
PxMeshQuery::getTriangle(static_cast<const PxHeightFieldGeometry&>(geom1), pose1, triangles[i], tri);
|
||||
TriangleSupport triSupport(tri.verts[0], tri.verts[1], tri.verts[2], inflation);
|
||||
PxBounds3 bounds = bounds0;
|
||||
for (PxU32 j = 0; j < 3; ++j)
|
||||
bounds.include(tri.verts[j]);
|
||||
bounds.fattenFast(inflation);
|
||||
// See comment in BaseConvexCallbacks::raycast
|
||||
PxReal wiseDist = PxMin(maxDist, bounds.getDimensions().magnitude());
|
||||
PxReal t;
|
||||
PxVec3 n, p;
|
||||
if (PxGjkQuery::sweep(*this, triSupport, pose0, identityPose, unitDir, wiseDist, t, n, p))
|
||||
{
|
||||
if (sweepHit.distance > t)
|
||||
{
|
||||
sweepHit.faceIndex = triangles[i];
|
||||
sweepHit.distance = t;
|
||||
sweepHit.position = p;
|
||||
sweepHit.normal = n;
|
||||
sweepHit.flags = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eFACE_INDEX;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sweepHit.distance < PX_MAX_F32)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::BaseConvexCallbacks::usePersistentContactManifold(const PxGeometry& /*geometry*/, PxReal& breakingThreshold) const
|
||||
{
|
||||
// Even if we don't use persistent manifold, we still need to set proper breakingThreshold
|
||||
// because the other geometry still can force the PCM usage. FLT_EPSILON ensures that
|
||||
// the contacts will be discarded and recomputed every frame if actor moves.
|
||||
breakingThreshold = FLT_EPSILON;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::BaseConvexCallbacks::setMargin(float m)
|
||||
{
|
||||
margin = m;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtBaseConvexCallbacks, margin, *this, margin);
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_CUSTOM_GEOMETRY_TYPE(PxCustomGeometryExt::CylinderCallbacks)
|
||||
|
||||
PxCustomGeometryExt::CylinderCallbacks::CylinderCallbacks(float _height, float _radius, int _axis, float _margin)
|
||||
:
|
||||
BaseConvexCallbacks(_margin), height(_height), radius(_radius), axis(_axis)
|
||||
{
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, *this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtBaseConvexCallbacks, margin, *static_cast<BaseConvexCallbacks*>(this), margin);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, height, *this, height);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, radius, *this, radius);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, axis, *this, axis);
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::CylinderCallbacks::setHeight(float h)
|
||||
{
|
||||
height = h;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, height, *this, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::CylinderCallbacks::setRadius(float r)
|
||||
{
|
||||
radius = r;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, radius, *this, radius);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::CylinderCallbacks::setAxis(int a)
|
||||
{
|
||||
axis = a;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtCylinderCallbacks, axis, *this, axis);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::CylinderCallbacks::visualize(const PxGeometry&, PxRenderOutput& out, const PxTransform& transform, const PxBounds3&) const
|
||||
{
|
||||
const float ERR = 0.001f;
|
||||
|
||||
out << gCollisionShapeColor;
|
||||
out << transform;
|
||||
|
||||
int axis1 = (axis + 1) % 3;
|
||||
int axis2 = (axis + 2) % 3;
|
||||
|
||||
PxVec3 zr(PxZero), rd(PxZero), ax(PxZero), ax1(PxZero), ax2(PxZero), r0(PxZero), r1(PxZero);
|
||||
ax[axis] = ax1[axis1] = ax2[axis2] = 1.0f;
|
||||
r0[axis1] = r1[axis2] = radius;
|
||||
|
||||
rd[axis1] = radius;
|
||||
rd[axis] = -(height * 0.5f + margin);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
rd[axis] = (height * 0.5f + margin);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
rd[axis1] = radius + margin;
|
||||
rd[axis] = -(height * 0.5f);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
rd[axis] = (height * 0.5f);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
|
||||
drawLine(-ax * height * 0.5f + ax1 * (radius + margin), ax * height * 0.5f + ax1 * (radius + margin), out);
|
||||
drawLine(-ax * height * 0.5f - ax1 * (radius + margin), ax * height * 0.5f - ax1 * (radius + margin), out);
|
||||
drawLine(-ax * height * 0.5f + ax2 * (radius + margin), ax * height * 0.5f + ax2 * (radius + margin), out);
|
||||
drawLine(-ax * height * 0.5f - ax2 * (radius + margin), ax * height * 0.5f - ax2 * (radius + margin), out);
|
||||
|
||||
drawQuarterCircle(-ax * height * 0.5f + ax1 * radius, -ax * margin, -ax2, ERR, out);
|
||||
drawQuarterCircle(-ax * height * 0.5f - ax1 * radius, -ax * margin, ax2, ERR, out);
|
||||
drawQuarterCircle(-ax * height * 0.5f + ax2 * radius, -ax * margin, ax1, ERR, out);
|
||||
drawQuarterCircle(-ax * height * 0.5f - ax2 * radius, -ax * margin, -ax1, ERR, out);
|
||||
|
||||
drawQuarterCircle(ax * height * 0.5f + ax1 * radius, ax * margin, ax2, ERR, out);
|
||||
drawQuarterCircle(ax * height * 0.5f - ax1 * radius, ax * margin, -ax2, ERR, out);
|
||||
drawQuarterCircle(ax * height * 0.5f + ax2 * radius, ax * margin, -ax1, ERR, out);
|
||||
drawQuarterCircle(ax * height * 0.5f - ax2 * radius, ax * margin, ax1, ERR, out);
|
||||
}
|
||||
|
||||
PxVec3 PxCustomGeometryExt::CylinderCallbacks::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
float halfHeight = height * 0.5f;
|
||||
PxVec3 d = dir.getNormalized();
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case 0: // X
|
||||
{
|
||||
if (PxSign2(d.x) != 0 && PxSign2(d.y) == 0 && PxSign2(d.z) == 0) return PxVec3(PxSign2(d.x) * halfHeight, 0, 0);
|
||||
return PxVec3(PxSign2(d.x) * halfHeight, 0, 0) + PxVec3(0, d.y, d.z).getNormalized() * radius;
|
||||
}
|
||||
case 1: // Y
|
||||
{
|
||||
if (PxSign2(d.x) == 0 && PxSign2(d.y) != 0 && PxSign2(d.z) == 0) return PxVec3(0, PxSign2(d.y) * halfHeight, 0);
|
||||
return PxVec3(0, PxSign2(d.y) * halfHeight, 0) + PxVec3(d.x, 0, d.z).getNormalized() * radius;
|
||||
}
|
||||
case 2: // Z
|
||||
{
|
||||
if (PxSign2(d.x) == 0 && PxSign2(d.y) == 0 && PxSign2(d.z) != 0) return PxVec3(0, 0, PxSign2(d.z) * halfHeight);
|
||||
return PxVec3(0, 0, PxSign2(d.z) * halfHeight) + PxVec3(d.x, d.y, 0).getNormalized() * radius;
|
||||
}
|
||||
}
|
||||
|
||||
return PxVec3(0);
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::CylinderCallbacks::computeMassProperties(const PxGeometry& /*geometry*/, PxMassProperties& massProperties) const
|
||||
{
|
||||
if (margin == 0)
|
||||
{
|
||||
PxMassProperties& mass = massProperties;
|
||||
float R = radius, H = height;
|
||||
|
||||
mass.mass = PxPi * R * R * H;
|
||||
mass.inertiaTensor = PxMat33(PxZero);
|
||||
mass.centerOfMass = PxVec3(PxZero);
|
||||
|
||||
float I0 = mass.mass * R * R / 2.0f;
|
||||
float I1 = mass.mass * (3 * R * R + H * H) / 12.0f;
|
||||
|
||||
mass.inertiaTensor[axis][axis] = I0;
|
||||
mass.inertiaTensor[(axis + 1) % 3][(axis + 1) % 3] = mass.inertiaTensor[(axis + 2) % 3][(axis + 2) % 3] = I1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int SLICE_COUNT = 32;
|
||||
PxMassProperties sliceMasses[SLICE_COUNT];
|
||||
PxTransform slicePoses[SLICE_COUNT];
|
||||
float sliceHeight = height / SLICE_COUNT;
|
||||
|
||||
for (int i = 0; i < SLICE_COUNT; ++i)
|
||||
{
|
||||
float t = -height * 0.5f + i * sliceHeight + sliceHeight * 0.5f;
|
||||
float R = getRadiusAtHeight(t), H = sliceHeight;
|
||||
|
||||
PxMassProperties mass;
|
||||
mass.mass = PxPi * R * R * H;
|
||||
mass.inertiaTensor = PxMat33(PxZero);
|
||||
mass.centerOfMass = PxVec3(PxZero);
|
||||
|
||||
float I0 = mass.mass * R * R / 2.0f;
|
||||
float I1 = mass.mass * (3 * R * R + H * H) / 12.0f;
|
||||
|
||||
mass.inertiaTensor[axis][axis] = I0;
|
||||
mass.inertiaTensor[(axis + 1) % 3][(axis + 1) % 3] = mass.inertiaTensor[(axis + 2) % 3][(axis + 2) % 3] = I1;
|
||||
mass.centerOfMass[axis] = t;
|
||||
|
||||
sliceMasses[i] = mass;
|
||||
slicePoses[i] = PxTransform(PxIdentity);
|
||||
}
|
||||
|
||||
massProperties = PxMassProperties::sum(sliceMasses, slicePoses, SLICE_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::CylinderCallbacks::useSubstituteGeometry(PxGeometryHolder& geom, PxTransform& preTransform, const PxContactPoint& p, const PxTransform& pose0) const
|
||||
{
|
||||
// here I check if we contact with the cylender bases or the lateral surface
|
||||
// where more than 1 contact point can be generated.
|
||||
PxVec3 locN = pose0.rotateInv(p.normal);
|
||||
float nAng = acosf(PxClamp(-locN[axis], -1.0f, 1.0f));
|
||||
float epsAng = PxPi / 36.0f; // 5 degrees
|
||||
if (nAng < epsAng || nAng > PxPi - epsAng)
|
||||
{
|
||||
// if we contact with the bases
|
||||
// make the substitute geometry a box and rotate it so one of
|
||||
// the corners matches the contact point
|
||||
PxVec3 halfSize;
|
||||
halfSize[axis] = height * 0.5f + margin;
|
||||
halfSize[(axis + 1) % 3] = halfSize[(axis + 2) % 3] = radius / sqrtf(2.0f);
|
||||
geom = PxBoxGeometry(halfSize);
|
||||
PxVec3 axisDir(PxZero); axisDir[axis] = 1.0f;
|
||||
PxVec3 locP = pose0.transformInv(p.point);
|
||||
float s1 = locP[(axis + 1) % 3], s2 = locP[(axis + 2) % 3];
|
||||
float ang = ((s1 * s1) + (s2 * s2) > 1e-3f) ? atan2f(s2, s1) : 0;
|
||||
preTransform = PxTransform(PxQuat(ang + PxPi * 0.25f, axisDir));
|
||||
return true;
|
||||
}
|
||||
else if (nAng > PxPiDivTwo - epsAng && nAng < PxPiDivTwo + epsAng)
|
||||
{
|
||||
// if it's the lateral surface
|
||||
// make the substitute geometry a capsule and rotate it so it aligns
|
||||
// with the cylinder surface
|
||||
geom = PxCapsuleGeometry(radius + margin, height * 0.5f);
|
||||
switch (axis)
|
||||
{
|
||||
case 0: preTransform = PxTransform(PxIdentity); break;
|
||||
case 1: preTransform = PxTransform(PxQuat(PxPi * 0.5f, PxVec3(0, 0, 1))); break;
|
||||
case 2: preTransform = PxTransform(PxQuat(PxPi * 0.5f, PxVec3(0, 1, 0))); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float PxCustomGeometryExt::CylinderCallbacks::getRadiusAtHeight(float h) const
|
||||
{
|
||||
if (h >= -height * 0.5f && h <= height * 0.5f)
|
||||
return radius + margin;
|
||||
|
||||
if (h < -height * 0.5f)
|
||||
{
|
||||
float a = -h - height * 0.5f;
|
||||
return radius + sqrtf(margin * margin - a * a);
|
||||
}
|
||||
|
||||
if (h > height * 0.5f)
|
||||
{
|
||||
float a = h - height * 0.5f;
|
||||
return radius + sqrtf(margin * margin - a * a);
|
||||
}
|
||||
|
||||
PX_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_CUSTOM_GEOMETRY_TYPE(PxCustomGeometryExt::ConeCallbacks)
|
||||
|
||||
PxCustomGeometryExt::ConeCallbacks::ConeCallbacks(float _height, float _radius, int _axis, float _margin)
|
||||
:
|
||||
BaseConvexCallbacks(_margin), height(_height), radius(_radius), axis(_axis)
|
||||
{
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, *this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtBaseConvexCallbacks, margin, *static_cast<BaseConvexCallbacks*>(this), margin);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, height, *this, height);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, radius, *this, radius);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, axis, *this, axis);
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::ConeCallbacks::setHeight(float h)
|
||||
{
|
||||
height = h;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, height, *this, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::ConeCallbacks::setRadius(float r)
|
||||
{
|
||||
radius = r;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, radius, *this, radius);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::ConeCallbacks::setAxis(int a)
|
||||
{
|
||||
axis = a;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxCustomGeometryExtConeCallbacks, axis, *this, axis);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::ConeCallbacks::visualize(const PxGeometry&, PxRenderOutput& out, const PxTransform& transform, const PxBounds3&) const
|
||||
{
|
||||
const float ERR = 0.001f;
|
||||
|
||||
out << gCollisionShapeColor;
|
||||
out << transform;
|
||||
|
||||
int axis1 = (axis + 1) % 3;
|
||||
int axis2 = (axis + 2) % 3;
|
||||
|
||||
PxVec3 zr(PxZero), rd(PxZero), ax(PxZero), ax1(PxZero), ax2(PxZero), r0(PxZero), r1(PxZero);
|
||||
ax[axis] = ax1[axis1] = ax2[axis2] = 1.0f;
|
||||
r0[axis1] = r1[axis2] = radius;
|
||||
|
||||
float ang = atan2f(radius, height);
|
||||
float aSin = sinf(ang);
|
||||
|
||||
rd[axis1] = radius;
|
||||
rd[axis] = -(height * 0.5f + margin);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
rd[axis] = -(height * 0.5f) + margin * aSin;
|
||||
rd[axis1] = getRadiusAtHeight(rd[axis]);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
rd[axis] = height * 0.5f + margin * aSin;
|
||||
rd[axis1] = getRadiusAtHeight(rd[axis]);
|
||||
drawCircle(zr, rd, ax, ERR, out);
|
||||
|
||||
float h0 = -height * 0.5f + margin * aSin, h1 = height * 0.5f + margin * aSin;
|
||||
float s0 = getRadiusAtHeight(h0), s1 = getRadiusAtHeight(h1);
|
||||
drawLine(ax * h0 + ax1 * s0, ax * h1 + ax1 * s1, out);
|
||||
drawLine(ax * h0 - ax1 * s0, ax * h1 - ax1 * s1, out);
|
||||
drawLine(ax * h0 + ax2 * s0, ax * h1 + ax2 * s1, out);
|
||||
drawLine(ax * h0 - ax2 * s0, ax * h1 - ax2 * s1, out);
|
||||
|
||||
drawArc(-ax * height * 0.5f + ax1 * radius, -ax * margin, -ax2, PxPiDivTwo + ang, ERR, out);
|
||||
drawArc(-ax * height * 0.5f - ax1 * radius, -ax * margin, ax2, PxPiDivTwo + ang, ERR, out);
|
||||
drawArc(-ax * height * 0.5f + ax2 * radius, -ax * margin, ax1, PxPiDivTwo + ang, ERR, out);
|
||||
drawArc(-ax * height * 0.5f - ax2 * radius, -ax * margin, -ax1, PxPiDivTwo + ang, ERR, out);
|
||||
|
||||
drawArc(ax * height * 0.5f, ax * margin, ax2, PxPiDivTwo - ang, ERR, out);
|
||||
drawArc(ax * height * 0.5f, ax * margin, -ax2, PxPiDivTwo - ang, ERR, out);
|
||||
drawArc(ax * height * 0.5f, ax * margin, -ax1, PxPiDivTwo - ang, ERR, out);
|
||||
drawArc(ax * height * 0.5f, ax * margin, ax1, PxPiDivTwo - ang, ERR, out);
|
||||
}
|
||||
|
||||
PxVec3 PxCustomGeometryExt::ConeCallbacks::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
float halfHeight = height * 0.5f;
|
||||
float cosAlph = radius / sqrtf(height * height + radius * radius);
|
||||
PxVec3 d = dir.getNormalized();
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case 0: // X
|
||||
{
|
||||
if (d.x > cosAlph || (PxSign2(d.x) != 0 && PxSign2(d.y) == 0 && PxSign2(d.z) == 0)) return PxVec3(PxSign2(d.x) * halfHeight, 0, 0);
|
||||
return PxVec3(-halfHeight, 0, 0) + PxVec3(0, d.y, d.z).getNormalized() * radius;
|
||||
}
|
||||
case 1: // Y
|
||||
{
|
||||
if (d.y > cosAlph || (PxSign2(d.y) != 0 && PxSign2(d.x) == 0 && PxSign2(d.z) == 0)) return PxVec3(0, PxSign2(d.y) * halfHeight, 0);
|
||||
return PxVec3(0, -halfHeight, 0) + PxVec3(d.x, 0, d.z).getNormalized() * radius;
|
||||
}
|
||||
case 2: // Z
|
||||
{
|
||||
if (d.z > cosAlph || (PxSign2(d.z) != 0 && PxSign2(d.x) == 0 && PxSign2(d.y) == 0)) return PxVec3(0, 0, PxSign2(d.z) * halfHeight);
|
||||
return PxVec3(0, 0, -halfHeight) + PxVec3(d.x, d.y, 0).getNormalized() * radius;
|
||||
}
|
||||
}
|
||||
|
||||
return PxVec3(0);
|
||||
}
|
||||
|
||||
void PxCustomGeometryExt::ConeCallbacks::computeMassProperties(const PxGeometry& /*geometry*/, PxMassProperties& massProperties) const
|
||||
{
|
||||
if (margin == 0)
|
||||
{
|
||||
PxMassProperties& mass = massProperties;
|
||||
|
||||
float H = height, R = radius;
|
||||
|
||||
mass.mass = PxPi * R * R * H / 3.0f;
|
||||
mass.inertiaTensor = PxMat33(PxZero);
|
||||
mass.centerOfMass = PxVec3(PxZero);
|
||||
|
||||
float I0 = mass.mass * R * R * 3.0f / 10.0f;
|
||||
float I1 = mass.mass * (R * R * 3.0f / 20.0f + H * H * 3.0f / 80.0f);
|
||||
|
||||
mass.inertiaTensor[axis][axis] = I0;
|
||||
mass.inertiaTensor[(axis + 1) % 3][(axis + 1) % 3] = mass.inertiaTensor[(axis + 2) % 3][(axis + 2) % 3] = I1;
|
||||
|
||||
mass.centerOfMass[axis] = -H / 4.0f;
|
||||
|
||||
mass.inertiaTensor = PxMassProperties::translateInertia(mass.inertiaTensor, mass.mass, mass.centerOfMass);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int SLICE_COUNT = 32;
|
||||
PxMassProperties sliceMasses[SLICE_COUNT];
|
||||
PxTransform slicePoses[SLICE_COUNT];
|
||||
float sliceHeight = height / SLICE_COUNT;
|
||||
|
||||
for (int i = 0; i < SLICE_COUNT; ++i)
|
||||
{
|
||||
float t = -height * 0.5f + i * sliceHeight + sliceHeight * 0.5f;
|
||||
float R = getRadiusAtHeight(t), H = sliceHeight;
|
||||
|
||||
PxMassProperties mass;
|
||||
mass.mass = PxPi * R * R * H;
|
||||
mass.inertiaTensor = PxMat33(PxZero);
|
||||
mass.centerOfMass = PxVec3(PxZero);
|
||||
|
||||
float I0 = mass.mass * R * R / 2.0f;
|
||||
float I1 = mass.mass * (3 * R * R + H * H) / 12.0f;
|
||||
|
||||
mass.inertiaTensor[axis][axis] = I0;
|
||||
mass.inertiaTensor[(axis + 1) % 3][(axis + 1) % 3] = mass.inertiaTensor[(axis + 2) % 3][(axis + 2) % 3] = I1;
|
||||
mass.centerOfMass[axis] = t;
|
||||
|
||||
sliceMasses[i] = mass;
|
||||
slicePoses[i] = PxTransform(PxIdentity);
|
||||
}
|
||||
|
||||
massProperties = PxMassProperties::sum(sliceMasses, slicePoses, SLICE_COUNT);
|
||||
|
||||
massProperties.inertiaTensor = PxMassProperties::translateInertia(massProperties.inertiaTensor, massProperties.mass, massProperties.centerOfMass);
|
||||
}
|
||||
}
|
||||
|
||||
bool PxCustomGeometryExt::ConeCallbacks::useSubstituteGeometry(PxGeometryHolder& geom, PxTransform& preTransform, const PxContactPoint& p, const PxTransform& pose0) const
|
||||
{
|
||||
// here I check if we contact with the cone base or the lateral surface
|
||||
// where more than 1 contact point can be generated.
|
||||
PxVec3 locN = pose0.rotateInv(p.normal);
|
||||
float nAng = acosf(PxClamp(-locN[axis], -1.0f, 1.0f));
|
||||
float epsAng = PxPi / 36.0f; // 5 degrees
|
||||
float coneAng = atan2f(radius, height);
|
||||
if (nAng > PxPi - epsAng)
|
||||
{
|
||||
// if we contact with the base
|
||||
// make the substitute geometry a box and rotate it so one of
|
||||
// the corners matches the contact point
|
||||
PxVec3 halfSize;
|
||||
halfSize[axis] = height * 0.5f + margin;
|
||||
halfSize[(axis + 1) % 3] = halfSize[(axis + 2) % 3] = radius / sqrtf(2.0f);
|
||||
geom = PxBoxGeometry(halfSize);
|
||||
PxVec3 axisDir(PxZero); axisDir[axis] = 1.0f;
|
||||
PxVec3 locP = pose0.transformInv(p.point);
|
||||
float s1 = locP[(axis + 1) % 3], s2 = locP[(axis + 2) % 3];
|
||||
float ang = ((s1 * s1) + (s2 * s2) > 1e-3f) ? atan2f(s2, s1) : 0;
|
||||
preTransform = PxTransform(PxQuat(ang + PxPi * 0.25f, axisDir));
|
||||
return true;
|
||||
}
|
||||
else if (nAng > PxPiDivTwo - coneAng - epsAng && nAng < PxPiDivTwo - coneAng + epsAng)
|
||||
{
|
||||
// if it's the lateral surface
|
||||
// make the substitute geometry a capsule and rotate it so it aligns
|
||||
// with the cone surface
|
||||
geom = PxCapsuleGeometry(radius * 0.25f + margin, sqrtf(height * height + radius * radius) * 0.5f);
|
||||
switch (axis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
PxVec3 capC = (PxVec3(height * 0.5f, 0, 0) + PxVec3(-height * 0.5f, radius, 0)) * 0.5f - PxVec3(radius, height, 0).getNormalized() * radius * 0.25f;
|
||||
preTransform = PxTransform(capC, PxQuat(-coneAng, PxVec3(0, 0, 1)));
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
PxVec3 capC = (PxVec3(0, height * 0.5f, 0) + PxVec3(0, -height * 0.5f, radius)) * 0.5f - PxVec3(0, radius, height).getNormalized() * radius * 0.25f;
|
||||
preTransform = PxTransform(capC, PxQuat(-coneAng, PxVec3(1, 0, 0)) * PxQuat(PxPiDivTwo, PxVec3(0, 0, 1)));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
PxVec3 capC = (PxVec3(0, 0, height * 0.5f) + PxVec3(radius, 0, -height * 0.5f)) * 0.5f - PxVec3(height, 0, radius).getNormalized() * radius * 0.25f;
|
||||
preTransform = PxTransform(capC, PxQuat(-coneAng, PxVec3(0, 1, 0)) * PxQuat(PxPiDivTwo, PxVec3(0, 1, 0)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
PxVec3 axisDir(PxZero); axisDir[axis] = 1.0f;
|
||||
float n1 = -locN[(axis + 1) % 3], n2 = -locN[(axis + 2) % 3];
|
||||
float ang = atan2f(n2, n1);
|
||||
// PT:: tag: scalar transform*transform
|
||||
preTransform = PxTransform(PxQuat(ang, axisDir)) * preTransform;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float PxCustomGeometryExt::ConeCallbacks::getRadiusAtHeight(float h) const
|
||||
{
|
||||
float angle = atan2f(radius, height);
|
||||
float aSin = sinf(angle);
|
||||
float aCos = cosf(angle);
|
||||
|
||||
if (h >= -height * 0.5f + margin * aSin && h <= height * 0.5f + margin * aSin)
|
||||
return radius * (height * 0.5f - h) / height + margin / aCos;
|
||||
|
||||
if (h < -height * 0.5f + margin * aSin)
|
||||
{
|
||||
float a = -h - height * 0.5f;
|
||||
return radius + sqrtf(margin * margin - a * a);
|
||||
}
|
||||
|
||||
if (h > height * 0.5f + margin * aSin)
|
||||
{
|
||||
float a = h - height * 0.5f;
|
||||
return sqrtf(margin * margin - a * a);
|
||||
}
|
||||
|
||||
PX_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
511
engine/third_party/physx/source/physxextensions/src/ExtCustomSceneQuerySystem.cpp
vendored
Normal file
511
engine/third_party/physx/source/physxextensions/src/ExtCustomSceneQuerySystem.cpp
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
// 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/PxCustomSceneQuerySystem.h"
|
||||
#include "extensions/PxShapeExt.h"
|
||||
#include "foundation/PxAlloca.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "geometry/PxBVH.h"
|
||||
#include "GuActorShapeMap.h"
|
||||
#include "ExtSqQuery.h"
|
||||
#include "SqFactory.h"
|
||||
#include "PxRigidActor.h"
|
||||
#include "PxPruningStructure.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sq;
|
||||
using namespace Gu;
|
||||
|
||||
// PT: this customized version uses:
|
||||
// - a modified version of Sq::PrunerManager, named Sq::ExtPrunerManager, located in ExtSqManager.cpp
|
||||
// - a modified version of Sq::SceneQueries, named Sq::ExtSceneQueries, located in ExtSqQuery.cpp
|
||||
//
|
||||
// Sq::PrunerManager and Sq::SceneQueries live in the SceneQuery lib, and are used by PhysX internally
|
||||
// to implement the regular SQ system.
|
||||
//
|
||||
// Sq::ExtPrunerManager and Sq::ExtSceneQueries live in the Extensions lib, and are not used by the
|
||||
// regular PhysX SQ system. They are examples of how the default code can be customized.
|
||||
//
|
||||
|
||||
static CompanionPrunerType getCompanionType(PxDynamicTreeSecondaryPruner::Enum type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case PxDynamicTreeSecondaryPruner::eNONE: return COMPANION_PRUNER_NONE;
|
||||
case PxDynamicTreeSecondaryPruner::eBUCKET: return COMPANION_PRUNER_BUCKET;
|
||||
case PxDynamicTreeSecondaryPruner::eINCREMENTAL: return COMPANION_PRUNER_INCREMENTAL;
|
||||
case PxDynamicTreeSecondaryPruner::eBVH: return COMPANION_PRUNER_AABB_TREE;
|
||||
case PxDynamicTreeSecondaryPruner::eLAST: return COMPANION_PRUNER_NONE;
|
||||
}
|
||||
return COMPANION_PRUNER_NONE;
|
||||
}
|
||||
|
||||
static BVHBuildStrategy getBuildStrategy(PxBVHBuildStrategy::Enum bs)
|
||||
{
|
||||
switch(bs)
|
||||
{
|
||||
case PxBVHBuildStrategy::eFAST: return BVH_SPLATTER_POINTS;
|
||||
case PxBVHBuildStrategy::eDEFAULT: return BVH_SPLATTER_POINTS_SPLIT_GEOM_CENTER;
|
||||
case PxBVHBuildStrategy::eSAH: return BVH_SAH;
|
||||
case PxBVHBuildStrategy::eLAST: return BVH_SPLATTER_POINTS;
|
||||
}
|
||||
return BVH_SPLATTER_POINTS;
|
||||
}
|
||||
|
||||
static Pruner* create(PxPruningStructureType::Enum type, PxU64 contextID, PxDynamicTreeSecondaryPruner::Enum secondaryType, PxBVHBuildStrategy::Enum buildStrategy, PxU32 nbObjectsPerNode)
|
||||
{
|
||||
// if(0)
|
||||
// return createIncrementalPruner(contextID);
|
||||
|
||||
const CompanionPrunerType cpType = getCompanionType(secondaryType);
|
||||
const BVHBuildStrategy bs = getBuildStrategy(buildStrategy);
|
||||
|
||||
Pruner* pruner = NULL;
|
||||
switch(type)
|
||||
{
|
||||
case PxPruningStructureType::eNONE: { pruner = createBucketPruner(contextID); break; }
|
||||
case PxPruningStructureType::eDYNAMIC_AABB_TREE: { pruner = createAABBPruner(contextID, true, cpType, bs, nbObjectsPerNode); break; }
|
||||
case PxPruningStructureType::eSTATIC_AABB_TREE: { pruner = createAABBPruner(contextID, false, cpType, bs, nbObjectsPerNode); break; }
|
||||
case PxPruningStructureType::eLAST: break;
|
||||
}
|
||||
return pruner;
|
||||
}
|
||||
|
||||
#define EXT_PRUNER_EPSILON 0.005f
|
||||
|
||||
// PT: in this external implementation we'll use Px pointers instead of Np pointers in the payload.
|
||||
static PX_FORCE_INLINE void setPayload(PrunerPayload& pp, const PxShape* shape, const PxRigidActor* actor)
|
||||
{
|
||||
pp.data[0] = size_t(shape);
|
||||
pp.data[1] = size_t(actor);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxShape* getShapeFromPayload(const PrunerPayload& payload)
|
||||
{
|
||||
return reinterpret_cast<PxShape*>(payload.data[0]);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxRigidActor* getActorFromPayload(const PrunerPayload& payload)
|
||||
{
|
||||
return reinterpret_cast<PxRigidActor*>(payload.data[1]);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool isDynamicActor(const PxRigidActor& actor)
|
||||
{
|
||||
const PxType actorType = actor.getConcreteType();
|
||||
return actorType != PxConcreteType::eRIGID_STATIC;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PX_FORCE_INLINE ActorShapeData createActorShapeData(PrunerHandle h, PrunerCompoundId id) { return (ActorShapeData(id) << 32) | ActorShapeData(h); }
|
||||
static PX_FORCE_INLINE PrunerHandle getPrunerHandle(ActorShapeData data) { return PrunerHandle(data); }
|
||||
static PX_FORCE_INLINE PrunerCompoundId getCompoundID(ActorShapeData data) { return PrunerCompoundId(data >> 32); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
class ExtSqAdapter : public ExtQueryAdapter
|
||||
{
|
||||
PX_NOCOPY(ExtSqAdapter)
|
||||
public:
|
||||
ExtSqAdapter(const PxCustomSceneQuerySystemAdapter& adapter) : mUserAdapter(adapter)/*, mFilterData(NULL)*/ {}
|
||||
virtual ~ExtSqAdapter() {}
|
||||
|
||||
// Adapter
|
||||
virtual const PxGeometry& getGeometry(const PrunerPayload& payload) const;
|
||||
//~Adapter
|
||||
|
||||
// ExtQueryAdapter
|
||||
virtual PrunerHandle findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const;
|
||||
virtual void getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const;
|
||||
virtual void getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const;
|
||||
virtual bool processPruner(PxU32 prunerIndex, const PxQueryThreadContext* context, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const;
|
||||
//~ExtQueryAdapter
|
||||
|
||||
const PxCustomSceneQuerySystemAdapter& mUserAdapter;
|
||||
ActorShapeMap mDatabase;
|
||||
const PxQueryFilterData* mFilterData;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const PxGeometry& ExtSqAdapter::getGeometry(const PrunerPayload& payload) const
|
||||
{
|
||||
PxShape* shape = getShapeFromPayload(payload);
|
||||
return shape->getGeometry();
|
||||
}
|
||||
|
||||
PrunerHandle ExtSqAdapter::findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const
|
||||
{
|
||||
const PxU32 actorIndex = cache.actor->getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mDatabase.find(actorIndex, cache.actor, cache.shape);
|
||||
|
||||
compoundId = getCompoundID(actorShapeData);
|
||||
|
||||
prunerIndex = mUserAdapter.getPrunerIndex(*cache.actor, *cache.shape);
|
||||
|
||||
return getPrunerHandle(actorShapeData);
|
||||
}
|
||||
|
||||
void ExtSqAdapter::getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const
|
||||
{
|
||||
PxShape* shape = getShapeFromPayload(payload);
|
||||
filterData = shape->getQueryFilterData();
|
||||
}
|
||||
|
||||
void ExtSqAdapter::getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const
|
||||
{
|
||||
actorShape.actor = getActorFromPayload(payload);
|
||||
actorShape.shape = getShapeFromPayload(payload);
|
||||
}
|
||||
|
||||
bool ExtSqAdapter::processPruner(PxU32 prunerIndex, const PxQueryThreadContext* context, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const
|
||||
{
|
||||
return mUserAdapter.processPruner(prunerIndex, context, filterData, filterCall);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
class CustomPxSQ : public PxCustomSceneQuerySystem, public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
CustomPxSQ(const PxCustomSceneQuerySystemAdapter& adapter, ExtPVDCapture* pvd, PxU64 contextID,
|
||||
PxSceneQueryUpdateMode::Enum mode, bool usesTreeOfPruners) :
|
||||
mExtAdapter (adapter),
|
||||
mQueries (pvd, contextID, EXT_PRUNER_EPSILON, mExtAdapter, usesTreeOfPruners),
|
||||
mUpdateMode (mode),
|
||||
mRefCount (1)
|
||||
{}
|
||||
virtual ~CustomPxSQ() {}
|
||||
|
||||
virtual void release();
|
||||
virtual void acquireReference();
|
||||
virtual void preallocate(PxU32 prunerIndex, PxU32 nbShapes) { SQ().preallocate(prunerIndex, nbShapes); }
|
||||
virtual void addSQShape( const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds,
|
||||
const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure);
|
||||
virtual void removeSQShape(const PxRigidActor& actor, const PxShape& shape);
|
||||
virtual void updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform);
|
||||
virtual PxSQCompoundHandle addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& pxbvh, const PxTransform* transforms);
|
||||
virtual void removeSQCompound(PxSQCompoundHandle compoundHandle);
|
||||
virtual void updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform);
|
||||
virtual void flushUpdates() { SQ().flushUpdates(); }
|
||||
virtual void flushMemory() { SQ().flushMemory(); }
|
||||
virtual void visualize(PxU32 prunerIndex, PxRenderOutput& out) const { SQ().visualize(prunerIndex, out); }
|
||||
virtual void shiftOrigin(const PxVec3& shift) { SQ().shiftOrigin(shift); }
|
||||
virtual PxSQBuildStepHandle prepareSceneQueryBuildStep(PxU32 prunerIndex);
|
||||
virtual void sceneQueryBuildStep(PxSQBuildStepHandle handle);
|
||||
virtual void finalizeUpdates();
|
||||
virtual void setDynamicTreeRebuildRateHint(PxU32 dynTreeRebuildRateHint) { SQ().setDynamicTreeRebuildRateHint(dynTreeRebuildRateHint); }
|
||||
virtual PxU32 getDynamicTreeRebuildRateHint() const { return SQ().getDynamicTreeRebuildRateHint(); }
|
||||
virtual void forceRebuildDynamicTree(PxU32 prunerIndex) { SQ().forceRebuildDynamicTree(prunerIndex); }
|
||||
virtual PxSceneQueryUpdateMode::Enum getUpdateMode() const { return mUpdateMode; }
|
||||
virtual void setUpdateMode(PxSceneQueryUpdateMode::Enum mode) { mUpdateMode = mode; }
|
||||
virtual PxU32 getStaticTimestamp() const { return SQ().getStaticTimestamp(); }
|
||||
virtual void merge(const PxPruningStructure& pxps);
|
||||
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
virtual bool sweep( const PxGeometry& geometry, const PxTransform& pose,
|
||||
const PxVec3& unitDir, const PxReal distance,
|
||||
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const;
|
||||
virtual bool overlap(const PxGeometry& geometry, const PxTransform& transform,
|
||||
PxOverlapCallback& hitCall,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
virtual PxSQPrunerHandle getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const;
|
||||
virtual void sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
||||
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices);
|
||||
|
||||
virtual PxU32 addPruner(PxPruningStructureType::Enum primaryType, PxDynamicTreeSecondaryPruner::Enum secondaryType, PxU32 preallocated);
|
||||
virtual PxU32 startCustomBuildstep();
|
||||
virtual void customBuildstep(PxU32 index);
|
||||
virtual void finishCustomBuildstep();
|
||||
|
||||
PX_FORCE_INLINE ExtPrunerManager& SQ() { return mQueries.mSQManager; }
|
||||
PX_FORCE_INLINE const ExtPrunerManager& SQ() const { return mQueries.mSQManager; }
|
||||
|
||||
ExtSqAdapter mExtAdapter;
|
||||
ExtSceneQueries mQueries;
|
||||
PxSceneQueryUpdateMode::Enum mUpdateMode;
|
||||
PxU32 mRefCount;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void addExternalSQ(PxSceneQuerySystem* added);
|
||||
void removeExternalSQ(PxSceneQuerySystem* removed);
|
||||
|
||||
void CustomPxSQ::release()
|
||||
{
|
||||
mRefCount--;
|
||||
if(!mRefCount)
|
||||
{
|
||||
removeExternalSQ(this);
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
}
|
||||
|
||||
void CustomPxSQ::acquireReference()
|
||||
{
|
||||
mRefCount++;
|
||||
}
|
||||
|
||||
void CustomPxSQ::addSQShape(const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds, const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure)
|
||||
{
|
||||
PrunerPayload payload;
|
||||
setPayload(payload, &shape, &actor);
|
||||
|
||||
const bool isDynamic = isDynamicActor(actor);
|
||||
const PxU32 prunerIndex = mExtAdapter.mUserAdapter.getPrunerIndex(actor, shape);
|
||||
|
||||
const PrunerCompoundId cid = compoundHandle ? PrunerCompoundId(*compoundHandle) : INVALID_COMPOUND_ID;
|
||||
const PrunerHandle shapeHandle = SQ().addPrunerShape(payload, prunerIndex, isDynamic, cid, bounds, transform, hasPruningStructure);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
mExtAdapter.mDatabase.add(actorIndex, &actor, &shape, createActorShapeData(shapeHandle, cid));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct DatabaseCleaner : PrunerPayloadRemovalCallback
|
||||
{
|
||||
DatabaseCleaner(ExtSqAdapter& adapter) : mAdapter(adapter){}
|
||||
|
||||
virtual void invoke(PxU32 nbRemoved, const PrunerPayload* removed) PX_OVERRIDE PX_FINAL
|
||||
{
|
||||
PxU32 actorIndex = 0xffffffff;
|
||||
const PxRigidActor* cachedActor = NULL;
|
||||
|
||||
while(nbRemoved--)
|
||||
{
|
||||
const PrunerPayload& payload = *removed++;
|
||||
|
||||
const PxRigidActor* actor = getActorFromPayload(payload);
|
||||
|
||||
if(actor!=cachedActor)
|
||||
{
|
||||
actorIndex = actor->getInternalActorIndex();
|
||||
cachedActor = actor;
|
||||
}
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
bool status = mAdapter.mDatabase.remove(actorIndex, actor, getShapeFromPayload(payload), NULL);
|
||||
PX_ASSERT(status);
|
||||
PX_UNUSED(status);
|
||||
}
|
||||
}
|
||||
ExtSqAdapter& mAdapter;
|
||||
|
||||
PX_NOCOPY(DatabaseCleaner)
|
||||
};
|
||||
}
|
||||
|
||||
void CustomPxSQ::removeSQShape(const PxRigidActor& actor, const PxShape& shape)
|
||||
{
|
||||
const bool isDynamic = isDynamicActor(actor);
|
||||
const PxU32 prunerIndex = mExtAdapter.mUserAdapter.getPrunerIndex(actor, shape);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
ActorShapeData actorShapeData;
|
||||
mExtAdapter.mDatabase.remove(actorIndex, &actor, &shape, &actorShapeData);
|
||||
|
||||
const PrunerHandle shapeHandle = getPrunerHandle(actorShapeData);
|
||||
const PrunerCompoundId compoundId = getCompoundID(actorShapeData);
|
||||
|
||||
SQ().removePrunerShape(prunerIndex, isDynamic, compoundId, shapeHandle, NULL);
|
||||
}
|
||||
|
||||
void CustomPxSQ::updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform)
|
||||
{
|
||||
const bool isDynamic = isDynamicActor(actor);
|
||||
const PxU32 prunerIndex = mExtAdapter.mUserAdapter.getPrunerIndex(actor, shape);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
||||
|
||||
const PrunerHandle shapeHandle = getPrunerHandle(actorShapeData);
|
||||
const PrunerCompoundId cid = getCompoundID(actorShapeData);
|
||||
|
||||
SQ().markForUpdate(prunerIndex, isDynamic, cid, shapeHandle, transform);
|
||||
}
|
||||
|
||||
PxSQCompoundHandle CustomPxSQ::addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& bvh, const PxTransform* transforms)
|
||||
{
|
||||
const PxU32 numSqShapes = bvh.getNbBounds();
|
||||
|
||||
PX_ALLOCA(payloads, PrunerPayload, numSqShapes);
|
||||
for(PxU32 i=0; i<numSqShapes; i++)
|
||||
setPayload(payloads[i], shapes[i], &actor);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
PX_ALLOCA(shapeHandles, PrunerHandle, numSqShapes);
|
||||
SQ().addCompoundShape(bvh, actorIndex, actor.getGlobalPose(), shapeHandles, payloads, transforms, isDynamicActor(actor));
|
||||
|
||||
for(PxU32 i=0; i<numSqShapes; i++)
|
||||
{
|
||||
// PT: TODO: actorIndex is now redundant!
|
||||
mExtAdapter.mDatabase.add(actorIndex, &actor, shapes[i], createActorShapeData(shapeHandles[i], actorIndex));
|
||||
}
|
||||
|
||||
return PxSQCompoundHandle(actorIndex);
|
||||
}
|
||||
|
||||
void CustomPxSQ::removeSQCompound(PxSQCompoundHandle compoundHandle)
|
||||
{
|
||||
DatabaseCleaner cleaner(mExtAdapter);
|
||||
SQ().removeCompoundActor(PrunerCompoundId(compoundHandle), &cleaner);
|
||||
}
|
||||
|
||||
void CustomPxSQ::updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform)
|
||||
{
|
||||
SQ().updateCompoundActor(PrunerCompoundId(compoundHandle), compoundTransform);
|
||||
}
|
||||
|
||||
PxSQBuildStepHandle CustomPxSQ::prepareSceneQueryBuildStep(PxU32 prunerIndex)
|
||||
{
|
||||
return SQ().prepareSceneQueriesUpdate(prunerIndex);
|
||||
}
|
||||
|
||||
void CustomPxSQ::sceneQueryBuildStep(PxSQBuildStepHandle handle)
|
||||
{
|
||||
SQ().sceneQueryBuildStep(handle);
|
||||
}
|
||||
|
||||
void CustomPxSQ::finalizeUpdates()
|
||||
{
|
||||
switch(mUpdateMode)
|
||||
{
|
||||
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_ENABLED: SQ().afterSync(true, true); break;
|
||||
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED: SQ().afterSync(true, false); break;
|
||||
case PxSceneQueryUpdateMode::eBUILD_DISABLED_COMMIT_DISABLED: SQ().afterSync(false, false); break;
|
||||
}
|
||||
}
|
||||
|
||||
void CustomPxSQ::merge(const PxPruningStructure& /*pxps*/)
|
||||
{
|
||||
PX_ASSERT(!"Not supported by this custom SQ system");
|
||||
|
||||
// PT: PxPruningStructure only knows about the regular static/dynamic pruners, so it is not
|
||||
// compatible with this custom version.
|
||||
}
|
||||
|
||||
bool CustomPxSQ::raycast( const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._raycast(origin, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, flags);
|
||||
}
|
||||
|
||||
bool CustomPxSQ::sweep( const PxGeometry& geometry, const PxTransform& pose,
|
||||
const PxVec3& unitDir, const PxReal distance,
|
||||
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._sweep(geometry, pose, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, inflation, flags);
|
||||
}
|
||||
|
||||
bool CustomPxSQ::overlap( const PxGeometry& geometry, const PxTransform& transform,
|
||||
PxOverlapCallback& hitCall,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._overlap( geometry, transform, hitCall, filterData, filterCall, cache, flags);
|
||||
}
|
||||
|
||||
PxSQPrunerHandle CustomPxSQ::getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const
|
||||
{
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
||||
|
||||
prunerIndex = mExtAdapter.mUserAdapter.getPrunerIndex(actor, shape);
|
||||
|
||||
return PxSQPrunerHandle(getPrunerHandle(actorShapeData));
|
||||
}
|
||||
|
||||
void CustomPxSQ::sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
||||
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices)
|
||||
{
|
||||
SQ().sync(prunerIndex, handles, indices, bounds, transforms, count, ignoredIndices);
|
||||
}
|
||||
|
||||
PxU32 CustomPxSQ::addPruner(PxPruningStructureType::Enum primaryType, PxDynamicTreeSecondaryPruner::Enum secondaryType, PxU32 preallocated)
|
||||
{
|
||||
Pruner* pruner = create(primaryType, mQueries.getContextId(), secondaryType, PxBVHBuildStrategy::eFAST, 4);
|
||||
return mQueries.mSQManager.addPruner(pruner, preallocated);
|
||||
}
|
||||
|
||||
PxU32 CustomPxSQ::startCustomBuildstep()
|
||||
{
|
||||
return SQ().startCustomBuildstep();
|
||||
}
|
||||
|
||||
void CustomPxSQ::customBuildstep(PxU32 index)
|
||||
{
|
||||
SQ().customBuildstep(index);
|
||||
}
|
||||
|
||||
void CustomPxSQ::finishCustomBuildstep()
|
||||
{
|
||||
SQ().finishCustomBuildstep();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxCustomSceneQuerySystem* physx::PxCreateCustomSceneQuerySystem(PxSceneQueryUpdateMode::Enum sceneQueryUpdateMode, PxU64 contextID, const PxCustomSceneQuerySystemAdapter& adapter, bool usesTreeOfPruners)
|
||||
{
|
||||
ExtPVDCapture* pvd = NULL;
|
||||
CustomPxSQ* pxsq = PX_NEW(CustomPxSQ)(adapter, pvd, contextID, sceneQueryUpdateMode, usesTreeOfPruners);
|
||||
|
||||
addExternalSQ(pxsq);
|
||||
|
||||
return pxsq;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
1365
engine/third_party/physx/source/physxextensions/src/ExtD6Joint.cpp
vendored
Normal file
1365
engine/third_party/physx/source/physxextensions/src/ExtD6Joint.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
172
engine/third_party/physx/source/physxextensions/src/ExtD6Joint.h
vendored
Normal file
172
engine/third_party/physx/source/physxextensions/src/ExtD6Joint.h
vendored
Normal 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 EXT_D6_JOINT_H
|
||||
#define EXT_D6_JOINT_H
|
||||
|
||||
#include "extensions/PxD6Joint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxD6JointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct D6JointData : public JointData
|
||||
{
|
||||
static constexpr PxU32 sDriveEntryCapacity = 6;
|
||||
|
||||
PxD6Motion::Enum motion[6];
|
||||
PxJointLinearLimit distanceLimit;
|
||||
PxJointLinearLimitPair linearLimitX;
|
||||
PxJointLinearLimitPair linearLimitY;
|
||||
PxJointLinearLimitPair linearLimitZ;
|
||||
PxJointAngularLimitPair twistLimit;
|
||||
PxJointLimitCone swingLimit;
|
||||
PxJointLimitPyramid pyramidSwingLimit;
|
||||
|
||||
PxD6JointDrive drive[sDriveEntryCapacity];
|
||||
|
||||
PxTransform drivePosition;
|
||||
PxVec3 driveLinearVelocity;
|
||||
PxVec3 driveAngularVelocity;
|
||||
|
||||
// derived quantities
|
||||
|
||||
PxU32 locked; // bitmap of locked DOFs
|
||||
PxU32 limited; // bitmap of limited DOFs
|
||||
PxU32 driving; // bitmap of active drives (implies driven DOFs not locked)
|
||||
|
||||
PxReal distanceMinDist; // distance limit minimum distance to get a good direction
|
||||
|
||||
// PT: the PxD6Motion values are now shared for both kind of linear limits, so we need
|
||||
// an extra bool to know which one(s) should be actually used.
|
||||
bool mUseDistanceLimit;
|
||||
bool mUseNewLinearLimits;
|
||||
|
||||
// PT: the swing limits can now be a cone or a pyramid, so we need
|
||||
// an extra bool to know which one(s) should be actually used.
|
||||
bool mUseConeLimit;
|
||||
bool mUsePyramidLimits;
|
||||
|
||||
PxU8 angularDriveConfig; // stores the angular drive config (PxD6AngularDriveConfig::Enum)
|
||||
|
||||
private:
|
||||
D6JointData(const PxJointLinearLimit& distance,
|
||||
const PxJointLinearLimitPair& linearX,
|
||||
const PxJointLinearLimitPair& linearY,
|
||||
const PxJointLinearLimitPair& linearZ,
|
||||
const PxJointAngularLimitPair& twist,
|
||||
const PxJointLimitCone& swing,
|
||||
const PxJointLimitPyramid& pyramid) :
|
||||
distanceLimit (distance),
|
||||
linearLimitX (linearX),
|
||||
linearLimitY (linearY),
|
||||
linearLimitZ (linearZ),
|
||||
twistLimit (twist),
|
||||
swingLimit (swing),
|
||||
pyramidSwingLimit (pyramid),
|
||||
mUseDistanceLimit (false),
|
||||
mUseNewLinearLimits (false),
|
||||
mUseConeLimit (false),
|
||||
mUsePyramidLimits (false),
|
||||
angularDriveConfig (PxD6AngularDriveConfig::eLEGACY)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef JointT<PxD6Joint, D6JointData, PxD6JointGeneratedValues> D6JointT;
|
||||
|
||||
class D6Joint : public D6JointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
D6Joint(PxBaseFlags baseFlags) : D6JointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static D6Joint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<D6Joint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
D6Joint(const PxTolerancesScale& scale, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual ~D6Joint();
|
||||
#endif
|
||||
|
||||
// PxD6Joint
|
||||
virtual void setMotion(PxD6Axis::Enum index, PxD6Motion::Enum t) PX_OVERRIDE;
|
||||
virtual PxD6Motion::Enum getMotion(PxD6Axis::Enum index) const PX_OVERRIDE;
|
||||
virtual PxReal getTwistAngle() const PX_OVERRIDE;
|
||||
virtual PxReal getSwingYAngle() const PX_OVERRIDE;
|
||||
virtual PxReal getSwingZAngle() const PX_OVERRIDE;
|
||||
virtual void setDistanceLimit(const PxJointLinearLimit& l) PX_OVERRIDE;
|
||||
virtual PxJointLinearLimit getDistanceLimit() const PX_OVERRIDE;
|
||||
virtual void setLinearLimit(PxD6Axis::Enum axis, const PxJointLinearLimitPair& limit) PX_OVERRIDE;
|
||||
virtual PxJointLinearLimitPair getLinearLimit(PxD6Axis::Enum axis) const PX_OVERRIDE;
|
||||
virtual void setTwistLimit(const PxJointAngularLimitPair& l) PX_OVERRIDE;
|
||||
virtual PxJointAngularLimitPair getTwistLimit() const PX_OVERRIDE;
|
||||
virtual void setSwingLimit(const PxJointLimitCone& l) PX_OVERRIDE;
|
||||
virtual PxJointLimitCone getSwingLimit() const PX_OVERRIDE;
|
||||
virtual void setPyramidSwingLimit(const PxJointLimitPyramid& limit) PX_OVERRIDE;
|
||||
virtual PxJointLimitPyramid getPyramidSwingLimit() const PX_OVERRIDE;
|
||||
virtual void setDrive(PxD6Drive::Enum index, const PxD6JointDrive& d) PX_OVERRIDE;
|
||||
virtual PxD6JointDrive getDrive(PxD6Drive::Enum index) const PX_OVERRIDE;
|
||||
virtual void setDrivePosition(const PxTransform& pose, bool autowake = true) PX_OVERRIDE;
|
||||
virtual PxTransform getDrivePosition() const PX_OVERRIDE;
|
||||
virtual void setDriveVelocity(const PxVec3& linear, const PxVec3& angular, bool autowake = true) PX_OVERRIDE;
|
||||
virtual void getDriveVelocity(PxVec3& linear, PxVec3& angular) const PX_OVERRIDE;
|
||||
virtual PxD6JointGPUIndex getGPUIndex() const PX_OVERRIDE;
|
||||
virtual void setAngularDriveConfig(PxD6AngularDriveConfig::Enum) PX_OVERRIDE;
|
||||
virtual PxD6AngularDriveConfig::Enum getAngularDriveConfig() const PX_OVERRIDE;
|
||||
//~PxD6Joint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
virtual void* prepareData() PX_OVERRIDE;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE;
|
||||
#endif
|
||||
//~PxConstraintConnector
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
friend void omniPvdInitJoint<D6Joint>(D6Joint& joint);
|
||||
#endif
|
||||
|
||||
private:
|
||||
PX_FORCE_INLINE bool isDriveActive(PxU32 index) const
|
||||
{
|
||||
const PxD6JointDrive& d = data().drive[index];
|
||||
return d.stiffness!=0 || d.damping != 0;
|
||||
}
|
||||
|
||||
bool mRecomputeMotion;
|
||||
bool mPadding[3]; // PT: padding from prev bool
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
250
engine/third_party/physx/source/physxextensions/src/ExtD6JointCreate.cpp
vendored
Normal file
250
engine/third_party/physx/source/physxextensions/src/ExtD6JointCreate.cpp
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
// 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/PxMathUtils.h"
|
||||
#include "extensions/PxD6JointCreate.h"
|
||||
#include "extensions/PxD6Joint.h"
|
||||
#include "extensions/PxFixedJoint.h"
|
||||
#include "extensions/PxRevoluteJoint.h"
|
||||
#include "extensions/PxSphericalJoint.h"
|
||||
#include "extensions/PxPrismaticJoint.h"
|
||||
#include "extensions/PxDistanceJoint.h"
|
||||
#include "PxPhysics.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static const PxVec3 gX(1.0f, 0.0f, 0.0f);
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Fixed(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, bool useD6)
|
||||
{
|
||||
const PxTransform jointFrame0(localPos0);
|
||||
const PxTransform jointFrame1(localPos1);
|
||||
if(useD6)
|
||||
// PT: by default all D6 axes are locked, i.e. it is a fixed joint.
|
||||
return PxD6JointCreate(physics, actor0, jointFrame0, actor1, jointFrame1);
|
||||
else
|
||||
return PxFixedJointCreate(physics, actor0, jointFrame0, actor1, jointFrame1);
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Distance(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, float maxDist, bool useD6)
|
||||
{
|
||||
const PxTransform localFrame0(localPos0);
|
||||
const PxTransform localFrame1(localPos1);
|
||||
|
||||
if(useD6)
|
||||
{
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
|
||||
|
||||
j->setMotion(PxD6Axis::eX, PxD6Motion::eLIMITED);
|
||||
j->setMotion(PxD6Axis::eY, PxD6Motion::eLIMITED);
|
||||
j->setMotion(PxD6Axis::eZ, PxD6Motion::eLIMITED);
|
||||
j->setDistanceLimit(PxJointLinearLimit(maxDist));
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxDistanceJoint* j = PxDistanceJointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setDistanceJointFlag(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED, true);
|
||||
j->setMaxDistance(maxDist);
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Prismatic(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float minLimit, float maxLimit, bool useD6)
|
||||
{
|
||||
const PxQuat q = PxShortestRotation(gX, axis);
|
||||
const PxTransform localFrame0(localPos0, q);
|
||||
const PxTransform localFrame1(localPos1, q);
|
||||
|
||||
const PxJointLinearLimitPair limit(PxTolerancesScale(), minLimit, maxLimit);
|
||||
|
||||
if(useD6)
|
||||
{
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
|
||||
if(minLimit==maxLimit)
|
||||
j->setMotion(PxD6Axis::eX, PxD6Motion::eLOCKED);
|
||||
else if(minLimit>maxLimit)
|
||||
j->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
|
||||
else// if(minLimit<maxLimit)
|
||||
{
|
||||
j->setMotion(PxD6Axis::eX, PxD6Motion::eLIMITED);
|
||||
j->setLinearLimit(PxD6Axis::eX, limit);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxPrismaticJoint* j = PxPrismaticJointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
if(minLimit<maxLimit)
|
||||
{
|
||||
j->setPrismaticJointFlag(PxPrismaticJointFlag::eLIMIT_ENABLED, true);
|
||||
j->setLimit(limit);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Revolute(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float minLimit, float maxLimit, bool useD6)
|
||||
{
|
||||
const PxQuat q = PxShortestRotation(gX, axis);
|
||||
const PxTransform localFrame0(localPos0, q);
|
||||
const PxTransform localFrame1(localPos1, q);
|
||||
|
||||
const PxJointAngularLimitPair limit(minLimit, maxLimit);
|
||||
|
||||
if(useD6)
|
||||
{
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
if(minLimit==maxLimit)
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLOCKED);
|
||||
else if(minLimit>maxLimit)
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
|
||||
else// if(minLimit<maxLimit)
|
||||
{
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLIMITED);
|
||||
j->setTwistLimit(limit);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxRevoluteJoint* j = PxRevoluteJointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
if(minLimit<maxLimit)
|
||||
{
|
||||
j->setRevoluteJointFlag(PxRevoluteJointFlag::eLIMIT_ENABLED, true);
|
||||
j->setLimit(limit);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Spherical(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis, float limit1, float limit2, bool useD6)
|
||||
{
|
||||
const PxQuat q = PxShortestRotation(gX, axis);
|
||||
const PxTransform localFrame0(localPos0, q);
|
||||
const PxTransform localFrame1(localPos1, q);
|
||||
|
||||
const PxJointLimitCone limit(limit1, limit2);
|
||||
|
||||
if(useD6)
|
||||
{
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
|
||||
if(limit1>0.0f && limit2>0.0f)
|
||||
{
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
|
||||
j->setSwingLimit(limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxSphericalJoint* j = PxSphericalJointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
if(limit1>0.0f && limit2>0.0f)
|
||||
{
|
||||
j->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, true);
|
||||
j->setLimitCone(limit);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_GenericCone(float& apiroty, float& apirotz, PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, float minLimit1, float maxLimit1, float minLimit2, float maxLimit2, bool useD6)
|
||||
{
|
||||
const float DesiredMinSwingY = minLimit1;
|
||||
const float DesiredMaxSwingY = maxLimit1;
|
||||
const float DesiredMinSwingZ = minLimit2;
|
||||
const float DesiredMaxSwingZ = maxLimit2;
|
||||
const float APIMaxY = (DesiredMaxSwingY - DesiredMinSwingY)*0.5f;
|
||||
const float APIMaxZ = (DesiredMaxSwingZ - DesiredMinSwingZ)*0.5f;
|
||||
const float APIRotY = (DesiredMaxSwingY + DesiredMinSwingY)*0.5f;
|
||||
const float APIRotZ = (DesiredMaxSwingZ + DesiredMinSwingZ)*0.5f;
|
||||
apiroty = APIRotY;
|
||||
apirotz = APIRotZ;
|
||||
|
||||
const PxQuat RotY = PxGetRotYQuat(APIRotY);
|
||||
const PxQuat RotZ = PxGetRotZQuat(APIRotZ);
|
||||
const PxQuat Rot = RotY * RotZ;
|
||||
|
||||
const PxTransform localFrame0(localPos0, Rot);
|
||||
const PxTransform localFrame1(localPos1);
|
||||
|
||||
const PxJointLimitCone limit(APIMaxY, APIMaxZ);
|
||||
|
||||
if(useD6)
|
||||
{
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
|
||||
j->setSwingLimit(limit);
|
||||
return j;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxSphericalJoint* j = PxSphericalJointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, true);
|
||||
j->setLimitCone(limit);
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
PxJoint* physx::PxD6JointCreate_Pyramid(PxPhysics& physics, PxRigidActor* actor0, const PxVec3& localPos0, PxRigidActor* actor1, const PxVec3& localPos1, const PxVec3& axis,
|
||||
float minLimit1, float maxLimit1, float minLimit2, float maxLimit2)
|
||||
{
|
||||
const PxQuat q = PxShortestRotation(gX, axis);
|
||||
const PxTransform localFrame0(localPos0, q);
|
||||
const PxTransform localFrame1(localPos1, q);
|
||||
|
||||
const PxJointLimitPyramid limit(minLimit1, maxLimit1, minLimit2, maxLimit2);
|
||||
|
||||
PxD6Joint* j = PxD6JointCreate(physics, actor0, localFrame0, actor1, localFrame1);
|
||||
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
|
||||
if(limit.isValid())
|
||||
{
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
|
||||
j->setPyramidSwingLimit(limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
|
||||
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
183
engine/third_party/physx/source/physxextensions/src/ExtDefaultCpuDispatcher.cpp
vendored
Normal file
183
engine/third_party/physx/source/physxextensions/src/ExtDefaultCpuDispatcher.cpp
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// 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 "ExtDefaultCpuDispatcher.h"
|
||||
#include "ExtCpuWorkerThread.h"
|
||||
#include "ExtTaskQueueHelper.h"
|
||||
#include "foundation/PxString.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxDefaultCpuDispatcher* physx::PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks, PxDefaultCpuDispatcherWaitForWorkMode::Enum mode, PxU32 yieldProcessorCount)
|
||||
{
|
||||
return PX_NEW(Ext::DefaultCpuDispatcher)(numThreads, affinityMasks, mode, yieldProcessorCount);
|
||||
}
|
||||
|
||||
#if !PX_SWITCH
|
||||
void Ext::DefaultCpuDispatcher::getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount)
|
||||
{
|
||||
for(PxU32 i=0; i < threadCount; i++)
|
||||
{
|
||||
affinityMasks[i] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Ext::DefaultCpuDispatcher::DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks, PxDefaultCpuDispatcherWaitForWorkMode::Enum mode, PxU32 yieldProcessorCount) : mNumThreads(numThreads), mShuttingDown(false)
|
||||
#if PX_PROFILE
|
||||
,mRunProfiled(true)
|
||||
#else
|
||||
,mRunProfiled(false)
|
||||
#endif
|
||||
, mWaitForWorkMode(mode)
|
||||
, mYieldProcessorCount(yieldProcessorCount)
|
||||
{
|
||||
PX_CHECK_MSG((((PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_PROCESSOR == mWaitForWorkMode) && (mYieldProcessorCount > 0)) ||
|
||||
(((PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_THREAD == mWaitForWorkMode) || (PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode)) && (0 == mYieldProcessorCount))), "Illegal yield processor count for chosen execute mode");
|
||||
|
||||
PxU32* defaultAffinityMasks = NULL;
|
||||
|
||||
if(!affinityMasks)
|
||||
{
|
||||
defaultAffinityMasks = PX_ALLOCATE(PxU32, numThreads, "ThreadAffinityMasks");
|
||||
getAffinityMasks(defaultAffinityMasks, numThreads);
|
||||
affinityMasks = defaultAffinityMasks;
|
||||
}
|
||||
|
||||
// initialize threads first, then start
|
||||
|
||||
mWorkerThreads = PX_ALLOCATE(CpuWorkerThread, numThreads, "CpuWorkerThread");
|
||||
const PxU32 nameLength = 32;
|
||||
mThreadNames = PX_ALLOCATE(PxU8, nameLength * numThreads, "CpuWorkerThreadName");
|
||||
|
||||
if (mWorkerThreads)
|
||||
{
|
||||
for(PxU32 i = 0; i < numThreads; ++i)
|
||||
{
|
||||
PX_PLACEMENT_NEW(mWorkerThreads+i, CpuWorkerThread)();
|
||||
mWorkerThreads[i].initialize(this);
|
||||
}
|
||||
|
||||
for(PxU32 i = 0; i < numThreads; ++i)
|
||||
{
|
||||
if (mThreadNames)
|
||||
{
|
||||
char* threadName = reinterpret_cast<char*>(mThreadNames + (i*nameLength));
|
||||
Pxsnprintf(threadName, nameLength, "PxWorker%02d", i);
|
||||
mWorkerThreads[i].setName(threadName);
|
||||
}
|
||||
|
||||
mWorkerThreads[i].setAffinityMask(affinityMasks[i]);
|
||||
mWorkerThreads[i].start(PxThread::getDefaultStackSize());
|
||||
}
|
||||
|
||||
PX_FREE(defaultAffinityMasks);
|
||||
}
|
||||
else
|
||||
{
|
||||
mNumThreads = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Ext::DefaultCpuDispatcher::~DefaultCpuDispatcher()
|
||||
{
|
||||
for(PxU32 i = 0; i < mNumThreads; ++i)
|
||||
mWorkerThreads[i].signalQuit();
|
||||
|
||||
mShuttingDown = true;
|
||||
if(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode)
|
||||
mWorkReady.set();
|
||||
for(PxU32 i = 0; i < mNumThreads; ++i)
|
||||
mWorkerThreads[i].waitForQuit();
|
||||
|
||||
for(PxU32 i = 0; i < mNumThreads; ++i)
|
||||
mWorkerThreads[i].~CpuWorkerThread();
|
||||
|
||||
PX_FREE(mWorkerThreads);
|
||||
PX_FREE(mThreadNames);
|
||||
}
|
||||
|
||||
void Ext::DefaultCpuDispatcher::release()
|
||||
{
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
void Ext::DefaultCpuDispatcher::submitTask(PxBaseTask& task)
|
||||
{
|
||||
if(!mNumThreads)
|
||||
{
|
||||
// no worker threads, run directly
|
||||
runTask(task);
|
||||
task.release();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Could use TLS to make this more efficient
|
||||
const PxThread::Id currentThread = PxThread::getId();
|
||||
const PxU32 nbThreads = mNumThreads;
|
||||
for(PxU32 i=0; i<nbThreads; ++i)
|
||||
{
|
||||
if(mWorkerThreads[i].tryAcceptJobToLocalQueue(task, currentThread))
|
||||
{
|
||||
if(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode)
|
||||
mWorkReady.set();
|
||||
else
|
||||
PX_ASSERT(PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_PROCESSOR == mWaitForWorkMode || PxDefaultCpuDispatcherWaitForWorkMode::eYIELD_THREAD == mWaitForWorkMode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(mHelper.tryAcceptJobToQueue(task))
|
||||
{
|
||||
if(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode)
|
||||
mWorkReady.set();
|
||||
}
|
||||
}
|
||||
|
||||
void Ext::DefaultCpuDispatcher::resetWakeSignal()
|
||||
{
|
||||
PX_ASSERT(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode);
|
||||
mWorkReady.reset();
|
||||
|
||||
// The code below is necessary to avoid deadlocks on shut down.
|
||||
// A thread usually loops as follows:
|
||||
// while quit is not signaled
|
||||
// 1) reset wake signal
|
||||
// 2) fetch work
|
||||
// 3) if work -> process
|
||||
// 4) else -> wait for wake signal
|
||||
//
|
||||
// If a thread reaches 1) after the thread pool signaled wake up,
|
||||
// the wake up sync gets reset and all other threads which have not
|
||||
// passed 4) already will wait forever.
|
||||
// The code below makes sure that on shutdown, the wake up signal gets
|
||||
// sent again after it was reset
|
||||
//
|
||||
if (mShuttingDown)
|
||||
mWorkReady.set();
|
||||
}
|
||||
127
engine/third_party/physx/source/physxextensions/src/ExtDefaultCpuDispatcher.h
vendored
Normal file
127
engine/third_party/physx/source/physxextensions/src/ExtDefaultCpuDispatcher.h
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// 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 EXT_DEFAULT_CPU_DISPATCHER_H
|
||||
#define EXT_DEFAULT_CPU_DISPATCHER_H
|
||||
|
||||
#include "common/PxProfileZone.h"
|
||||
#include "task/PxTask.h"
|
||||
#include "extensions/PxDefaultCpuDispatcher.h"
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxSync.h"
|
||||
#include "ExtSharedQueueEntryPool.h"
|
||||
#include "ExtTaskQueueHelper.h"
|
||||
#include "ExtCpuWorkerThread.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
#if PX_VC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value.
|
||||
#endif // Because of the SList member I assume
|
||||
|
||||
class DefaultCpuDispatcher : public PxDefaultCpuDispatcher, public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(DefaultCpuDispatcher)
|
||||
private:
|
||||
~DefaultCpuDispatcher();
|
||||
public:
|
||||
DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks, PxDefaultCpuDispatcherWaitForWorkMode::Enum mode = PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK, PxU32 yieldProcessorCount = 0);
|
||||
|
||||
// PxCpuDispatcher
|
||||
virtual void submitTask(PxBaseTask& task) PX_OVERRIDE;
|
||||
virtual PxU32 getWorkerCount() const PX_OVERRIDE { return mNumThreads; }
|
||||
//~PxCpuDispatcher
|
||||
|
||||
// PxDefaultCpuDispatcher
|
||||
virtual void release() PX_OVERRIDE;
|
||||
virtual void setRunProfiled(bool runProfiled) PX_OVERRIDE { mRunProfiled = runProfiled; }
|
||||
virtual bool getRunProfiled() const PX_OVERRIDE { return mRunProfiled; }
|
||||
//~PxDefaultCpuDispatcher
|
||||
|
||||
template<const bool highPriorityT>
|
||||
PxBaseTask* fetchNextTask()
|
||||
{
|
||||
// PT: get job from local list
|
||||
PxBaseTask* task = mHelper.fetchTask<highPriorityT>();
|
||||
if(!task)
|
||||
{
|
||||
// PT: steal job from other threads
|
||||
const PxU32 nbThreads = mNumThreads;
|
||||
for(PxU32 i=0; i<nbThreads; ++i)
|
||||
{
|
||||
task = mWorkerThreads[i].getJob<highPriorityT>();
|
||||
if(task)
|
||||
return task;
|
||||
}
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void runTask(PxBaseTask& task)
|
||||
{
|
||||
if(mRunProfiled)
|
||||
{
|
||||
PX_PROFILE_ZONE(task.getName(), task.getContextId());
|
||||
task.run();
|
||||
}
|
||||
else
|
||||
task.run();
|
||||
}
|
||||
|
||||
void waitForWork() { PX_ASSERT(PxDefaultCpuDispatcherWaitForWorkMode::eWAIT_FOR_WORK == mWaitForWorkMode); mWorkReady.wait(); }
|
||||
void resetWakeSignal();
|
||||
|
||||
static void getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount);
|
||||
|
||||
PX_FORCE_INLINE PxDefaultCpuDispatcherWaitForWorkMode::Enum getWaitForWorkMode() const { return mWaitForWorkMode; }
|
||||
PX_FORCE_INLINE PxU32 getYieldProcessorCount() const { return mYieldProcessorCount; }
|
||||
|
||||
protected:
|
||||
CpuWorkerThread* mWorkerThreads;
|
||||
TaskQueueHelper mHelper;
|
||||
PxSync mWorkReady;
|
||||
PxU8* mThreadNames;
|
||||
PxU32 mNumThreads;
|
||||
bool mShuttingDown;
|
||||
bool mRunProfiled;
|
||||
const PxDefaultCpuDispatcherWaitForWorkMode::Enum mWaitForWorkMode;
|
||||
const PxU32 mYieldProcessorCount;
|
||||
};
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace Ext
|
||||
}
|
||||
|
||||
#endif
|
||||
98
engine/third_party/physx/source/physxextensions/src/ExtDefaultErrorCallback.cpp
vendored
Normal file
98
engine/third_party/physx/source/physxextensions/src/ExtDefaultErrorCallback.cpp
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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/PxString.h"
|
||||
#include "foundation/PxThread.h"
|
||||
#include "extensions/PxDefaultErrorCallback.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace physx;
|
||||
|
||||
|
||||
PxDefaultErrorCallback::PxDefaultErrorCallback()
|
||||
{
|
||||
}
|
||||
|
||||
PxDefaultErrorCallback::~PxDefaultErrorCallback()
|
||||
{
|
||||
}
|
||||
|
||||
void PxDefaultErrorCallback::reportError(PxErrorCode::Enum e, const char* message, const char* file, int line)
|
||||
{
|
||||
const char* errorCode = NULL;
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case PxErrorCode::eNO_ERROR:
|
||||
errorCode = "no error";
|
||||
break;
|
||||
case PxErrorCode::eINVALID_PARAMETER:
|
||||
errorCode = "invalid parameter";
|
||||
break;
|
||||
case PxErrorCode::eINVALID_OPERATION:
|
||||
errorCode = "invalid operation";
|
||||
break;
|
||||
case PxErrorCode::eOUT_OF_MEMORY:
|
||||
errorCode = "out of memory";
|
||||
break;
|
||||
case PxErrorCode::eDEBUG_INFO:
|
||||
errorCode = "info";
|
||||
break;
|
||||
case PxErrorCode::eDEBUG_WARNING:
|
||||
errorCode = "warning";
|
||||
break;
|
||||
case PxErrorCode::ePERF_WARNING:
|
||||
errorCode = "performance warning";
|
||||
break;
|
||||
case PxErrorCode::eABORT:
|
||||
errorCode = "abort";
|
||||
break;
|
||||
case PxErrorCode::eINTERNAL_ERROR:
|
||||
errorCode = "internal error";
|
||||
break;
|
||||
case PxErrorCode::eMASK_ALL:
|
||||
errorCode = "unknown error";
|
||||
break;
|
||||
}
|
||||
|
||||
PX_ASSERT(errorCode);
|
||||
if(errorCode)
|
||||
{
|
||||
char buffer[1024];
|
||||
sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message);
|
||||
|
||||
PxPrintString(buffer);
|
||||
|
||||
PX_ASSERT(e != PxErrorCode::eABORT);
|
||||
|
||||
if (e == PxErrorCode::eABORT)
|
||||
PxThread::sleep(1000); // make sure that the error message is flushed
|
||||
}
|
||||
}
|
||||
233
engine/third_party/physx/source/physxextensions/src/ExtDefaultProfiler.cpp
vendored
Normal file
233
engine/third_party/physx/source/physxextensions/src/ExtDefaultProfiler.cpp
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// 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/PxTime.h"
|
||||
#include "foundation/PxThread.h"
|
||||
#include "ExtDefaultProfiler.h"
|
||||
|
||||
|
||||
using namespace physx;
|
||||
|
||||
const PxU32 gMinBufferSize = 32767;
|
||||
|
||||
|
||||
// Ensure alignment for all structs is as expected.
|
||||
#define DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(type, alignment) PX_COMPILE_TIME_ASSERT((sizeof(type) & (alignment - 1)) == 0);
|
||||
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerVersionInfo, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerHeader, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerThread, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerName, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerEvent, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT_SIZE(PxDefaultProfilerValueEvent, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
|
||||
|
||||
PxDefaultProfiler* physx::PxDefaultProfilerCreate(PxOutputStream& outputStream, PxU32 numberOfBuffers, PxU32 bufferSize)
|
||||
{
|
||||
return PX_NEW(Ext::DefaultProfiler)(outputStream, numberOfBuffers, bufferSize);
|
||||
}
|
||||
|
||||
Ext::DefaultProfiler::DefaultProfiler(PxOutputStream& outputStream, PxU32 numberOfBuffers, PxU32 bufferSize) :
|
||||
mOutputStream(outputStream)
|
||||
{
|
||||
mTlsSlotId = PxTlsAlloc();
|
||||
|
||||
// Ensure the buffer size is large enough to hold some minimal set of data.
|
||||
if(bufferSize < gMinBufferSize)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, PX_FL,
|
||||
"Ext::DefaultProfiler::DefaultProfiler: buffer was increased to the minimum buffer size of %d bytes.",
|
||||
gMinBufferSize);
|
||||
|
||||
mBufferSize = gMinBufferSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
// Pre-allocate all of the profiler data blocks.
|
||||
for(PxU32 i = 0; i < numberOfBuffers; i++)
|
||||
{
|
||||
DefaultProfilerDataBlock* dataBlock = PX_NEW(DefaultProfilerDataBlock)(bufferSize, outputStream, mMutex);
|
||||
mEmptyList.push(*dataBlock);
|
||||
}
|
||||
|
||||
// Save version info.
|
||||
PxDefaultProfilerVersionInfo versionInfo;
|
||||
versionInfo.major = PX_PROFILER_VERSION_MAJOR;
|
||||
versionInfo.minor = PX_PROFILER_VERSION_MINOR;
|
||||
outputStream.write(&versionInfo, sizeof(PxDefaultProfilerVersionInfo));
|
||||
}
|
||||
|
||||
Ext::DefaultProfiler::~DefaultProfiler()
|
||||
{
|
||||
flush();
|
||||
|
||||
// Delete all of the used and empty blocks.
|
||||
DefaultProfilerDataBlock* dataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(mEmptyList.pop());
|
||||
|
||||
while(dataBlock)
|
||||
{
|
||||
PX_DELETE(dataBlock);
|
||||
|
||||
dataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(mEmptyList.pop());
|
||||
}
|
||||
|
||||
dataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(mUsedList.pop());
|
||||
|
||||
while(dataBlock)
|
||||
{
|
||||
PX_DELETE(dataBlock);
|
||||
|
||||
dataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(mUsedList.pop());
|
||||
}
|
||||
|
||||
PxTlsFree(mTlsSlotId);
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::release()
|
||||
{
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::flush()
|
||||
{
|
||||
// Loop through every used data block and flush them to the stream.
|
||||
DefaultProfilerDataBlock* usedDataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(mUsedList.flush());
|
||||
|
||||
while(usedDataBlock)
|
||||
{
|
||||
usedDataBlock->flush();
|
||||
|
||||
DefaultProfilerDataBlock* previousDataBlock = usedDataBlock;
|
||||
usedDataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(usedDataBlock->next());
|
||||
|
||||
mUsedList.push(*previousDataBlock);
|
||||
}
|
||||
}
|
||||
|
||||
Ext::DefaultProfilerDataBlock* Ext::DefaultProfiler::getThreadData()
|
||||
{
|
||||
DefaultProfilerDataBlock* dataBlock = reinterpret_cast<DefaultProfilerDataBlock*>(PxTlsGet(mTlsSlotId));
|
||||
|
||||
// This thread never had a profiling callback, grab a data block from the pool of pre-allocated blocks.
|
||||
// If there are none left, allocate a new block.
|
||||
if(!dataBlock)
|
||||
{
|
||||
dataBlock = static_cast<DefaultProfilerDataBlock*>(mEmptyList.pop());
|
||||
|
||||
if(!dataBlock)
|
||||
{
|
||||
dataBlock = PX_NEW(DefaultProfilerDataBlock)(mBufferSize, mOutputStream, mMutex);
|
||||
}
|
||||
|
||||
// Store the data block in the TLS.
|
||||
PxTlsSet(mTlsSlotId, dataBlock);
|
||||
|
||||
// Write the event block header.
|
||||
PxU64 threadId = PxThread::getId();
|
||||
|
||||
PxDefaultProfilerThread* thread;
|
||||
dataBlock->write(PxDefaultProfilerDataType::eTHREAD_BLOCK, thread);
|
||||
thread->threadId = threadId;
|
||||
|
||||
// Save the new data block in the user list.
|
||||
mUsedList.push(*dataBlock);
|
||||
}
|
||||
|
||||
return dataBlock;
|
||||
}
|
||||
|
||||
template <typename TEntry>
|
||||
TEntry* Ext::DefaultProfiler::writeProfilerEvent(const char* name, PxDefaultProfilerDataType::Enum type, PxU64 contextId)
|
||||
{
|
||||
Ext::DefaultProfilerDataBlock* dataBlock = getThreadData();
|
||||
|
||||
TEntry* entry;
|
||||
dataBlock->write(type, entry, name);
|
||||
|
||||
PxDefaultProfilerEvent*event = static_cast<PxDefaultProfilerEvent*>(entry);
|
||||
event->time = PxTime::getCurrentTimeInTensOfNanoSeconds();
|
||||
event->contextId = contextId;
|
||||
event->nameKey = PxU64(name);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void* Ext::DefaultProfiler::zoneStart(const char* eventName, bool detached, uint64_t contextId)
|
||||
{
|
||||
PxDefaultProfilerDataType::Enum type;
|
||||
|
||||
if(detached)
|
||||
{
|
||||
type = PxDefaultProfilerDataType::eZONE_START_CROSS_THREAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = PxDefaultProfilerDataType::eZONE_START;
|
||||
}
|
||||
|
||||
writeProfilerEvent<PxDefaultProfilerEvent>(eventName, type, contextId);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::zoneEnd(void*, const char* eventName, bool detached, uint64_t contextId)
|
||||
{
|
||||
PxDefaultProfilerDataType::Enum type;
|
||||
|
||||
if(detached)
|
||||
{
|
||||
type = PxDefaultProfilerDataType::eZONE_END_CROSS_THREAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = PxDefaultProfilerDataType::eZONE_END;
|
||||
}
|
||||
|
||||
writeProfilerEvent<PxDefaultProfilerEvent>(eventName, type, contextId);
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::recordData(int32_t value, const char* valueName, uint64_t contextId)
|
||||
{
|
||||
PxDefaultProfilerValueEvent* valueEvent = writeProfilerEvent<PxDefaultProfilerValueEvent>(valueName, PxDefaultProfilerDataType::eVALUE_INT, contextId);
|
||||
valueEvent->intValue = value;
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::recordData(float value, const char* valueName, uint64_t contextId)
|
||||
{
|
||||
PxDefaultProfilerValueEvent* valueEvent = writeProfilerEvent<PxDefaultProfilerValueEvent>(valueName, PxDefaultProfilerDataType::eVALUE_FLOAT, contextId);
|
||||
valueEvent->floatValue = value;
|
||||
}
|
||||
|
||||
void Ext::DefaultProfiler::recordFrame(const char* name, uint64_t contextId)
|
||||
{
|
||||
writeProfilerEvent<PxDefaultProfilerEvent>(name, PxDefaultProfilerDataType::eFRAME, contextId);
|
||||
}
|
||||
220
engine/third_party/physx/source/physxextensions/src/ExtDefaultProfiler.h
vendored
Normal file
220
engine/third_party/physx/source/physxextensions/src/ExtDefaultProfiler.h
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
// 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 EXT_DEFAULT_PROFILER_H
|
||||
#define EXT_DEFAULT_PROFILER_H
|
||||
|
||||
#include "extensions/PxDefaultProfiler.h"
|
||||
|
||||
#include "foundation/PxProfiler.h"
|
||||
#include "foundation/PxHashSet.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxMutex.h"
|
||||
#include "foundation/PxSList.h"
|
||||
|
||||
|
||||
#define DEFAULT_PROFILER_CHECK_ALIGNMENT(value, alignment) PX_ASSERT((value & (alignment - 1)) == 0);
|
||||
#define DEFAULT_PROFILER_REQUIRED_ALIGNMENT 8
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
|
||||
|
||||
class DefaultProfilerDataBlock : public PxSListEntry, public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
char* mBuffer;
|
||||
char* mNextEntry;
|
||||
char* mEndBuffer;
|
||||
|
||||
PxHashSet<PxU64> mNameKeys;
|
||||
|
||||
PxOutputStream& mOutputStream;
|
||||
PxMutex& mMutex;
|
||||
|
||||
|
||||
DefaultProfilerDataBlock(const PxU32 bufferSize, PxOutputStream& outputStream, PxMutex& mutex) :
|
||||
mOutputStream(outputStream),
|
||||
mMutex(mutex)
|
||||
{
|
||||
mBuffer = static_cast<char*>(PxAlignedAllocator<DEFAULT_PROFILER_REQUIRED_ALIGNMENT>().allocate(bufferSize, PX_FL));
|
||||
mNextEntry = mBuffer;
|
||||
mEndBuffer = mBuffer + bufferSize;
|
||||
}
|
||||
|
||||
~DefaultProfilerDataBlock()
|
||||
{
|
||||
PxAlignedAllocator<DEFAULT_PROFILER_REQUIRED_ALIGNMENT>().deallocate(mBuffer);
|
||||
}
|
||||
|
||||
PxU32 size() const
|
||||
{
|
||||
return (PxU32)(mNextEntry - mBuffer);
|
||||
}
|
||||
|
||||
bool isFull(const PxU32 size) const
|
||||
{
|
||||
return (mNextEntry + size >= mEndBuffer);
|
||||
}
|
||||
|
||||
void seek(const PxU32 offset)
|
||||
{
|
||||
mNextEntry = mBuffer + offset;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
// The thread ID is stored at the start of every data block and must be preserved.
|
||||
static const PxU32 sThreadOffset = sizeof(PxDefaultProfilerHeader) + sizeof(PxDefaultProfilerThread);
|
||||
|
||||
// The thread must be locked to prevent multiple writes to the stream at the same time.
|
||||
PxMutex::ScopedLock scopedLock(mMutex);
|
||||
|
||||
// Keep the header that lists the thread Id for this data block.
|
||||
mOutputStream.write(mBuffer, size());
|
||||
seek(sThreadOffset);
|
||||
}
|
||||
|
||||
|
||||
template <typename TEntry>
|
||||
void write(PxDefaultProfilerDataType::Enum type, TEntry*& entry, const char* name = nullptr)
|
||||
{
|
||||
static const PxU32 sNameSize = sizeof(PxDefaultProfilerHeader) + sizeof(PxDefaultProfilerName);
|
||||
|
||||
PxU64 key = (PxU64)name;
|
||||
PxU32 nameSize;
|
||||
PxU32 nameStringSize;
|
||||
PxU32 paddedNameStringSize;
|
||||
|
||||
if(name && mNameKeys.contains(key) == false)
|
||||
{
|
||||
nameSize = sNameSize;
|
||||
nameStringSize = (PxU32)strlen(name) + 1;
|
||||
|
||||
// Pad the string buffer.
|
||||
paddedNameStringSize = (nameStringSize + (DEFAULT_PROFILER_REQUIRED_ALIGNMENT - 1)) & ~(DEFAULT_PROFILER_REQUIRED_ALIGNMENT - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nameSize = 0;
|
||||
nameStringSize = 0;
|
||||
paddedNameStringSize = 0;
|
||||
}
|
||||
|
||||
// Check if there is enough space in the buffer.
|
||||
const PxU32 requiredSize = sizeof(PxDefaultProfilerHeader) + sizeof(TEntry) + nameSize + paddedNameStringSize;
|
||||
|
||||
if(isFull(requiredSize))
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
PxDefaultProfilerHeader* header = reinterpret_cast<PxDefaultProfilerHeader*>(mNextEntry);
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT((PxU64)header, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
mNextEntry += sizeof(PxDefaultProfilerHeader);
|
||||
header->type = type;
|
||||
|
||||
// Point the entry to the correct point in the buffer. Write to the buffer outside of this funciton.
|
||||
entry = reinterpret_cast<TEntry*>(mNextEntry);
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT((PxU64)entry, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
mNextEntry += sizeof(TEntry);
|
||||
|
||||
// Write the name if necessary.
|
||||
if(nameSize > 0)
|
||||
{
|
||||
header = reinterpret_cast<PxDefaultProfilerHeader*>(mNextEntry);
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT((PxU64)header, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
mNextEntry += sizeof(PxDefaultProfilerHeader);
|
||||
header->type = PxDefaultProfilerDataType::eNAME_REGISTRATION;
|
||||
|
||||
PxDefaultProfilerName* profilerName = reinterpret_cast<PxDefaultProfilerName*>(mNextEntry);
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT((PxU64)profilerName, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
mNextEntry += sizeof(PxDefaultProfilerName);
|
||||
profilerName->key = key;
|
||||
profilerName->size = paddedNameStringSize;
|
||||
|
||||
DEFAULT_PROFILER_CHECK_ALIGNMENT((PxU64)mNextEntry, DEFAULT_PROFILER_REQUIRED_ALIGNMENT)
|
||||
PxMemCopy(mNextEntry, name, nameStringSize);
|
||||
mNextEntry += paddedNameStringSize;
|
||||
|
||||
mNameKeys.insert(key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DefaultProfiler : public PxDefaultProfiler, public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(DefaultProfiler)
|
||||
|
||||
private:
|
||||
~DefaultProfiler();
|
||||
|
||||
public:
|
||||
DefaultProfiler(PxOutputStream& outputStream, PxU32 numberOfBuffers, PxU32 bufferSize);
|
||||
|
||||
virtual void release() PX_OVERRIDE;
|
||||
virtual void flush() PX_OVERRIDE;
|
||||
|
||||
virtual void* zoneStart(const char* eventName, bool detached, uint64_t contextId) PX_OVERRIDE;
|
||||
virtual void zoneEnd(void* profilerData, const char* eventName, bool detached, uint64_t contextId) PX_OVERRIDE;
|
||||
virtual void recordData(int32_t value, const char* valueName, uint64_t contextId) PX_OVERRIDE;
|
||||
virtual void recordData(float value, const char* valueName, uint64_t contextId) PX_OVERRIDE;
|
||||
virtual void recordFrame(const char* name, uint64_t contextId) PX_OVERRIDE;
|
||||
|
||||
protected:
|
||||
|
||||
// Return a pointer to the data block.
|
||||
DefaultProfilerDataBlock* getThreadData();
|
||||
|
||||
template <typename TEntry>
|
||||
TEntry* writeProfilerEvent(const char* name, PxDefaultProfilerDataType::Enum type, PxU64 contextId);
|
||||
|
||||
|
||||
PxOutputStream& mOutputStream;
|
||||
|
||||
// Container for the pre-allocated event data blocks.
|
||||
PxSList mEmptyList;
|
||||
|
||||
// Container for the used event entry data.
|
||||
PxSList mUsedList;
|
||||
|
||||
// TLS Implementation.
|
||||
PxU32 mTlsSlotId;
|
||||
PxMutex mMutex;
|
||||
|
||||
PxU32 mBufferSize;
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
}
|
||||
|
||||
#endif
|
||||
360
engine/third_party/physx/source/physxextensions/src/ExtDefaultSimulationFilterShader.cpp
vendored
Normal file
360
engine/third_party/physx/source/physxextensions/src/ExtDefaultSimulationFilterShader.cpp
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
// 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/PxDefaultSimulationFilterShader.h"
|
||||
#include "PxRigidActor.h"
|
||||
#include "PxShape.h"
|
||||
#include "PxDeformableSurface.h"
|
||||
#include "PxDeformableVolume.h"
|
||||
#include "foundation/PxIntrinsics.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxInlineArray.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
namespace
|
||||
{
|
||||
#define GROUP_SIZE 32
|
||||
|
||||
struct PxCollisionBitMap
|
||||
{
|
||||
PX_INLINE PxCollisionBitMap() : enable(true) {}
|
||||
|
||||
bool operator()() const { return enable; }
|
||||
bool& operator= (const bool &v) { enable = v; return enable; }
|
||||
|
||||
private:
|
||||
bool enable;
|
||||
};
|
||||
|
||||
PxCollisionBitMap gCollisionTable[GROUP_SIZE][GROUP_SIZE];
|
||||
|
||||
PxFilterOp::Enum gFilterOps[3] = { PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND };
|
||||
|
||||
PxGroupsMask gFilterConstants[2];
|
||||
|
||||
bool gFilterBool = false;
|
||||
|
||||
static void gAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(mask0.bits0 & mask1.bits0);
|
||||
results.bits1 = PxU16(mask0.bits1 & mask1.bits1);
|
||||
results.bits2 = PxU16(mask0.bits2 & mask1.bits2);
|
||||
results.bits3 = PxU16(mask0.bits3 & mask1.bits3);
|
||||
}
|
||||
static void gOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(mask0.bits0 | mask1.bits0);
|
||||
results.bits1 = PxU16(mask0.bits1 | mask1.bits1);
|
||||
results.bits2 = PxU16(mask0.bits2 | mask1.bits2);
|
||||
results.bits3 = PxU16(mask0.bits3 | mask1.bits3);
|
||||
}
|
||||
static void gXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(mask0.bits0 ^ mask1.bits0);
|
||||
results.bits1 = PxU16(mask0.bits1 ^ mask1.bits1);
|
||||
results.bits2 = PxU16(mask0.bits2 ^ mask1.bits2);
|
||||
results.bits3 = PxU16(mask0.bits3 ^ mask1.bits3);
|
||||
}
|
||||
static void gNAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(~(mask0.bits0 & mask1.bits0));
|
||||
results.bits1 = PxU16(~(mask0.bits1 & mask1.bits1));
|
||||
results.bits2 = PxU16(~(mask0.bits2 & mask1.bits2));
|
||||
results.bits3 = PxU16(~(mask0.bits3 & mask1.bits3));
|
||||
}
|
||||
static void gNOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(~(mask0.bits0 | mask1.bits0));
|
||||
results.bits1 = PxU16(~(mask0.bits1 | mask1.bits1));
|
||||
results.bits2 = PxU16(~(mask0.bits2 | mask1.bits2));
|
||||
results.bits3 = PxU16(~(mask0.bits3 | mask1.bits3));
|
||||
}
|
||||
static void gNXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(~(mask0.bits0 ^ mask1.bits0));
|
||||
results.bits1 = PxU16(~(mask0.bits1 ^ mask1.bits1));
|
||||
results.bits2 = PxU16(~(mask0.bits2 ^ mask1.bits2));
|
||||
results.bits3 = PxU16(~(mask0.bits3 ^ mask1.bits3));
|
||||
}
|
||||
|
||||
static void gSWAP_AND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
|
||||
{
|
||||
results.bits0 = PxU16(mask0.bits0 & mask1.bits2);
|
||||
results.bits1 = PxU16(mask0.bits1 & mask1.bits3);
|
||||
results.bits2 = PxU16(mask0.bits2 & mask1.bits0);
|
||||
results.bits3 = PxU16(mask0.bits3 & mask1.bits1);
|
||||
}
|
||||
|
||||
typedef void (*FilterFunction) (PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1);
|
||||
|
||||
FilterFunction const gTable[] = { gAND, gOR, gXOR, gNAND, gNOR, gNXOR, gSWAP_AND };
|
||||
|
||||
static PxFilterData convert(const PxGroupsMask& mask)
|
||||
{
|
||||
PxFilterData fd;
|
||||
|
||||
fd.word2 = PxU32(mask.bits0 | (mask.bits1 << 16));
|
||||
fd.word3 = PxU32(mask.bits2 | (mask.bits3 << 16));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static PxGroupsMask convert(const PxFilterData& fd)
|
||||
{
|
||||
PxGroupsMask mask;
|
||||
|
||||
mask.bits0 = PxU16((fd.word2 & 0xffff));
|
||||
mask.bits1 = PxU16((fd.word2 >> 16));
|
||||
mask.bits2 = PxU16((fd.word3 & 0xffff));
|
||||
mask.bits3 = PxU16((fd.word3 >> 16));
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static bool getFilterData(const PxActor& actor, PxFilterData& fd)
|
||||
{
|
||||
PxActorType::Enum aType = actor.getType();
|
||||
switch (aType)
|
||||
{
|
||||
case PxActorType::eRIGID_DYNAMIC:
|
||||
case PxActorType::eRIGID_STATIC:
|
||||
case PxActorType::eARTICULATION_LINK:
|
||||
{
|
||||
const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
|
||||
PX_CHECK_AND_RETURN_VAL(rActor.getNbShapes() >= 1,"There must be a shape in actor", false);
|
||||
|
||||
PxShape* shape = NULL;
|
||||
rActor.getShapes(&shape, 1);
|
||||
|
||||
fd = shape->getSimulationFilterData();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE static void adjustFilterData(bool groupsMask, const PxFilterData& src, PxFilterData& dst)
|
||||
{
|
||||
if (groupsMask)
|
||||
{
|
||||
dst.word2 = src.word2;
|
||||
dst.word3 = src.word3;
|
||||
}
|
||||
else
|
||||
dst.word0 = src.word0;
|
||||
}
|
||||
|
||||
template<bool TGroupsMask>
|
||||
static void setFilterData(PxActor& actor, const PxFilterData& fd)
|
||||
{
|
||||
PxActorType::Enum aType = actor.getType();
|
||||
switch (aType)
|
||||
{
|
||||
case PxActorType::eRIGID_DYNAMIC:
|
||||
case PxActorType::eRIGID_STATIC:
|
||||
case PxActorType::eARTICULATION_LINK:
|
||||
{
|
||||
const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
|
||||
|
||||
PxShape* shape;
|
||||
for(PxU32 i=0; i < rActor.getNbShapes(); i++)
|
||||
{
|
||||
rActor.getShapes(&shape, 1, i);
|
||||
|
||||
// retrieve current group mask
|
||||
PxFilterData resultFd = shape->getSimulationFilterData();
|
||||
|
||||
adjustFilterData(TGroupsMask, fd, resultFd);
|
||||
|
||||
// set new filter data
|
||||
shape->setSimulationFilterData(resultFd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PxActorType::eDEFORMABLE_SURFACE:
|
||||
{
|
||||
PxDeformableSurface& sActor = static_cast<PxDeformableSurface&>(actor);
|
||||
PxShape* shape = sActor.getShape();
|
||||
|
||||
// retrieve current group mask
|
||||
PxFilterData resultFd = shape->getSimulationFilterData();
|
||||
|
||||
adjustFilterData(TGroupsMask, fd, resultFd);
|
||||
|
||||
// set new filter data
|
||||
shape->setSimulationFilterData(resultFd);
|
||||
}
|
||||
break;
|
||||
case PxActorType::eDEFORMABLE_VOLUME:
|
||||
{
|
||||
PxDeformableVolume& sActor = static_cast<PxDeformableVolume&>(actor);
|
||||
PxShape* shape = sActor.getShape();
|
||||
|
||||
// retrieve current group mask
|
||||
PxFilterData resultFd = shape->getSimulationFilterData();
|
||||
|
||||
adjustFilterData(TGroupsMask, fd, resultFd);
|
||||
|
||||
// set new filter data
|
||||
shape->setSimulationFilterData(resultFd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PxFilterFlags physx::PxDefaultSimulationFilterShader(
|
||||
PxFilterObjectAttributes attributes0,
|
||||
PxFilterData filterData0,
|
||||
PxFilterObjectAttributes attributes1,
|
||||
PxFilterData filterData1,
|
||||
PxPairFlags& pairFlags,
|
||||
const void* constantBlock,
|
||||
PxU32 constantBlockSize)
|
||||
{
|
||||
PX_UNUSED(constantBlock);
|
||||
PX_UNUSED(constantBlockSize);
|
||||
|
||||
// let triggers through
|
||||
if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
|
||||
{
|
||||
pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
|
||||
return PxFilterFlags();
|
||||
}
|
||||
|
||||
// Collision Group
|
||||
if (!gCollisionTable[filterData0.word0][filterData1.word0]())
|
||||
{
|
||||
return PxFilterFlag::eSUPPRESS;
|
||||
}
|
||||
|
||||
// Filter function
|
||||
PxGroupsMask g0 = convert(filterData0);
|
||||
PxGroupsMask g1 = convert(filterData1);
|
||||
|
||||
PxGroupsMask g0k0; gTable[gFilterOps[0]](g0k0, g0, gFilterConstants[0]);
|
||||
PxGroupsMask g1k1; gTable[gFilterOps[1]](g1k1, g1, gFilterConstants[1]);
|
||||
PxGroupsMask final; gTable[gFilterOps[2]](final, g0k0, g1k1);
|
||||
|
||||
bool r = final.bits0 || final.bits1 || final.bits2 || final.bits3;
|
||||
if (r != gFilterBool)
|
||||
{
|
||||
return PxFilterFlag::eSUPPRESS;
|
||||
}
|
||||
|
||||
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
|
||||
|
||||
return PxFilterFlags();
|
||||
}
|
||||
|
||||
bool physx::PxGetGroupCollisionFlag(const PxU16 group1, const PxU16 group2)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(group1 < 32 && group2 < 32, "Group must be less than 32");
|
||||
|
||||
return gCollisionTable[group1][group2]();
|
||||
}
|
||||
|
||||
void physx::PxSetGroupCollisionFlag(const PxU16 group1, const PxU16 group2, const bool enable)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(group1 < 32 && group2 < 32, "Group must be less than 32");
|
||||
|
||||
gCollisionTable[group1][group2] = enable;
|
||||
gCollisionTable[group2][group1] = enable;
|
||||
}
|
||||
|
||||
PxU16 physx::PxGetGroup(const PxActor& actor)
|
||||
{
|
||||
PxFilterData fd;
|
||||
getFilterData(actor, fd);
|
||||
return PxU16(fd.word0);
|
||||
}
|
||||
|
||||
void physx::PxSetGroup(PxActor& actor, const PxU16 collisionGroup)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(collisionGroup < 32,"Collision group must be less than 32");
|
||||
PxFilterData fd(collisionGroup, 0, 0, 0);
|
||||
setFilterData<false>(actor, fd);
|
||||
}
|
||||
|
||||
void physx::PxGetFilterOps(PxFilterOp::Enum& op0, PxFilterOp::Enum& op1, PxFilterOp::Enum& op2)
|
||||
{
|
||||
op0 = gFilterOps[0];
|
||||
op1 = gFilterOps[1];
|
||||
op2 = gFilterOps[2];
|
||||
}
|
||||
|
||||
void physx::PxSetFilterOps(const PxFilterOp::Enum& op0, const PxFilterOp::Enum& op1, const PxFilterOp::Enum& op2)
|
||||
{
|
||||
gFilterOps[0] = op0;
|
||||
gFilterOps[1] = op1;
|
||||
gFilterOps[2] = op2;
|
||||
}
|
||||
|
||||
bool physx::PxGetFilterBool()
|
||||
{
|
||||
return gFilterBool;
|
||||
}
|
||||
|
||||
void physx::PxSetFilterBool(const bool enable)
|
||||
{
|
||||
gFilterBool = enable;
|
||||
}
|
||||
|
||||
void physx::PxGetFilterConstants(PxGroupsMask& c0, PxGroupsMask& c1)
|
||||
{
|
||||
c0 = gFilterConstants[0];
|
||||
c1 = gFilterConstants[1];
|
||||
}
|
||||
|
||||
void physx::PxSetFilterConstants(const PxGroupsMask& c0, const PxGroupsMask& c1)
|
||||
{
|
||||
gFilterConstants[0] = c0;
|
||||
gFilterConstants[1] = c1;
|
||||
}
|
||||
|
||||
PxGroupsMask physx::PxGetGroupsMask(const PxActor& actor)
|
||||
{
|
||||
PxFilterData fd;
|
||||
if (getFilterData(actor, fd))
|
||||
return convert(fd);
|
||||
else
|
||||
return PxGroupsMask();
|
||||
}
|
||||
|
||||
void physx::PxSetGroupsMask(PxActor& actor, const PxGroupsMask& mask)
|
||||
{
|
||||
PxFilterData fd = convert(mask);
|
||||
setFilterData<true>(actor, fd);
|
||||
}
|
||||
193
engine/third_party/physx/source/physxextensions/src/ExtDefaultStreams.cpp
vendored
Normal file
193
engine/third_party/physx/source/physxextensions/src/ExtDefaultStreams.cpp
vendored
Normal 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.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "foundation/PxAllocatorCallback.h"
|
||||
#include "foundation/PxMemory.h"
|
||||
#include "foundation/PxBitUtils.h"
|
||||
#include "extensions/PxDefaultStreams.h"
|
||||
|
||||
#include "SnFile.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxDefaultMemoryOutputStream::PxDefaultMemoryOutputStream(PxAllocatorCallback &allocator)
|
||||
: mAllocator (allocator)
|
||||
, mData (NULL)
|
||||
, mSize (0)
|
||||
, mCapacity (0)
|
||||
{
|
||||
}
|
||||
|
||||
PxDefaultMemoryOutputStream::~PxDefaultMemoryOutputStream()
|
||||
{
|
||||
if(mData)
|
||||
mAllocator.deallocate(mData);
|
||||
}
|
||||
|
||||
PxU32 PxDefaultMemoryOutputStream::write(const void* src, PxU32 size)
|
||||
{
|
||||
PxU32 expectedSize = mSize + size;
|
||||
if(expectedSize > mCapacity)
|
||||
{
|
||||
mCapacity = PxMax(PxNextPowerOfTwo(expectedSize), 4096u);
|
||||
|
||||
PxU8* newData = reinterpret_cast<PxU8*>(mAllocator.allocate(mCapacity,"PxDefaultMemoryOutputStream",__FILE__,__LINE__));
|
||||
PX_ASSERT(newData!=NULL);
|
||||
|
||||
PxMemCopy(newData, mData, mSize);
|
||||
if(mData)
|
||||
mAllocator.deallocate(mData);
|
||||
|
||||
mData = newData;
|
||||
}
|
||||
PxMemCopy(mData+mSize, src, size);
|
||||
mSize += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxDefaultMemoryInputData::PxDefaultMemoryInputData(PxU8* data, PxU32 length) :
|
||||
mSize (length),
|
||||
mData (data),
|
||||
mPos (0)
|
||||
{
|
||||
}
|
||||
|
||||
PxU32 PxDefaultMemoryInputData::read(void* dest, PxU32 count)
|
||||
{
|
||||
PxU32 length = PxMin<PxU32>(count, mSize-mPos);
|
||||
PxMemCopy(dest, mData+mPos, length);
|
||||
mPos += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
PxU32 PxDefaultMemoryInputData::getLength() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
void PxDefaultMemoryInputData::seek(PxU32 offset)
|
||||
{
|
||||
mPos = PxMin<PxU32>(mSize, offset);
|
||||
}
|
||||
|
||||
PxU32 PxDefaultMemoryInputData::tell() const
|
||||
{
|
||||
return mPos;
|
||||
}
|
||||
|
||||
PxDefaultFileOutputStream::PxDefaultFileOutputStream(const char* filename)
|
||||
{
|
||||
mFile = NULL;
|
||||
sn::fopen_s(&mFile, filename, "wb");
|
||||
// PT: when this fails, check that:
|
||||
// - the path is correct
|
||||
// - the file does not already exist. If it does, check that it is not write protected.
|
||||
if(NULL == mFile)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL,
|
||||
"Unable to open file %s, errno 0x%x\n",filename,errno);
|
||||
}
|
||||
PX_ASSERT(mFile);
|
||||
}
|
||||
|
||||
PxDefaultFileOutputStream::~PxDefaultFileOutputStream()
|
||||
{
|
||||
if(mFile)
|
||||
fclose(mFile);
|
||||
mFile = NULL;
|
||||
}
|
||||
|
||||
PxU32 PxDefaultFileOutputStream::write(const void* src, PxU32 count)
|
||||
{
|
||||
return mFile ? PxU32(fwrite(src, 1, count, mFile)) : 0;
|
||||
}
|
||||
|
||||
bool PxDefaultFileOutputStream::isValid()
|
||||
{
|
||||
return mFile != NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxDefaultFileInputData::PxDefaultFileInputData(const char* filename)
|
||||
{
|
||||
mFile = NULL;
|
||||
sn::fopen_s(&mFile, filename, "rb");
|
||||
|
||||
if(mFile)
|
||||
{
|
||||
fseek(mFile, 0, SEEK_END);
|
||||
mLength = PxU32(ftell(mFile));
|
||||
fseek(mFile, 0, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PxDefaultFileInputData::~PxDefaultFileInputData()
|
||||
{
|
||||
if(mFile)
|
||||
fclose(mFile);
|
||||
}
|
||||
|
||||
PxU32 PxDefaultFileInputData::read(void* dest, PxU32 count)
|
||||
{
|
||||
PX_ASSERT(mFile);
|
||||
const size_t size = fread(dest, 1, count, mFile);
|
||||
// there should be no assert here since by spec of PxInputStream we can read fewer bytes than expected
|
||||
return PxU32(size);
|
||||
}
|
||||
|
||||
PxU32 PxDefaultFileInputData::getLength() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
void PxDefaultFileInputData::seek(PxU32 pos)
|
||||
{
|
||||
fseek(mFile, long(pos), SEEK_SET);
|
||||
}
|
||||
|
||||
PxU32 PxDefaultFileInputData::tell() const
|
||||
{
|
||||
return PxU32(ftell(mFile));
|
||||
}
|
||||
|
||||
bool PxDefaultFileInputData::isValid() const
|
||||
{
|
||||
return mFile != NULL;
|
||||
}
|
||||
112
engine/third_party/physx/source/physxextensions/src/ExtDeformableSkinning.cpp
vendored
Normal file
112
engine/third_party/physx/source/physxextensions/src/ExtDeformableSkinning.cpp
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
// 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/PxDeformableSkinningExt.h"
|
||||
#include "GuAABBTree.h"
|
||||
#include "foundation/PxMathUtils.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
|
||||
void PxDeformableSkinningExt::initializeInterpolatedVertices(
|
||||
PxTriangleMeshEmbeddingInfo* embeddingInfo,
|
||||
const PxVec3* guideVertices, const PxVec3* guideNormals,
|
||||
const PxU32* guideTriangles, PxU32 numGuideTriangles, const PxVec3* embeddedVertices,
|
||||
PxU32 numEmbeddedVertices)
|
||||
{
|
||||
PX_UNUSED(guideNormals); //The guideNormals could be used for higher quality embedding infos
|
||||
|
||||
PX_SIMD_GUARD
|
||||
|
||||
Gu::TinyBVH bvh;
|
||||
Gu::TinyBVH::constructFromTriangles(guideTriangles, numGuideTriangles, guideVertices, bvh);
|
||||
|
||||
Gu::ClosestDistanceToTrimeshTraversalController traversalController(guideTriangles, guideVertices, bvh.mTree.begin());
|
||||
|
||||
//Implements to most basic variant - lots of room for improvements
|
||||
for (PxU32 i = 0; i < numEmbeddedVertices; ++i)
|
||||
{
|
||||
traversalController.setQueryPoint(embeddedVertices[i]);
|
||||
bvh.Traverse(traversalController);
|
||||
|
||||
const PxU32 closestTriangleid = traversalController.getClosestTriId();
|
||||
|
||||
const PxU32* tri = &guideTriangles[3 * closestTriangleid];
|
||||
const PxVec3& v0 = guideVertices[tri[0]];
|
||||
const PxVec3& v1 = guideVertices[tri[1]];
|
||||
const PxVec3& v2 = guideVertices[tri[2]];
|
||||
|
||||
const PxVec3 closestPoint = traversalController.getClosestPoint();
|
||||
|
||||
PxVec3 triNormal = (v1 - v0).cross(v2 - v0);
|
||||
triNormal.normalize();
|
||||
|
||||
PxVec3 distVec = (embeddedVertices[i] - closestPoint);
|
||||
|
||||
PxReal normalOffset = distVec.dot(triNormal);
|
||||
PxVec3 projPoint = embeddedVertices[i] - normalOffset*triNormal;
|
||||
|
||||
PxVec4 barycentric;
|
||||
PxComputeBarycentric(v0, v1, v2, projPoint, barycentric);
|
||||
|
||||
embeddingInfo[i] = PxTriangleMeshEmbeddingInfo(PxVec2(barycentric.x, barycentric.y), normalOffset, closestTriangleid);
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableSkinningExt::initializeInterpolatedVertices(
|
||||
PxTetrahedronMeshEmbeddingInfo* embeddingInfo,
|
||||
const PxVec3* guideVertices,
|
||||
const PxU32* guideTetrahedra, PxU32 numGuideTetrahedra, const PxVec3* embeddedVertices,
|
||||
PxU32 numEmbeddedVertices )
|
||||
{
|
||||
PX_SIMD_GUARD
|
||||
|
||||
Gu::TinyBVH bvh;
|
||||
Gu::TinyBVH::constructFromTetrahedra(guideTetrahedra, numGuideTetrahedra, guideVertices, bvh);
|
||||
|
||||
Gu::ClosestDistanceToTetmeshTraversalController traversalController(guideTetrahedra, guideVertices, bvh.mTree.begin());
|
||||
|
||||
//Implements to most basic variant - lots of room for improvements
|
||||
for (PxU32 i = 0; i < numEmbeddedVertices; ++i)
|
||||
{
|
||||
traversalController.setQueryPoint(embeddedVertices[i]);
|
||||
bvh.Traverse(traversalController);
|
||||
|
||||
const PxU32 closestTetid = traversalController.getClosestTetId();
|
||||
|
||||
const PxU32* tet = &guideTetrahedra[4 * closestTetid];
|
||||
|
||||
const PxVec3 closestPoint = traversalController.getClosestPoint();
|
||||
PxVec4 barycentric;
|
||||
PxComputeBarycentric(guideVertices[tet[0]], guideVertices[tet[1]], guideVertices[tet[2]], guideVertices[tet[3]], closestPoint, barycentric);
|
||||
|
||||
embeddingInfo[i] = PxTetrahedronMeshEmbeddingInfo(barycentric.getXYZ(), closestTetid);
|
||||
}
|
||||
}
|
||||
|
||||
272
engine/third_party/physx/source/physxextensions/src/ExtDeformableSurfaceExt.cpp
vendored
Normal file
272
engine/third_party/physx/source/physxextensions/src/ExtDeformableSurfaceExt.cpp
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
// 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/PxDeformableSurfaceExt.h"
|
||||
|
||||
#include "PxPhysics.h"
|
||||
#include "cooking/PxCooking.h"
|
||||
#include "cudamanager/PxCudaContext.h"
|
||||
#include "cudamanager/PxCudaContextManager.h"
|
||||
#include "extensions/PxCudaHelpersExt.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void PxDeformableSurfaceExt::copyToDevice(PxDeformableSurface& fm, PxDeformableSurfaceDataFlags flags, PxU32 nbVertices,
|
||||
PxVec4* positionInvMassPinned, PxVec4* velocityPinned, PxVec4* restPositionPinned,
|
||||
CUstream stream)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PxScopedCudaLock _lock(*fm.getCudaContextManager());
|
||||
PxCudaContext* ctx = fm.getCudaContextManager()->getCudaContext();
|
||||
|
||||
if(flags & PxDeformableSurfaceDataFlag::ePOSITION_INVMASS && positionInvMassPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(fm.getPositionInvMassBufferD()), positionInvMassPinned,
|
||||
nbVertices * sizeof(PxVec4), stream);
|
||||
|
||||
if(flags & PxDeformableSurfaceDataFlag::eVELOCITY && velocityPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(fm.getVelocityBufferD()), velocityPinned,
|
||||
nbVertices * sizeof(PxVec4), stream);
|
||||
|
||||
if(flags & PxDeformableSurfaceDataFlag::eREST_POSITION && restPositionPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(fm.getRestPositionBufferD()), restPositionPinned,
|
||||
nbVertices * sizeof(PxVec4), stream);
|
||||
|
||||
if(stream == 0)
|
||||
ctx->streamSynchronize(stream);
|
||||
#else
|
||||
PX_UNUSED(nbVertices);
|
||||
PX_UNUSED(positionInvMassPinned);
|
||||
PX_UNUSED(velocityPinned);
|
||||
PX_UNUSED(restPositionPinned);
|
||||
PX_UNUSED(stream);
|
||||
#endif
|
||||
fm.markDirty(flags);
|
||||
}
|
||||
|
||||
PxU32 PxDeformableSurfaceExt::allocateAndInitializeHostMirror(PxDeformableSurface& deformableSurface, const PxVec3* positions,
|
||||
const PxVec3* velocities, const PxVec3* restPositions,
|
||||
float clothMass, const PxTransform& transform,
|
||||
PxCudaContextManager* cudaContextManager,
|
||||
PxVec4*& positionInvMassPinned, PxVec4*& velocityPinned,
|
||||
PxVec4*& restPositionPinned)
|
||||
{
|
||||
PX_ASSERT(cudaContextManager != NULL);
|
||||
|
||||
PxShape* shape = deformableSurface.getShape();
|
||||
if(shape == NULL)
|
||||
return 0;
|
||||
|
||||
const PxTriangleMeshGeometry& triangleMeshGeometry = static_cast<const PxTriangleMeshGeometry&>(shape->getGeometry());
|
||||
|
||||
PxTriangleMesh* triangleMesh = triangleMeshGeometry.triangleMesh;
|
||||
if(triangleMesh == NULL)
|
||||
return 0;
|
||||
|
||||
const PxU32 nbVertices = triangleMesh->getNbVertices();
|
||||
const PxVec3* const initPositions = positions ? positions : triangleMesh->getVertices(); // triangle mesh may represent "rest configuration".
|
||||
|
||||
allocateAndInitializeHostMirror(initPositions, velocities, restPositions, nbVertices, clothMass, transform,
|
||||
cudaContextManager, positionInvMassPinned, velocityPinned, restPositionPinned);
|
||||
|
||||
return nbVertices;
|
||||
}
|
||||
|
||||
PxU32 PxDeformableSurfaceExt::allocateAndInitializeHostMirror(const PxVec3* positions, const PxVec3* velocities,
|
||||
const PxVec3* restPositions, PxU32 nbVertices, float clothMass,
|
||||
const PxTransform& transform,
|
||||
PxCudaContextManager* cudaContextManager,
|
||||
PxVec4*& positionInvMassPinned, PxVec4*& velocityPinned,
|
||||
PxVec4*& restPositionPinned)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
positionInvMassPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbVertices);
|
||||
velocityPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbVertices);
|
||||
restPositionPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbVertices);
|
||||
#else
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
|
||||
float invMass = static_cast<float>(nbVertices) / clothMass;
|
||||
|
||||
for(PxU32 i = 0; i < nbVertices; ++i)
|
||||
{
|
||||
PxVec3 pos = positions[i];
|
||||
pos = transform.transform(pos);
|
||||
|
||||
positionInvMassPinned[i] = PxVec4(pos.x, pos.y, pos.z, invMass);
|
||||
velocityPinned[i] = velocities ? PxVec4(velocities[i].x, velocities[i].y, velocities[i].z, invMass)
|
||||
: PxVec4(0.f, 0.f, 0.f, invMass);
|
||||
restPositionPinned[i] = restPositions
|
||||
? PxVec4(restPositions[i].x, restPositions[i].y, restPositions[i].z, invMass)
|
||||
: PxVec4(pos.x, pos.y, pos.z, invMass);
|
||||
}
|
||||
|
||||
return nbVertices;
|
||||
}
|
||||
|
||||
void PxDeformableSurfaceExt::distributeTriangleMassToVertices(PxDeformableSurface& deformableSurface, const PxReal* triangleMasses,
|
||||
PxVec4* positionInvMassPinned)
|
||||
{
|
||||
PxShape* shape = deformableSurface.getShape();
|
||||
const PxTriangleMeshGeometry& triangleMeshGeometry = static_cast<const PxTriangleMeshGeometry&>(shape->getGeometry());
|
||||
PxTriangleMesh* triangleMesh = triangleMeshGeometry.triangleMesh;
|
||||
const PxU32 numVerts = triangleMesh->getNbVertices();
|
||||
const PxU32 numTriangles = triangleMesh->getNbTriangles();
|
||||
|
||||
PxArray<PxReal> vertexMasses(numVerts, 0.f);
|
||||
const bool has16bitIndices = triangleMesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES;
|
||||
const void* indices = triangleMesh->getTriangles();
|
||||
|
||||
PxReal oneThird = 1.0f / 3.0f;
|
||||
for(PxU32 i = 0; i < numTriangles; ++i)
|
||||
{
|
||||
PxU32 vref0, vref1, vref2;
|
||||
if (has16bitIndices)
|
||||
{
|
||||
vref0 = ((const PxU16*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU16*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU16*)indices)[i * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vref0 = ((const PxU32*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU32*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU32*)indices)[i * 3 + 2];
|
||||
}
|
||||
|
||||
PxReal vertexMass = oneThird * triangleMasses[i];
|
||||
|
||||
vertexMasses[vref0] += vertexMass;
|
||||
vertexMasses[vref1] += vertexMass;
|
||||
vertexMasses[vref2] += vertexMass;
|
||||
}
|
||||
|
||||
for(PxU32 i = 0; i < numVerts; ++i)
|
||||
{
|
||||
PxReal invMass = 1.f / vertexMasses[i];
|
||||
positionInvMassPinned[i].w = invMass;
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableSurfaceExt::distributeDensityToVertices(PxDeformableSurface& deformableSurface, PxReal massPerVolume, PxReal clothThickness,
|
||||
PxVec4* positionInvMassPinned)
|
||||
{
|
||||
const PxReal massPerArea = massPerVolume * clothThickness;
|
||||
|
||||
PxShape* shape = deformableSurface.getShape();
|
||||
const PxTriangleMeshGeometry& triangleMeshGeometry = static_cast<const PxTriangleMeshGeometry&>(shape->getGeometry());
|
||||
PxTriangleMesh* triangleMesh = triangleMeshGeometry.triangleMesh;
|
||||
const PxU32 numVerts = triangleMesh->getNbVertices();
|
||||
const PxU32 numTriangles = triangleMesh->getNbTriangles();
|
||||
|
||||
PxArray<PxReal> vertexMasses(numVerts, 0.f);
|
||||
const bool has16bitIndices = triangleMesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES;
|
||||
const void* indices = triangleMesh->getTriangles();
|
||||
const PxVec3* vertices = triangleMesh->getVertices();
|
||||
|
||||
PxReal oneThird = 1.0f / 3.0f;
|
||||
for (PxU32 i = 0; i < numTriangles; ++i)
|
||||
{
|
||||
PxU32 vref0, vref1, vref2;
|
||||
if (has16bitIndices)
|
||||
{
|
||||
vref0 = ((const PxU16*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU16*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU16*)indices)[i * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vref0 = ((const PxU32*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU32*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU32*)indices)[i * 3 + 2];
|
||||
}
|
||||
|
||||
const PxVec3 a = vertices[vref0];
|
||||
const PxVec3 b = vertices[vref1];
|
||||
const PxVec3 c = vertices[vref2];
|
||||
|
||||
PxReal triangleArea = 0.5f * (b - a).cross(c - a).magnitude();
|
||||
PxReal triangleMass = massPerArea* triangleArea;
|
||||
PxReal vertexMass = oneThird * triangleMass;
|
||||
|
||||
vertexMasses[vref0] += vertexMass;
|
||||
vertexMasses[vref1] += vertexMass;
|
||||
vertexMasses[vref2] += vertexMass;
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < numVerts; ++i)
|
||||
{
|
||||
PxReal invMass = 1.f / vertexMasses[i];
|
||||
positionInvMassPinned[i].w = invMass;
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableSurfaceExt::distributeMassToVertices(PxDeformableSurface& deformableSurface, PxReal totalMass,
|
||||
PxVec4* positionInvMassPinned)
|
||||
{
|
||||
PxShape* shape = deformableSurface.getShape();
|
||||
const PxTriangleMeshGeometry& triangleMeshGeometry = static_cast<const PxTriangleMeshGeometry&>(shape->getGeometry());
|
||||
PxTriangleMesh* triangleMesh = triangleMeshGeometry.triangleMesh;
|
||||
|
||||
PxReal totalArea = 0.0f;
|
||||
|
||||
const PxU32 numVerts = triangleMesh->getNbVertices();
|
||||
const PxU32 numTriangles = triangleMesh->getNbTriangles();
|
||||
|
||||
PxArray<PxReal> vertexMasses(numVerts, 0.f);
|
||||
const bool has16bitIndices = triangleMesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES;
|
||||
const void* indices = triangleMesh->getTriangles();
|
||||
const PxVec3* vertices = triangleMesh->getVertices();
|
||||
|
||||
for (PxU32 i = 0; i < numTriangles; ++i)
|
||||
{
|
||||
PxU32 vref0, vref1, vref2;
|
||||
if (has16bitIndices)
|
||||
{
|
||||
vref0 = ((const PxU16*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU16*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU16*)indices)[i * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vref0 = ((const PxU32*)indices)[i * 3 + 0];
|
||||
vref1 = ((const PxU32*)indices)[i * 3 + 1];
|
||||
vref2 = ((const PxU32*)indices)[i * 3 + 2];
|
||||
}
|
||||
const PxVec3 a = vertices[vref0];
|
||||
const PxVec3 b = vertices[vref1];
|
||||
const PxVec3 c = vertices[vref2];
|
||||
|
||||
totalArea += (b - a).cross(c - a).magnitude();
|
||||
}
|
||||
totalArea *= 0.5f;
|
||||
|
||||
PxReal massPerArea = totalMass / totalArea;
|
||||
const PxReal clothThickness = 1.0f; //Value does not matter since it cancels out
|
||||
distributeDensityToVertices(deformableSurface, massPerArea / clothThickness, clothThickness, positionInvMassPinned);
|
||||
}
|
||||
633
engine/third_party/physx/source/physxextensions/src/ExtDeformableVolumeExt.cpp
vendored
Normal file
633
engine/third_party/physx/source/physxextensions/src/ExtDeformableVolumeExt.cpp
vendored
Normal file
@@ -0,0 +1,633 @@
|
||||
// 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/PxDeformableVolumeExt.h"
|
||||
#include "extensions/PxTetMakerExt.h"
|
||||
|
||||
#include "GuTetrahedronMesh.h"
|
||||
#include "GuTetrahedronMeshUtils.h"
|
||||
#include "cooking/PxCooking.h"
|
||||
#include "PxPhysics.h"
|
||||
#include "extensions/PxRemeshingExt.h"
|
||||
#include "cudamanager/PxCudaContextManager.h"
|
||||
#include "cudamanager/PxCudaContext.h"
|
||||
#include "extensions/PxCudaHelpersExt.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Cm;
|
||||
|
||||
//Computes the volume of the simulation mesh defined as the sum of the volumes of all tetrahedra
|
||||
static PxReal computeSimulationMeshVolume(PxDeformableVolume& deformableVolume, PxVec4* simPositions)
|
||||
{
|
||||
const PxU32 numTetsGM = deformableVolume.getSimulationMesh()->getNbTetrahedrons();
|
||||
|
||||
const PxU32* tetPtr32 = reinterpret_cast<const PxU32*>(deformableVolume.getSimulationMesh()->getTetrahedrons());
|
||||
const PxU16* tetPtr16 = reinterpret_cast<const PxU16*>(deformableVolume.getSimulationMesh()->getTetrahedrons());
|
||||
const bool sixteenBit = deformableVolume.getSimulationMesh()->getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES;
|
||||
|
||||
PxReal volume = 0;
|
||||
for (PxU32 i = 0; i < numTetsGM; ++i)
|
||||
{
|
||||
PxVec4& x0 = simPositions[sixteenBit ? tetPtr16[4 * i] : tetPtr32[4 * i]];
|
||||
PxVec4& x1 = simPositions[sixteenBit ? tetPtr16[4 * i + 1] : tetPtr32[4 * i + 1]];
|
||||
PxVec4& x2 = simPositions[sixteenBit ? tetPtr16[4 * i + 2] : tetPtr32[4 * i + 2]];
|
||||
PxVec4& x3 = simPositions[sixteenBit ? tetPtr16[4 * i + 3] : tetPtr32[4 * i + 3]];
|
||||
|
||||
const PxVec3 u1 = x1.getXYZ() - x0.getXYZ();
|
||||
const PxVec3 u2 = x2.getXYZ() - x0.getXYZ();
|
||||
const PxVec3 u3 = x3.getXYZ() - x0.getXYZ();
|
||||
|
||||
PxMat33 Q = PxMat33(u1, u2, u3);
|
||||
|
||||
const PxReal det = Q.getDeterminant();
|
||||
volume += det;
|
||||
}
|
||||
volume /= 6.0f;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
//Recomputes the volume associated with a vertex. Every tetrahedron distributes a quarter of its volume to
|
||||
//each vertex it is connected to. Finally the volume stored for every vertex is inverted.
|
||||
static void updateNodeInverseVolumes(PxDeformableVolume& deformableVolume, PxVec4* simPositions)
|
||||
{
|
||||
const PxU32 numVertsGM = deformableVolume.getSimulationMesh()->getNbVertices();
|
||||
const PxU32 numTetsGM = deformableVolume.getSimulationMesh()->getNbTetrahedrons();
|
||||
|
||||
const PxU32* tetPtr32 = reinterpret_cast<const PxU32*>(deformableVolume.getSimulationMesh()->getTetrahedrons());
|
||||
const PxU16* tetPtr16 = reinterpret_cast<const PxU16*>(deformableVolume.getSimulationMesh()->getTetrahedrons());
|
||||
const bool sixteenBit = deformableVolume.getSimulationMesh()->getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES;
|
||||
|
||||
for (PxU32 i = 0; i < numVertsGM; ++i)
|
||||
simPositions[i].w = 0.0f;
|
||||
|
||||
for (PxU32 i = 0; i < numTetsGM; ++i)
|
||||
{
|
||||
PxVec4& x0 = simPositions[sixteenBit ? tetPtr16[4 * i] : tetPtr32[4 * i]];
|
||||
PxVec4& x1 = simPositions[sixteenBit ? tetPtr16[4 * i + 1] : tetPtr32[4 * i + 1]];
|
||||
PxVec4& x2 = simPositions[sixteenBit ? tetPtr16[4 * i + 2] : tetPtr32[4 * i + 2]];
|
||||
PxVec4& x3 = simPositions[sixteenBit ? tetPtr16[4 * i + 3] : tetPtr32[4 * i + 3]];
|
||||
|
||||
const PxVec3 u1 = x1.getXYZ() - x0.getXYZ();
|
||||
const PxVec3 u2 = x2.getXYZ() - x0.getXYZ();
|
||||
const PxVec3 u3 = x3.getXYZ() - x0.getXYZ();
|
||||
|
||||
PxMat33 Q = PxMat33(u1, u2, u3);
|
||||
|
||||
//det should be positive
|
||||
const PxReal det = Q.getDeterminant();
|
||||
|
||||
if (det <= 1.e-9f)
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "updateNodeInverseVolumes(): tetrahedron is degenerate or inverted");
|
||||
|
||||
//Distribute one quarter of the volume to each vertex the tetrahedron is connected to
|
||||
const PxReal volume = det / 6.0f;
|
||||
x0.w += 0.25f * volume;
|
||||
x1.w += 0.25f * volume;
|
||||
x2.w += 0.25f * volume;
|
||||
x3.w += 0.25f * volume;
|
||||
}
|
||||
|
||||
//Invert the volumes stored per vertex and copy it to the velocity buffer
|
||||
for (PxU32 i = 0; i < numVertsGM; ++i)
|
||||
{
|
||||
if (simPositions[i].w > 0)
|
||||
{
|
||||
simPositions[i].w = 1.0f / simPositions[i].w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::updateMass(PxDeformableVolume& deformableVolume, const PxReal density, const PxReal maxInvMassRatio, PxVec4* simPositionsPinned)
|
||||
{
|
||||
//Inverse volumes are recomputed to ensure that multiple subsequent calls of this method lead to correct results
|
||||
updateNodeInverseVolumes(deformableVolume, simPositionsPinned);
|
||||
|
||||
const PxU32 numVertsGM = deformableVolume.getSimulationMesh()->getNbVertices();
|
||||
|
||||
PxReal minInvMass = PX_MAX_F32, maxInvMass = 0.f;
|
||||
for (PxU32 i = 0; i < numVertsGM; ++i)
|
||||
{
|
||||
const PxVec4& vert = simPositionsPinned[i];
|
||||
PxReal invMass = vert.w;
|
||||
invMass = invMass / (density);
|
||||
minInvMass = invMass > 0.f ? PxMin(invMass, minInvMass) : minInvMass;
|
||||
maxInvMass = PxMax(invMass, maxInvMass);
|
||||
simPositionsPinned[i] = PxVec4(vert.x, vert.y, vert.z, invMass);
|
||||
}
|
||||
if (minInvMass != PX_MAX_F32)
|
||||
{
|
||||
const PxReal ratio = maxInvMass / minInvMass;
|
||||
if (ratio > maxInvMassRatio)
|
||||
{
|
||||
//Clamp the upper limit...
|
||||
maxInvMass = minInvMass * maxInvMassRatio;
|
||||
for (PxU32 i = 0; i < numVertsGM; ++i)
|
||||
{
|
||||
PxVec4& posInvMass = simPositionsPinned[i];
|
||||
posInvMass.w = PxMin(posInvMass.w, maxInvMass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::setMass(PxDeformableVolume& deformableVolume, const PxReal mass, const PxReal maxInvMassRatio, PxVec4* simPositionsPinned)
|
||||
{
|
||||
//Compute the density such that density times volume is equal to the desired mass
|
||||
updateMass(deformableVolume, mass / computeSimulationMeshVolume(deformableVolume, simPositionsPinned), maxInvMassRatio, simPositionsPinned);
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::transform(PxDeformableVolume& deformableVolume, const PxTransform& transform, const PxReal scale, PxVec4* simPositionsPinned, PxVec4* simVelocitiesPinned, PxVec4* collPositionsPinned, PxVec4* restPositionsPinned)
|
||||
{
|
||||
const PxU32 numVertsGM = deformableVolume.getSimulationMesh()->getNbVertices();
|
||||
const PxU32 numVerts = deformableVolume.getCollisionMesh()->getNbVertices();
|
||||
|
||||
for (PxU32 i = 0; i < numVertsGM; ++i)
|
||||
{
|
||||
const PxVec4 tpInvMass = simPositionsPinned[i];
|
||||
const PxReal invMass = tpInvMass.w;
|
||||
PxVec3 vert = PxVec3(tpInvMass.x * scale, tpInvMass.y * scale, tpInvMass.z * scale);
|
||||
//Transform the vertex position and keep the inverse mass
|
||||
vert = transform.transform(vert);
|
||||
simPositionsPinned[i] = PxVec4(vert.x, vert.y, vert.z, invMass);
|
||||
|
||||
PxVec4 vel = simVelocitiesPinned[i];
|
||||
PxVec3 v = PxVec3(vel.x * scale, vel.y * scale, vel.z * scale);
|
||||
//Velocities are translation invariant, therefore only the direction needs to get adjusted.
|
||||
//The inverse mass is stored as well to optimize memory access on the GPU
|
||||
v = transform.rotate(v);
|
||||
simVelocitiesPinned[i] = PxVec4(v.x, v.y, v.z, invMass);
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < numVerts; ++i)
|
||||
{
|
||||
restPositionsPinned[i] = PxVec4(restPositionsPinned[i].x*scale, restPositionsPinned[i].y*scale, restPositionsPinned[i].z*scale, 1.f);
|
||||
|
||||
const PxVec4 tpInvMass = collPositionsPinned[i];
|
||||
PxVec3 vert = PxVec3(tpInvMass.x * scale, tpInvMass.y * scale, tpInvMass.z * scale);
|
||||
vert = transform.transform(vert);
|
||||
collPositionsPinned[i] = PxVec4(vert.x, vert.y, vert.z, tpInvMass.w);
|
||||
}
|
||||
|
||||
PxMat33* tetraRestPosesGM = static_cast<Gu::DeformableVolumeAuxData*>(deformableVolume.getDeformableVolumeAuxData())->getGridModelRestPosesFast(); // reinterpret_cast<PxMat33*>(simMeshData->deformableVolumeAuxData.getGridModelRestPosesFast());
|
||||
const PxU32 nbTetraGM = deformableVolume.getSimulationMesh()->getNbTetrahedrons();
|
||||
|
||||
const PxReal invScale = 1.0f / scale;
|
||||
for (PxU32 i = 0; i < nbTetraGM; ++i)
|
||||
{
|
||||
PxMat33& m = tetraRestPosesGM[i];
|
||||
//Scale the rest pose
|
||||
m.column0 = m.column0 * invScale;
|
||||
m.column1 = m.column1 * invScale;
|
||||
m.column2 = m.column2 * invScale;
|
||||
|
||||
//The rest pose is translation invariant, it only needs be rotated
|
||||
PxVec3 row0 = transform.rotateInv(PxVec3(m.column0.x, m.column1.x, m.column2.x));
|
||||
PxVec3 row1 = transform.rotateInv(PxVec3(m.column0.y, m.column1.y, m.column2.y));
|
||||
PxVec3 row2 = transform.rotateInv(PxVec3(m.column0.z, m.column1.z, m.column2.z));
|
||||
|
||||
m.column0 = PxVec3(row0.x, row1.x, row2.x);
|
||||
m.column1 = PxVec3(row0.y, row1.y, row2.y);
|
||||
m.column2 = PxVec3(row0.z, row1.z, row2.z);
|
||||
}
|
||||
|
||||
|
||||
PxMat33* tetraRestPoses = static_cast<Gu::DeformableVolumeAuxData*>(deformableVolume.getDeformableVolumeAuxData())->getRestPosesFast(); // reinterpret_cast<PxMat33*>(simMeshData->deformableVolumeAuxData.getGridModelRestPosesFast());
|
||||
const PxU32 nbTetra = deformableVolume.getCollisionMesh()->getNbTetrahedrons();
|
||||
|
||||
for (PxU32 i = 0; i < nbTetra; ++i)
|
||||
{
|
||||
PxMat33& m = tetraRestPoses[i];
|
||||
//Scale the rest pose
|
||||
m.column0 = m.column0 * invScale;
|
||||
m.column1 = m.column1 * invScale;
|
||||
m.column2 = m.column2 * invScale;
|
||||
|
||||
//The rest pose is translation invariant, it only needs be rotated
|
||||
PxVec3 row0 = transform.rotateInv(PxVec3(m.column0.x, m.column1.x, m.column2.x));
|
||||
PxVec3 row1 = transform.rotateInv(PxVec3(m.column0.y, m.column1.y, m.column2.y));
|
||||
PxVec3 row2 = transform.rotateInv(PxVec3(m.column0.z, m.column1.z, m.column2.z));
|
||||
|
||||
m.column0 = PxVec3(row0.x, row1.x, row2.x);
|
||||
m.column1 = PxVec3(row0.y, row1.y, row2.y);
|
||||
m.column2 = PxVec3(row0.z, row1.z, row2.z);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::updateEmbeddedCollisionMesh(PxDeformableVolume& deformableVolume, PxVec4* simPositionsPinned, PxVec4* collPositionsPinned)
|
||||
{
|
||||
Gu::DeformableVolumeAuxData* deformableVolumeAuxData = static_cast<Gu::DeformableVolumeAuxData*>(deformableVolume.getDeformableVolumeAuxData());
|
||||
const PxU32* remapTable = deformableVolumeAuxData->mVertsRemapInGridModel;
|
||||
PxReal* barycentricCoordinates = deformableVolumeAuxData->mVertsBarycentricInGridModel;
|
||||
|
||||
PxTetrahedronMesh* simMesh = deformableVolume.getSimulationMesh();
|
||||
const void* tets = simMesh->getTetrahedrons();
|
||||
const PxU32* tets32 = static_cast<const PxU32*>(tets);
|
||||
const PxU16* tets16 = static_cast<const PxU16*>(tets);
|
||||
|
||||
bool sixteenBit = simMesh->getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES;
|
||||
|
||||
const PxU32 numVerts = deformableVolume.getCollisionMesh()->getNbVertices();
|
||||
for (PxU32 i = 0; i < numVerts; ++i)
|
||||
{
|
||||
//The tetrahedra are ordered differently on the GPU, therefore the index must be taken from the remap table
|
||||
const PxU32 tetrahedronIdx = remapTable[i];
|
||||
const PxVec4 p0 = simPositionsPinned[sixteenBit ? tets16[4 * tetrahedronIdx] : tets32[4 * tetrahedronIdx]];
|
||||
const PxVec4 p1 = simPositionsPinned[sixteenBit ? tets16[4 * tetrahedronIdx + 1] : tets32[4 * tetrahedronIdx + 1]];
|
||||
const PxVec4 p2 = simPositionsPinned[sixteenBit ? tets16[4 * tetrahedronIdx + 2] : tets32[4 * tetrahedronIdx + 2]];
|
||||
const PxVec4 p3 = simPositionsPinned[sixteenBit ? tets16[4 * tetrahedronIdx + 3] : tets32[4 * tetrahedronIdx + 3]];
|
||||
|
||||
const PxReal* barycentric = &barycentricCoordinates[4*i];
|
||||
|
||||
//Compute the embedded position as a weigted sum of vertices from the simulation mesh
|
||||
//This ensures that all tranformations and scale changes applied to the simulation mesh get transferred
|
||||
//to the collision mesh
|
||||
collPositionsPinned[i] = p0 * barycentric[0] + p1 * barycentric[1] + p2 * barycentric[2] + p3 * barycentric[3];
|
||||
collPositionsPinned[i].w = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::copyToDevice(PxDeformableVolume& deformableVolume, PxDeformableVolumeDataFlags flags, PxVec4* simPositionsPinned, PxVec4* simVelocitiesPinned, PxVec4* collPositionsPinned, PxVec4* restPositionsPinned, CUstream stream)
|
||||
{
|
||||
//Updating the collision mesh's vertices ensures that simulation mesh and collision mesh are
|
||||
//represented in the same coordinate system and the same scale
|
||||
updateEmbeddedCollisionMesh(deformableVolume, simPositionsPinned, collPositionsPinned);
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PxScopedCudaLock _lock(*deformableVolume.getCudaContextManager());
|
||||
PxCudaContext* ctx = deformableVolume.getCudaContextManager()->getCudaContext();
|
||||
|
||||
if (flags & PxDeformableVolumeDataFlag::ePOSITION_INVMASS && collPositionsPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(deformableVolume.getPositionInvMassBufferD()), collPositionsPinned, deformableVolume.getCollisionMesh()->getNbVertices() * sizeof(PxVec4), stream);
|
||||
|
||||
if (flags & PxDeformableVolumeDataFlag::eREST_POSITION_INVMASS && restPositionsPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(deformableVolume.getRestPositionBufferD()), restPositionsPinned, deformableVolume.getCollisionMesh()->getNbVertices() * sizeof(PxVec4), stream);
|
||||
|
||||
if (flags & PxDeformableVolumeDataFlag::eSIM_POSITION_INVMASS && simPositionsPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(deformableVolume.getSimPositionInvMassBufferD()), simPositionsPinned, deformableVolume.getSimulationMesh()->getNbVertices() * sizeof(PxVec4), stream);
|
||||
|
||||
if (flags & PxDeformableVolumeDataFlag::eSIM_VELOCITY && simVelocitiesPinned)
|
||||
ctx->memcpyHtoDAsync(reinterpret_cast<CUdeviceptr>(deformableVolume.getSimVelocityBufferD()), simVelocitiesPinned, deformableVolume.getSimulationMesh()->getNbVertices() * sizeof(PxVec4), stream);
|
||||
|
||||
// we need to synchronize if the stream is the default argument.
|
||||
if (stream == 0)
|
||||
{
|
||||
ctx->streamSynchronize(stream);
|
||||
}
|
||||
#else
|
||||
PX_UNUSED(restPositionsPinned);
|
||||
PX_UNUSED(simVelocitiesPinned);
|
||||
PX_UNUSED(stream);
|
||||
#endif
|
||||
|
||||
deformableVolume.markDirty(flags);
|
||||
}
|
||||
|
||||
PxDeformableVolumeMesh* PxDeformableVolumeExt::createDeformableVolumeMesh(const PxCookingParams& params, const PxSimpleTriangleMesh& surfaceMesh, PxU32 numVoxelsAlongLongestAABBAxis, PxInsertionCallback& insertionCallback, const bool validate)
|
||||
{
|
||||
//Compute collision mesh
|
||||
physx::PxArray<physx::PxVec3> collisionMeshVertices;
|
||||
physx::PxArray<physx::PxU32> collisionMeshIndices;
|
||||
if (!PxTetMaker::createConformingTetrahedronMesh(surfaceMesh, collisionMeshVertices, collisionMeshIndices, validate))
|
||||
return NULL;
|
||||
PxTetrahedronMeshDesc meshDesc(collisionMeshVertices, collisionMeshIndices);
|
||||
|
||||
//Compute simulation mesh
|
||||
physx::PxArray<physx::PxI32> vertexToTet;
|
||||
vertexToTet.resize(meshDesc.points.count);
|
||||
physx::PxArray<physx::PxVec3> simulationMeshVertices;
|
||||
physx::PxArray<physx::PxU32> simulationMeshIndices;
|
||||
PxTetMaker::createVoxelTetrahedronMesh(meshDesc, numVoxelsAlongLongestAABBAxis, simulationMeshVertices, simulationMeshIndices, vertexToTet.begin());
|
||||
PxTetrahedronMeshDesc simMeshDesc(simulationMeshVertices, simulationMeshIndices, PxTetrahedronMeshDesc::PxMeshFormat::eHEX_MESH);
|
||||
PxDeformableVolumeSimulationDataDesc simDesc(vertexToTet);
|
||||
|
||||
physx::PxDeformableVolumeMesh* deformableVolumeMesh = PxCreateDeformableVolumeMesh(params, simMeshDesc, meshDesc, simDesc, insertionCallback);
|
||||
|
||||
return deformableVolumeMesh;
|
||||
}
|
||||
|
||||
PxDeformableVolumeMesh* PxDeformableVolumeExt::createDeformableVolumeMeshNoVoxels(const PxCookingParams& params, const PxSimpleTriangleMesh& surfaceMesh, PxInsertionCallback& insertionCallback, PxReal maxWeightRatioInTet, const bool validate)
|
||||
{
|
||||
PxCookingParams p = params;
|
||||
p.maxWeightRatioInTet = maxWeightRatioInTet;
|
||||
|
||||
physx::PxArray<physx::PxVec3> collisionMeshVertices;
|
||||
physx::PxArray<physx::PxU32> collisionMeshIndices;
|
||||
if (!PxTetMaker::createConformingTetrahedronMesh(surfaceMesh, collisionMeshVertices, collisionMeshIndices, validate))
|
||||
return NULL;
|
||||
PxTetrahedronMeshDesc meshDesc(collisionMeshVertices, collisionMeshIndices);
|
||||
PxDeformableVolumeSimulationDataDesc simDesc;
|
||||
|
||||
physx::PxDeformableVolumeMesh* deformableVolumeMesh = PxCreateDeformableVolumeMesh(p, meshDesc, meshDesc, simDesc, insertionCallback);
|
||||
|
||||
return deformableVolumeMesh;
|
||||
}
|
||||
|
||||
PxDeformableVolume* PxDeformableVolumeExt::createDeformableVolumeFromMesh(PxDeformableVolumeMesh* deformableVolumeMesh, const PxTransform& transform, const PxDeformableVolumeMaterial& material, PxCudaContextManager& cudaContextManager,
|
||||
PxReal density, PxReal scale)
|
||||
{
|
||||
PxDeformableVolume* deformableVolume = PxGetPhysics().createDeformableVolume(cudaContextManager);
|
||||
if (deformableVolume)
|
||||
{
|
||||
PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE;
|
||||
|
||||
|
||||
PxTetrahedronMeshGeometry geometry(deformableVolumeMesh->getCollisionMesh());
|
||||
PxDeformableVolumeMaterial* materialPointer = const_cast<PxDeformableVolumeMaterial*>(&material);
|
||||
PxShape* shape = PxGetPhysics().createShape(geometry, &materialPointer, 1, true, shapeFlags);
|
||||
if (shape)
|
||||
{
|
||||
deformableVolume->attachShape(*shape);
|
||||
}
|
||||
deformableVolume->attachSimulationMesh(*deformableVolumeMesh->getSimulationMesh(), *deformableVolumeMesh->getDeformableVolumeAuxData());
|
||||
|
||||
PxVec4* simPositionInvMassPinned;
|
||||
PxVec4* simVelocityPinned;
|
||||
PxVec4* collPositionInvMassPinned;
|
||||
PxVec4* restPositionPinned;
|
||||
|
||||
PxDeformableVolumeExt::allocateAndInitializeHostMirror(*deformableVolume, &cudaContextManager, simPositionInvMassPinned, simVelocityPinned, collPositionInvMassPinned, restPositionPinned);
|
||||
|
||||
const PxReal maxInvMassRatio = 50.f;
|
||||
|
||||
PxDeformableVolumeExt::transform(*deformableVolume, transform, scale, simPositionInvMassPinned, simVelocityPinned, collPositionInvMassPinned, restPositionPinned);
|
||||
PxDeformableVolumeExt::updateMass(*deformableVolume, density, maxInvMassRatio, simPositionInvMassPinned);
|
||||
PxDeformableVolumeExt::copyToDevice(*deformableVolume, PxDeformableVolumeDataFlag::eALL, simPositionInvMassPinned, simVelocityPinned, collPositionInvMassPinned, restPositionPinned);
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PxCudaContextManager* mgr = &cudaContextManager;
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mgr, simPositionInvMassPinned);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mgr, simVelocityPinned);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mgr, collPositionInvMassPinned);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mgr, restPositionPinned)
|
||||
#endif
|
||||
}
|
||||
return deformableVolume;
|
||||
}
|
||||
|
||||
PxDeformableVolume* PxDeformableVolumeExt::createDeformableVolumeBox(const PxTransform& transform, const PxVec3& boxDimensions, const PxDeformableVolumeMaterial& material,
|
||||
PxCudaContextManager& cudaContextManager, PxReal maxEdgeLength, PxReal density, PxU32 numVoxelsAlongLongestAABBAxis, PxReal scale)
|
||||
{
|
||||
PxArray<PxVec3> triVerts;
|
||||
triVerts.reserve(8);
|
||||
triVerts.pushBack(PxVec3(0.5f, -0.5f, -0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(0.5f, -0.5f, 0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(-0.5f, -0.5f, 0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(-0.5f, -0.5f, -0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(0.5f, 0.5f, -0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(0.5f, 0.5f, 0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(-0.5f, 0.5f, 0.5f).multiply(boxDimensions));
|
||||
triVerts.pushBack(PxVec3(-0.5f, 0.5f, -0.5f).multiply(boxDimensions));
|
||||
|
||||
PxArray<PxU32> triIndices;
|
||||
triIndices.reserve(12 * 3);
|
||||
triIndices.pushBack(1); triIndices.pushBack(2); triIndices.pushBack(3);
|
||||
triIndices.pushBack(7); triIndices.pushBack(6); triIndices.pushBack(5);
|
||||
triIndices.pushBack(4); triIndices.pushBack(5); triIndices.pushBack(1);
|
||||
triIndices.pushBack(5); triIndices.pushBack(6); triIndices.pushBack(2);
|
||||
|
||||
triIndices.pushBack(2); triIndices.pushBack(6); triIndices.pushBack(7);
|
||||
triIndices.pushBack(0); triIndices.pushBack(3); triIndices.pushBack(7);
|
||||
triIndices.pushBack(0); triIndices.pushBack(1); triIndices.pushBack(3);
|
||||
triIndices.pushBack(4); triIndices.pushBack(7); triIndices.pushBack(5);
|
||||
|
||||
triIndices.pushBack(0); triIndices.pushBack(4); triIndices.pushBack(1);
|
||||
triIndices.pushBack(1); triIndices.pushBack(5); triIndices.pushBack(2);
|
||||
triIndices.pushBack(3); triIndices.pushBack(2); triIndices.pushBack(7);
|
||||
triIndices.pushBack(4); triIndices.pushBack(0); triIndices.pushBack(7);
|
||||
|
||||
if (maxEdgeLength > 0.0f)
|
||||
PxRemeshingExt::limitMaxEdgeLength(triIndices, triVerts, maxEdgeLength, 3);
|
||||
|
||||
PxSimpleTriangleMesh surfaceMesh;
|
||||
surfaceMesh.points.count = triVerts.size();
|
||||
surfaceMesh.points.data = triVerts.begin();
|
||||
surfaceMesh.triangles.count = triIndices.size() / 3;
|
||||
surfaceMesh.triangles.data = triIndices.begin();
|
||||
|
||||
PxTolerancesScale tolerancesScale;
|
||||
PxCookingParams params(tolerancesScale);
|
||||
params.meshWeldTolerance = 0.001f;
|
||||
params.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES);
|
||||
params.buildTriangleAdjacencies = false;
|
||||
params.buildGPUData = true;
|
||||
params.midphaseDesc = PxMeshMidPhase::eBVH34;
|
||||
|
||||
PxDeformableVolumeMesh* deformableVolumeMesh = createDeformableVolumeMesh(params, surfaceMesh, numVoxelsAlongLongestAABBAxis, PxGetPhysics().getPhysicsInsertionCallback());
|
||||
|
||||
return createDeformableVolumeFromMesh(deformableVolumeMesh, transform, material, cudaContextManager, density, scale);
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::allocateAndInitializeHostMirror(PxDeformableVolume& deformableVolume, PxCudaContextManager* cudaContextManager, PxVec4*& simPositionInvMassPinned, PxVec4*& simVelocityPinned, PxVec4*& collPositionInvMassPinned, PxVec4*& restPositionPinned)
|
||||
{
|
||||
PX_ASSERT(deformableVolume.getCollisionMesh() != NULL);
|
||||
PX_ASSERT(deformableVolume.getSimulationMesh() != NULL);
|
||||
|
||||
PxU32 nbCollVerts = deformableVolume.getCollisionMesh()->getNbVertices();
|
||||
PxU32 nbSimVerts = deformableVolume.getSimulationMesh()->getNbVertices();
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
simPositionInvMassPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbSimVerts);
|
||||
simVelocityPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbSimVerts);
|
||||
collPositionInvMassPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbCollVerts);
|
||||
restPositionPinned = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *cudaContextManager, nbCollVerts);
|
||||
#else
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
|
||||
// write positionInvMass into CPU part.
|
||||
const PxVec3* positions = deformableVolume.getCollisionMesh()->getVertices();
|
||||
|
||||
for (PxU32 i = 0; i < nbCollVerts; ++i)
|
||||
{
|
||||
PxVec3 vert = positions[i];
|
||||
collPositionInvMassPinned[i] = PxVec4(vert, 1.f);
|
||||
restPositionPinned[i] = PxVec4(vert, 1.f);
|
||||
}
|
||||
|
||||
// write sim mesh part.
|
||||
PxDeformableVolumeAuxData* s = deformableVolume.getDeformableVolumeAuxData();
|
||||
PxReal* invMassGM = s->getGridModelInvMass();
|
||||
|
||||
const PxVec3* simPositions = deformableVolume.getSimulationMesh()->getVertices();
|
||||
for (PxU32 i = 0; i < nbSimVerts; ++i)
|
||||
{
|
||||
PxReal invMass = invMassGM ? invMassGM[i] : 1.f;
|
||||
simPositionInvMassPinned[i] = PxVec4(simPositions[i], invMass);
|
||||
simVelocityPinned[i] = PxVec4(0.f, 0.f, 0.f, invMass);
|
||||
}
|
||||
}
|
||||
|
||||
struct InternalDeformableVolumeState
|
||||
{
|
||||
PxVec4* mVertices;
|
||||
PxArray<PxReal> mInvMasses;
|
||||
const PxU32* mTetrahedra;
|
||||
PxArray<PxMat33> mInvRestPose;
|
||||
PxArray<PxVec3> mPrevPos;
|
||||
|
||||
InternalDeformableVolumeState(const PxVec4* verticesOriginal, PxVec4* verticesDeformed, PxU32 nbVertices, const PxU32* tetrahedra, PxU32 nbTetraheda, const bool* vertexIsFixed) :
|
||||
mVertices(verticesDeformed), mTetrahedra(tetrahedra)
|
||||
{
|
||||
PxReal density = 1.0f;
|
||||
|
||||
mInvMasses.resize(nbVertices, 0.0f);
|
||||
mInvRestPose.resize(nbTetraheda, PxMat33(PxZero));
|
||||
for (PxU32 i = 0; i < nbTetraheda; i++)
|
||||
{
|
||||
const PxU32* t = &mTetrahedra[4 * i];
|
||||
const PxVec3 a = verticesOriginal[t[0]].getXYZ();
|
||||
PxMat33 ir(verticesOriginal[t[1]].getXYZ() - a, verticesOriginal[t[2]].getXYZ() - a, verticesOriginal[t[3]].getXYZ() - a);
|
||||
PxReal volume = ir.getDeterminant() / 6.0f;
|
||||
if (volume > 1e-8f)
|
||||
mInvRestPose[i] = ir.getInverse();
|
||||
|
||||
PxReal m = 0.25f * volume * density;
|
||||
mInvMasses[t[0]] += m;
|
||||
mInvMasses[t[1]] += m;
|
||||
mInvMasses[t[2]] += m;
|
||||
mInvMasses[t[3]] += m;
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < nbVertices; i++)
|
||||
{
|
||||
bool fixed = vertexIsFixed ? vertexIsFixed[i] : verticesOriginal[i].w == 0.0f;
|
||||
if (mInvMasses[i] != 0.0f && !fixed)
|
||||
mInvMasses[i] = 1.0f / mInvMasses[i];
|
||||
else
|
||||
mInvMasses[i] = 0.0f;
|
||||
}
|
||||
|
||||
mPrevPos.resize(nbVertices);
|
||||
for (PxU32 i = 0; i < mPrevPos.size(); ++i)
|
||||
mPrevPos[i] = mVertices[i].getXYZ();
|
||||
}
|
||||
|
||||
void applyDelta()
|
||||
{
|
||||
for (PxU32 i = 0; i < mPrevPos.size(); ++i)
|
||||
{
|
||||
PxVec3 delta = mVertices[i].getXYZ() - mPrevPos[i];
|
||||
mPrevPos[i] = mVertices[i].getXYZ();
|
||||
mVertices[i] += PxVec4(0.99f * delta, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void applyToElem(PxU32 elemNr, PxReal C, PxReal compliance, const PxVec3& g1, const PxVec3& g2, const PxVec3& g3, const PxVec4& invMasses)
|
||||
{
|
||||
if (C == 0.0f)
|
||||
return;
|
||||
const PxVec3 g0 = -g1 - g2 - g3;
|
||||
|
||||
const PxU32* t = &mTetrahedra[4 * elemNr];
|
||||
const PxReal w = g0.magnitudeSquared() * invMasses.x + g1.magnitudeSquared() * invMasses.y + g2.magnitudeSquared() * invMasses.z + g3.magnitudeSquared() * invMasses.w;
|
||||
|
||||
if (w == 0.0f)
|
||||
return;
|
||||
|
||||
const PxReal alpha = compliance;
|
||||
const PxReal dlambda = -C / (w + alpha);
|
||||
|
||||
if (invMasses.x != 0.0f)
|
||||
mVertices[t[0]] += PxVec4(g0 * dlambda * invMasses.x, 0.0f);
|
||||
if (invMasses.y != 0.0f)
|
||||
mVertices[t[1]] += PxVec4(g1 * dlambda * invMasses.y, 0.0f);
|
||||
if (invMasses.z != 0.0f)
|
||||
mVertices[t[2]] += PxVec4(g2 * dlambda * invMasses.z, 0.0f);
|
||||
if (invMasses.w != 0.0f)
|
||||
mVertices[t[3]] += PxVec4(g3 * dlambda * invMasses.w, 0.0f);
|
||||
}
|
||||
|
||||
void solveElem(PxU32 elemNr)
|
||||
{
|
||||
const PxMat33& ir = mInvRestPose[elemNr];
|
||||
if (ir == PxMat33(PxZero))
|
||||
return;
|
||||
|
||||
const PxU32* tet = &mTetrahedra[4 * elemNr];
|
||||
|
||||
PxVec4 invMasses(mInvMasses[tet[0]], mInvMasses[tet[1]], mInvMasses[tet[2]], mInvMasses[tet[3]]);
|
||||
|
||||
PxMat33 P;
|
||||
P.column0 = mVertices[tet[1]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
P.column1 = mVertices[tet[2]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
P.column2 = mVertices[tet[3]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
|
||||
PxMat33 F = P * ir;
|
||||
|
||||
PxVec3 g1 = F.column0 * 2.0f * ir.column0.x + F.column1 * 2.0f * ir.column1.x + F.column2 * 2.0f * ir.column2.x;
|
||||
PxVec3 g2 = F.column0 * 2.0f * ir.column0.y + F.column1 * 2.0f * ir.column1.y + F.column2 * 2.0f * ir.column2.y;
|
||||
PxVec3 g3 = F.column0 * 2.0f * ir.column0.z + F.column1 * 2.0f * ir.column1.z + F.column2 * 2.0f * ir.column2.z;
|
||||
|
||||
PxReal C = F.column0.magnitudeSquared() + F.column1.magnitudeSquared() + F.column2.magnitudeSquared() - 3.0f;
|
||||
|
||||
applyToElem(elemNr, C, 0.0f, g1, g2, g3, invMasses);
|
||||
|
||||
P.column0 = mVertices[tet[1]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
P.column1 = mVertices[tet[2]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
P.column2 = mVertices[tet[3]].getXYZ() - mVertices[tet[0]].getXYZ();
|
||||
|
||||
F = P * ir;
|
||||
|
||||
PxMat33& dF = P; //Re-use memory, possible since P is not used anymore afterwards
|
||||
dF.column0 = F.column1.cross(F.column2);
|
||||
dF.column1 = F.column2.cross(F.column0);
|
||||
dF.column2 = F.column0.cross(F.column1);
|
||||
|
||||
g1 = dF.column0 * ir.column0.x + dF.column1 * ir.column1.x + dF.column2 * ir.column2.x;
|
||||
g2 = dF.column0 * ir.column0.y + dF.column1 * ir.column1.y + dF.column2 * ir.column2.y;
|
||||
g3 = dF.column0 * ir.column0.z + dF.column1 * ir.column1.z + dF.column2 * ir.column2.z;
|
||||
|
||||
C = F.getDeterminant() - 1.0f;
|
||||
|
||||
applyToElem(elemNr, C, 0.0f, g1, g2, g3, invMasses);
|
||||
}
|
||||
};
|
||||
|
||||
void PxDeformableVolumeExt::relaxDeformableVolumeMesh(const PxVec4* verticesOriginal, PxVec4* verticesDeformed, PxU32 nbVertices, const PxU32* tetrahedra, PxU32 nbTetraheda, const bool* vertexIsFixed, PxU32 numIterations)
|
||||
{
|
||||
InternalDeformableVolumeState state(verticesOriginal, verticesDeformed, nbVertices, tetrahedra, nbTetraheda, vertexIsFixed);
|
||||
for (PxU32 iter = 0; iter < numIterations; ++iter)
|
||||
{
|
||||
state.applyDelta();
|
||||
for (PxU32 i = 0; i < nbTetraheda; ++i)
|
||||
state.solveElem(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void PxDeformableVolumeExt::convertCollisionToSimulationTet(PxDeformableVolume& deformableVolume, PxU32 tetId, const PxVec4& tetBarycentric, PxU32& outTetId, PxVec4& outTetBarycentric)
|
||||
{
|
||||
const PxTetrahedronMesh* simulationMesh = deformableVolume.getSimulationMesh();
|
||||
const Gu::DeformableVolumeAuxData* deformableVolumeAuxData = static_cast<const Gu::DeformableVolumeAuxData*>(deformableVolume.getDeformableVolumeAuxData());
|
||||
const Gu::BVTetrahedronMesh* collisionMesh = static_cast<const Gu::BVTetrahedronMesh*>(deformableVolume.getCollisionMesh());
|
||||
|
||||
// Sim mesh uses the same ordering for both CPU and GPU tet ids so we can use Gu::convertDeformableVolumeCollisionToSimMeshTets to convert from CPU collision tet id to CPU/GPU sim tet id.
|
||||
Gu::convertDeformableVolumeCollisionToSimMeshTets(*simulationMesh, *deformableVolumeAuxData, *collisionMesh, tetId, tetBarycentric, outTetId, outTetBarycentric, false);
|
||||
}
|
||||
331
engine/third_party/physx/source/physxextensions/src/ExtDistanceJoint.cpp
vendored
Normal file
331
engine/third_party/physx/source/physxextensions/src/ExtDistanceJoint.cpp
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
// 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 "ExtDistanceJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
DistanceJoint::DistanceJoint(const PxTolerancesScale& scale, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
DistanceJointT(PxJointConcreteType::eDISTANCE, actor0, localFrame0, actor1, localFrame1, "DistanceJointData")
|
||||
{
|
||||
DistanceJointData* data = static_cast<DistanceJointData*>(mData);
|
||||
|
||||
data->stiffness = 0.0f;
|
||||
data->damping = 0.0f;
|
||||
data->minDistance = 0.0f;
|
||||
data->maxDistance = 0.0f;
|
||||
data->tolerance = 0.025f * scale.length;
|
||||
data->jointFlags = PxDistanceJointFlag::eMAX_DISTANCE_ENABLED;
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getDistance() const
|
||||
{
|
||||
return getRelativeTransform().p.magnitude();
|
||||
}
|
||||
|
||||
void DistanceJoint::setMinDistance(PxReal distance)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(distance) && distance>=0.0f, "PxDistanceJoint::setMinDistance: invalid parameter");
|
||||
data().minDistance = distance;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, minDistance, static_cast<PxDistanceJoint&>(*this), distance)
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getMinDistance() const
|
||||
{
|
||||
return data().minDistance;
|
||||
}
|
||||
|
||||
void DistanceJoint::setMaxDistance(PxReal distance)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(distance) && distance>=0.0f, "PxDistanceJoint::setMaxDistance: invalid parameter");
|
||||
data().maxDistance = distance;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, maxDistance, static_cast<PxDistanceJoint&>(*this), distance)
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getMaxDistance() const
|
||||
{
|
||||
return data().maxDistance;
|
||||
}
|
||||
|
||||
void DistanceJoint::setTolerance(PxReal tolerance)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(tolerance), "PxDistanceJoint::setTolerance: invalid parameter");
|
||||
data().tolerance = tolerance;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, tolerance, static_cast<PxDistanceJoint&>(*this), tolerance)
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getTolerance() const
|
||||
{
|
||||
return data().tolerance;
|
||||
}
|
||||
|
||||
void DistanceJoint::setStiffness(PxReal stiffness)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(stiffness), "PxDistanceJoint::setStiffness: invalid parameter");
|
||||
data().stiffness = stiffness;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, stiffness, static_cast<PxDistanceJoint&>(*this), stiffness)
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getStiffness() const
|
||||
{
|
||||
return data().stiffness;
|
||||
}
|
||||
|
||||
void DistanceJoint::setDamping(PxReal damping)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(damping), "PxDistanceJoint::setDamping: invalid parameter");
|
||||
data().damping = damping;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, damping, static_cast<PxDistanceJoint&>(*this), damping)
|
||||
}
|
||||
|
||||
PxReal DistanceJoint::getDamping() const
|
||||
{
|
||||
return data().damping;
|
||||
}
|
||||
|
||||
PxDistanceJointFlags DistanceJoint::getDistanceJointFlags() const
|
||||
{
|
||||
return data().jointFlags;
|
||||
}
|
||||
|
||||
void DistanceJoint::setDistanceJointFlags(PxDistanceJointFlags flags)
|
||||
{
|
||||
data().jointFlags = flags;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, jointFlags, static_cast<PxDistanceJoint&>(*this), flags)
|
||||
}
|
||||
|
||||
void DistanceJoint::setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value)
|
||||
{
|
||||
if(value)
|
||||
data().jointFlags |= flag;
|
||||
else
|
||||
data().jointFlags &= ~flag;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, jointFlags, static_cast<PxDistanceJoint&>(*this), getDistanceJointFlags())
|
||||
}
|
||||
|
||||
static void DistanceJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
const DistanceJointData& data = *reinterpret_cast<const DistanceJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
|
||||
// PT: we consider the following is part of the joint's "limits" since that's the only available flag we have
|
||||
if(flags & PxConstraintVisualizationFlag::eLIMITS)
|
||||
{
|
||||
const bool enforceMax = (data.jointFlags & PxDistanceJointFlag::eMAX_DISTANCE_ENABLED);
|
||||
const bool enforceMin = (data.jointFlags & PxDistanceJointFlag::eMIN_DISTANCE_ENABLED);
|
||||
if(!enforceMin && !enforceMax)
|
||||
return;
|
||||
|
||||
PxVec3 dir = cB2w.p - cA2w.p;
|
||||
const float currentDist = dir.normalize();
|
||||
|
||||
PxU32 color = 0x00ff00;
|
||||
if(enforceMax && currentDist>data.maxDistance)
|
||||
color = 0xff0000;
|
||||
if(enforceMin && currentDist<data.minDistance)
|
||||
color = 0x0000ff;
|
||||
|
||||
viz.visualizeLine(cA2w.p, cB2w.p, color);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void setupConstraint(Px1DConstraint& c, const PxVec3& direction, const PxVec3& angular0, const PxVec3& angular1, const DistanceJointData& data)
|
||||
{
|
||||
// constraint is breakable, so we need to output forces
|
||||
|
||||
c.flags = Px1DConstraintFlag::eOUTPUT_FORCE;
|
||||
|
||||
c.linear0 = direction; c.angular0 = angular0;
|
||||
c.linear1 = direction; c.angular1 = angular1;
|
||||
|
||||
if(data.jointFlags & PxDistanceJointFlag::eSPRING_ENABLED)
|
||||
{
|
||||
c.flags |= Px1DConstraintFlag::eSPRING;
|
||||
c.mods.spring.stiffness = data.stiffness;
|
||||
c.mods.spring.damping = data.damping;
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU32 setupMinConstraint(Px1DConstraint& c, const PxVec3& direction, const PxVec3& angular0, const PxVec3& angular1, const DistanceJointData& data, float distance)
|
||||
{
|
||||
setupConstraint(c, direction, angular0, angular1, data);
|
||||
c.geometricError = distance - data.minDistance + data.tolerance;
|
||||
c.minImpulse = 0.0f;
|
||||
if(distance>=data.minDistance)
|
||||
c.flags |= Px1DConstraintFlag::eKEEPBIAS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU32 setupMaxConstraint(Px1DConstraint& c, const PxVec3& direction, const PxVec3& angular0, const PxVec3& angular1, const DistanceJointData& data, float distance)
|
||||
{
|
||||
setupConstraint(c, direction, angular0, angular1, data);
|
||||
c.geometricError = distance - data.maxDistance - data.tolerance;
|
||||
c.maxImpulse = 0.0f;
|
||||
if(distance<=data.maxDistance)
|
||||
c.flags |= Px1DConstraintFlag::eKEEPBIAS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 DistanceJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const DistanceJointData& data = *reinterpret_cast<const DistanceJointData*>(constantBlock);
|
||||
|
||||
const bool enforceMax = (data.jointFlags & PxDistanceJointFlag::eMAX_DISTANCE_ENABLED) && data.maxDistance>=0.0f;
|
||||
const bool enforceMin = (data.jointFlags & PxDistanceJointFlag::eMIN_DISTANCE_ENABLED) && data.minDistance>=0.0f;
|
||||
if(!enforceMax && !enforceMin)
|
||||
return 0;
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
cA2wOut = cB2w.p;
|
||||
cB2wOut = cB2w.p;
|
||||
|
||||
PxVec3 direction = cA2w.p - cB2w.p;
|
||||
const PxReal distance = direction.normalize();
|
||||
|
||||
#define EPS_REAL 1.192092896e-07F
|
||||
|
||||
if(distance < EPS_REAL)
|
||||
direction = PxVec3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
Px1DConstraint* c = constraints;
|
||||
|
||||
const PxVec3 angular0 = ch.getRa().cross(direction);
|
||||
const PxVec3 angular1 = ch.getRb().cross(direction);
|
||||
|
||||
if(enforceMin && !enforceMax)
|
||||
return setupMinConstraint(*c, direction, angular0, angular1, data, distance);
|
||||
else if(enforceMax && !enforceMin)
|
||||
return setupMaxConstraint(*c, direction, angular0, angular1, data, distance);
|
||||
else
|
||||
{
|
||||
if(data.minDistance == data.maxDistance)
|
||||
{
|
||||
setupConstraint(*c, direction, angular0, angular1, data);
|
||||
|
||||
//add tolerance so we don't have contact-style jitter problem.
|
||||
const PxReal error = distance - data.maxDistance;
|
||||
c->geometricError = error > data.tolerance ? error - data.tolerance :
|
||||
error < -data.tolerance ? error + data.tolerance : 0.0f;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// since we dont know the current rigid velocity, we need to insert row for both limits
|
||||
PxU32 nb = setupMinConstraint(*c, direction, angular0, angular1, data, distance);
|
||||
if(nb)
|
||||
c++;
|
||||
nb += setupMaxConstraint(*c, direction, angular0, angular1, data, distance);
|
||||
return nb;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gDistanceJointShaders = { DistanceJointSolverPrep, DistanceJointVisualize, PxConstraintFlag::Enum(0) };
|
||||
|
||||
PxConstraintSolverPrep DistanceJoint::getPrep() const { return gDistanceJointShaders.solverPrep; }
|
||||
|
||||
PxDistanceJoint* physx::PxDistanceJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxDistanceJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxDistanceJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxDistanceJointCreate: actors must be different");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxD6JointCreate: at least one actor must be dynamic");
|
||||
|
||||
return createJointT<DistanceJoint, DistanceJointData>(physics, actor0, localFrame0, actor1, localFrame1, gDistanceJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void DistanceJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gDistanceJointShaders);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
void DistanceJoint::updateOmniPvdProperties() const
|
||||
{
|
||||
const PxDistanceJoint& j = static_cast<const PxDistanceJoint&>(*this);
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, distance, j, getDistance())
|
||||
}
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<DistanceJoint>(DistanceJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxDistanceJoint& j = static_cast<PxDistanceJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eDISTANCE);
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, minDistance, j, joint.getMinDistance())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, maxDistance, j, joint.getMaxDistance())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, tolerance, j, joint.getTolerance())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, stiffness, j, joint.getStiffness())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, damping, j, joint.getDamping())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, jointFlags, j, joint.getDistanceJointFlags())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxDistanceJoint, distance, j, joint.getDistance())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
94
engine/third_party/physx/source/physxextensions/src/ExtDistanceJoint.h
vendored
Normal file
94
engine/third_party/physx/source/physxextensions/src/ExtDistanceJoint.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// 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 EXT_DISTANCE_JOINT_H
|
||||
#define EXT_DISTANCE_JOINT_H
|
||||
|
||||
#include "common/PxTolerancesScale.h"
|
||||
#include "extensions/PxDistanceJoint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxDistanceJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct DistanceJointData : public JointData
|
||||
{
|
||||
PxReal minDistance;
|
||||
PxReal maxDistance;
|
||||
PxReal tolerance;
|
||||
PxReal stiffness;
|
||||
PxReal damping;
|
||||
|
||||
PxDistanceJointFlags jointFlags;
|
||||
};
|
||||
|
||||
typedef JointT<PxDistanceJoint, DistanceJointData, PxDistanceJointGeneratedValues> DistanceJointT;
|
||||
class DistanceJoint : public DistanceJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
DistanceJoint(PxBaseFlags baseFlags) : DistanceJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static DistanceJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<DistanceJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
DistanceJoint(const PxTolerancesScale& scale, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxDistanceJoint
|
||||
virtual PxReal getDistance() const PX_OVERRIDE;
|
||||
virtual void setMinDistance(PxReal distance) PX_OVERRIDE;
|
||||
virtual PxReal getMinDistance() const PX_OVERRIDE;
|
||||
virtual void setMaxDistance(PxReal distance) PX_OVERRIDE;
|
||||
virtual PxReal getMaxDistance() const PX_OVERRIDE;
|
||||
virtual void setTolerance(PxReal tolerance) PX_OVERRIDE;
|
||||
virtual PxReal getTolerance() const PX_OVERRIDE;
|
||||
virtual void setStiffness(PxReal spring) PX_OVERRIDE;
|
||||
virtual PxReal getStiffness() const PX_OVERRIDE;
|
||||
virtual void setDamping(PxReal damping) PX_OVERRIDE;
|
||||
virtual PxReal getDamping() const PX_OVERRIDE;
|
||||
virtual void setDistanceJointFlags(PxDistanceJointFlags flags) PX_OVERRIDE;
|
||||
virtual void setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value) PX_OVERRIDE;
|
||||
virtual PxDistanceJointFlags getDistanceJointFlags() const PX_OVERRIDE;
|
||||
//~PxDistanceJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE;
|
||||
#endif
|
||||
//~PxConstraintConnector
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
260
engine/third_party/physx/source/physxextensions/src/ExtExtensions.cpp
vendored
Normal file
260
engine/third_party/physx/source/physxextensions/src/ExtExtensions.cpp
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
// 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/PxIO.h"
|
||||
#include "common/PxSerializer.h"
|
||||
#include "extensions/PxExtensionsAPI.h"
|
||||
#include "extensions/PxRepXSerializer.h"
|
||||
|
||||
#include "ExtDistanceJoint.h"
|
||||
#include "ExtD6Joint.h"
|
||||
#include "ExtFixedJoint.h"
|
||||
#include "ExtPrismaticJoint.h"
|
||||
#include "ExtRevoluteJoint.h"
|
||||
#include "ExtSphericalJoint.h"
|
||||
#include "ExtGearJoint.h"
|
||||
#include "ExtRackAndPinionJoint.h"
|
||||
#include "ExtSerialization.h"
|
||||
#include "SnRepXCoreSerializer.h"
|
||||
#include "SnJointRepXSerializer.h"
|
||||
#include "PxExtensionMetaDataObjects.h"
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
#include "ExtPvd.h"
|
||||
#include "PxPvdDataStream.h"
|
||||
#include "PxPvdClient.h"
|
||||
#include "PsPvd.h"
|
||||
#endif
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
# include "omnipvd/PxOmniPvd.h"
|
||||
# include "omnipvd/OmniPvdPxExtensionsSampler.h"
|
||||
#endif
|
||||
|
||||
using namespace physx;
|
||||
using namespace physx::pvdsdk;
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
struct JointConnectionHandler : public PvdClient
|
||||
{
|
||||
JointConnectionHandler() : mPvd(NULL),mConnected(false){}
|
||||
|
||||
PvdDataStream* getDataStream()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void onPvdConnected()
|
||||
{
|
||||
PvdDataStream* stream = PvdDataStream::create(mPvd);
|
||||
if(stream)
|
||||
{
|
||||
mConnected = true;
|
||||
Ext::Pvd::sendClassDescriptions(*stream);
|
||||
stream->release();
|
||||
}
|
||||
}
|
||||
|
||||
bool isConnected() const
|
||||
{
|
||||
return mConnected;
|
||||
}
|
||||
|
||||
void onPvdDisconnected()
|
||||
{
|
||||
mConnected = false;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
}
|
||||
|
||||
PsPvd* mPvd;
|
||||
bool mConnected;
|
||||
};
|
||||
|
||||
static JointConnectionHandler gPvdHandler;
|
||||
#endif
|
||||
|
||||
bool PxInitExtensions(PxPhysics& physics, PxPvd* pvd)
|
||||
{
|
||||
PX_ASSERT(&physics.getFoundation() == &PxGetFoundation());
|
||||
PX_UNUSED(physics);
|
||||
PX_UNUSED(pvd);
|
||||
PxIncFoundationRefCount();
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
if(pvd)
|
||||
{
|
||||
gPvdHandler.mPvd = static_cast<PsPvd*>(pvd);
|
||||
gPvdHandler.mPvd->addClient(&gPvdHandler);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
if (physics.getOmniPvd() && physics.getOmniPvd()->getWriter())
|
||||
{
|
||||
if (OmniPvdPxExtensionsSampler::createInstance())
|
||||
{
|
||||
OmniPvdPxExtensionsSampler::getInstance()->setOmniPvdInstance(physics.getOmniPvd());
|
||||
OmniPvdPxExtensionsSampler::getInstance()->registerClasses();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static PxArray<PxSceneQuerySystem*>* gExternalSQ = NULL;
|
||||
|
||||
void addExternalSQ(PxSceneQuerySystem* added)
|
||||
{
|
||||
if(!gExternalSQ)
|
||||
gExternalSQ = new PxArray<PxSceneQuerySystem*>;
|
||||
|
||||
gExternalSQ->pushBack(added);
|
||||
}
|
||||
|
||||
void removeExternalSQ(PxSceneQuerySystem* removed)
|
||||
{
|
||||
if(gExternalSQ)
|
||||
{
|
||||
const PxU32 nb = gExternalSQ->size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PxSceneQuerySystem* sq = (*gExternalSQ)[i];
|
||||
if(sq==removed)
|
||||
{
|
||||
gExternalSQ->replaceWithLast(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void releaseExternalSQ()
|
||||
{
|
||||
if(gExternalSQ)
|
||||
{
|
||||
PxArray<PxSceneQuerySystem*>* copy = gExternalSQ;
|
||||
gExternalSQ = NULL;
|
||||
|
||||
const PxU32 nb = copy->size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PxSceneQuerySystem* sq = (*copy)[i];
|
||||
sq->release();
|
||||
}
|
||||
PX_DELETE(copy);
|
||||
}
|
||||
}
|
||||
|
||||
void PxCloseExtensions()
|
||||
{
|
||||
releaseExternalSQ();
|
||||
|
||||
PxDecFoundationRefCount();
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
if(gPvdHandler.mConnected)
|
||||
{
|
||||
PX_ASSERT(gPvdHandler.mPvd);
|
||||
gPvdHandler.mPvd->removeClient(&gPvdHandler);
|
||||
gPvdHandler.mPvd = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
if (OmniPvdPxExtensionsSampler::getInstance())
|
||||
{
|
||||
OmniPvdPxExtensionsSampler::destroyInstance();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Ext::RegisterExtensionsSerializers(PxSerializationRegistry& sr)
|
||||
{
|
||||
//for repx serialization
|
||||
sr.registerRepXSerializer(PxConcreteType::eMATERIAL, PX_NEW_REPX_SERIALIZER( PxMaterialRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eSHAPE, PX_NEW_REPX_SERIALIZER( PxShapeRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33, PX_NEW_REPX_SERIALIZER( PxBVH33TriangleMeshRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34, PX_NEW_REPX_SERIALIZER( PxBVH34TriangleMeshRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eHEIGHTFIELD, PX_NEW_REPX_SERIALIZER( PxHeightFieldRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eCONVEX_MESH, PX_NEW_REPX_SERIALIZER( PxConvexMeshRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eRIGID_STATIC, PX_NEW_REPX_SERIALIZER( PxRigidStaticRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eRIGID_DYNAMIC, PX_NEW_REPX_SERIALIZER( PxRigidDynamicRepXSerializer ));
|
||||
sr.registerRepXSerializer(PxConcreteType::eARTICULATION_REDUCED_COORDINATE, PX_NEW_REPX_SERIALIZER( PxArticulationReducedCoordinateRepXSerializer));
|
||||
sr.registerRepXSerializer(PxConcreteType::eAGGREGATE, PX_NEW_REPX_SERIALIZER( PxAggregateRepXSerializer ));
|
||||
|
||||
sr.registerRepXSerializer(PxJointConcreteType::eFIXED, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxFixedJoint> ));
|
||||
sr.registerRepXSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxDistanceJoint> ));
|
||||
sr.registerRepXSerializer(PxJointConcreteType::eD6, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxD6Joint> ));
|
||||
sr.registerRepXSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxPrismaticJoint> ));
|
||||
sr.registerRepXSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxRevoluteJoint> ));
|
||||
sr.registerRepXSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxSphericalJoint> ));
|
||||
|
||||
//for binary serialization
|
||||
sr.registerSerializer(PxJointConcreteType::eFIXED, PX_NEW_SERIALIZER_ADAPTER( FixedJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_SERIALIZER_ADAPTER( DistanceJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eD6, PX_NEW_SERIALIZER_ADAPTER( D6Joint) );
|
||||
sr.registerSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_SERIALIZER_ADAPTER( PrismaticJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_SERIALIZER_ADAPTER( RevoluteJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_SERIALIZER_ADAPTER( SphericalJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eGEAR, PX_NEW_SERIALIZER_ADAPTER( GearJoint ));
|
||||
sr.registerSerializer(PxJointConcreteType::eRACK_AND_PINION, PX_NEW_SERIALIZER_ADAPTER( RackAndPinionJoint ));
|
||||
}
|
||||
|
||||
void Ext::UnregisterExtensionsSerializers(PxSerializationRegistry& sr)
|
||||
{
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eFIXED));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eDISTANCE));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eD6 ));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::ePRISMATIC));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eREVOLUTE));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eSPHERICAL));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eGEAR));
|
||||
PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eRACK_AND_PINION));
|
||||
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eMATERIAL));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eSHAPE));
|
||||
// PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eHEIGHTFIELD));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCONVEX_MESH));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_STATIC));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_DYNAMIC));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eARTICULATION_REDUCED_COORDINATE));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eAGGREGATE));
|
||||
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eFIXED));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eDISTANCE));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eD6));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::ePRISMATIC));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eREVOLUTE));
|
||||
PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eSPHERICAL));
|
||||
}
|
||||
114
engine/third_party/physx/source/physxextensions/src/ExtFixedJoint.cpp
vendored
Normal file
114
engine/third_party/physx/source/physxextensions/src/ExtFixedJoint.cpp
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// 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 "ExtFixedJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
FixedJoint::FixedJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
FixedJointT(PxJointConcreteType::eFIXED, actor0, localFrame0, actor1, localFrame1, "FixedJointData")
|
||||
{
|
||||
// FixedJointData* data = static_cast<FixedJointData*>(mData);
|
||||
}
|
||||
|
||||
static void FixedJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
{
|
||||
const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
}
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 FixedJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
joint::applyNeighborhoodOperator(cA2w, cB2w);
|
||||
|
||||
PxVec3 ra, rb;
|
||||
ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, 7, ra, rb);
|
||||
cA2wOut = ra + bA2w.p;
|
||||
cB2wOut = rb + bB2w.p;
|
||||
|
||||
return ch.getCount();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gFixedJointShaders = { FixedJointSolverPrep, FixedJointVisualize, PxConstraintFlag::Enum(0) };
|
||||
|
||||
PxConstraintSolverPrep FixedJoint::getPrep() const { return gFixedJointShaders.solverPrep; }
|
||||
|
||||
PxFixedJoint* physx::PxFixedJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxFixedJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxFixedJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxFixedJointCreate: at least one actor must be dynamic");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxFixedJointCreate: actors must be different");
|
||||
|
||||
return createJointT<FixedJoint, FixedJointData>(physics, actor0, localFrame0, actor1, localFrame1, gFixedJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void FixedJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gFixedJointShaders);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<FixedJoint>(FixedJoint& joint)
|
||||
{
|
||||
PxFixedJoint& j = static_cast<PxFixedJoint&>(joint);
|
||||
OMNI_PVD_CREATE(OMNI_PVD_CONTEXT_HANDLE, PxFixedJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eFIXED);
|
||||
}
|
||||
|
||||
#endif
|
||||
68
engine/third_party/physx/source/physxextensions/src/ExtFixedJoint.h
vendored
Normal file
68
engine/third_party/physx/source/physxextensions/src/ExtFixedJoint.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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 EXT_FIXED_JOINT_H
|
||||
#define EXT_FIXED_JOINT_H
|
||||
|
||||
#include "extensions/PxFixedJoint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxFixedJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct FixedJointData : public JointData
|
||||
{
|
||||
};
|
||||
|
||||
typedef JointT<PxFixedJoint, FixedJointData, PxFixedJointGeneratedValues> FixedJointT;
|
||||
|
||||
class FixedJoint : public FixedJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
FixedJoint(PxBaseFlags baseFlags) : FixedJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static FixedJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<FixedJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
FixedJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxFixedJoint
|
||||
//~PxFixedJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
//~PxConstraintConnector
|
||||
};
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
318
engine/third_party/physx/source/physxextensions/src/ExtGearJoint.cpp
vendored
Normal file
318
engine/third_party/physx/source/physxextensions/src/ExtGearJoint.cpp
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
// 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 "ExtGearJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
#include "extensions/PxRevoluteJoint.h"
|
||||
#include "PxArticulationJointReducedCoordinate.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
PX_IMPLEMENT_OUTPUT_ERROR
|
||||
|
||||
GearJoint::GearJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
GearJointT(PxJointConcreteType::eGEAR, actor0, localFrame0, actor1, localFrame1, "GearJointData")
|
||||
{
|
||||
GearJointData* data = static_cast<GearJointData*>(mData);
|
||||
data->hingeJoint0 = NULL;
|
||||
data->hingeJoint1 = NULL;
|
||||
data->gearRatio = 0.0f;
|
||||
data->error = 0.0f;
|
||||
|
||||
resetError();
|
||||
}
|
||||
|
||||
static bool checkJoint(const PxBase* hinge)
|
||||
{
|
||||
if(hinge)
|
||||
{
|
||||
bool invalidType;
|
||||
const PxType type = hinge->getConcreteType();
|
||||
if(type == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* joint = static_cast<const PxArticulationJointReducedCoordinate*>(hinge);
|
||||
const PxArticulationJointType::Enum artiJointType = joint->getJointType();
|
||||
invalidType = artiJointType != PxArticulationJointType::eREVOLUTE && artiJointType != PxArticulationJointType::eREVOLUTE_UNWRAPPED;
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidType = type != PxJointConcreteType::eREVOLUTE && type != PxJointConcreteType::eD6;
|
||||
}
|
||||
if(invalidType)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxGearJoint::setHinges: passed joint must be either a revolute joint or a D6 joint.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GearJoint::setHinges(const PxBase* hinge0, const PxBase* hinge1)
|
||||
{
|
||||
GearJointData* data = static_cast<GearJointData*>(mData);
|
||||
|
||||
if(!checkJoint(hinge0) || !checkJoint(hinge1))
|
||||
return false;
|
||||
|
||||
data->hingeJoint0 = hinge0;
|
||||
data->hingeJoint1 = hinge1;
|
||||
resetError();
|
||||
markDirty();
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
const PxBase* joints[] ={ hinge0, hinge1 };
|
||||
const PxU32 hingeCount = sizeof(joints) / sizeof(joints[0]);
|
||||
OMNI_PVD_SET_ARRAY(OMNI_PVD_CONTEXT_HANDLE, PxGearJoint, hinges, static_cast<PxGearJoint&>(*this), joints, hingeCount)
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GearJoint::getHinges(const PxBase*& hinge0, const PxBase*& hinge1) const
|
||||
{
|
||||
const GearJointData* data = static_cast<const GearJointData*>(mData);
|
||||
hinge0 = data->hingeJoint0;
|
||||
hinge1 = data->hingeJoint1;
|
||||
}
|
||||
|
||||
void GearJoint::setGearRatio(float ratio)
|
||||
{
|
||||
GearJointData* data = static_cast<GearJointData*>(mData);
|
||||
data->gearRatio = ratio;
|
||||
resetError();
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxGearJoint, ratio, static_cast<PxGearJoint&>(*this), ratio)
|
||||
}
|
||||
|
||||
float GearJoint::getGearRatio() const
|
||||
{
|
||||
const GearJointData* data = static_cast<const GearJointData*>(mData);
|
||||
return data->gearRatio;
|
||||
}
|
||||
|
||||
static float angleDiff(float angle0, float angle1)
|
||||
{
|
||||
const float diff = fmodf(angle1 - angle0 + PxPi, PxTwoPi) - PxPi;
|
||||
return diff < -PxPi ? diff + PxTwoPi : diff;
|
||||
}
|
||||
|
||||
static void getAngleAndSign(float& angle, float& sign, const PxBase* dataHingeJoint, PxRigidActor* gearActor0, PxRigidActor* gearActor1)
|
||||
{
|
||||
PxRigidActor* hingeActor0;
|
||||
PxRigidActor* hingeActor1;
|
||||
const PxType type = dataHingeJoint->getConcreteType();
|
||||
|
||||
if(type == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* artiHingeJoint = static_cast<const PxArticulationJointReducedCoordinate*>(dataHingeJoint);
|
||||
|
||||
hingeActor0 = &artiHingeJoint->getParentArticulationLink();
|
||||
hingeActor1 = &artiHingeJoint->getChildArticulationLink();
|
||||
|
||||
angle = artiHingeJoint->getJointPosition(PxArticulationAxis::eTWIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxJoint* hingeJoint = static_cast<const PxJoint*>(dataHingeJoint);
|
||||
|
||||
hingeJoint->getActors(hingeActor0, hingeActor1);
|
||||
|
||||
if(type == PxJointConcreteType::eREVOLUTE)
|
||||
angle = static_cast<const PxRevoluteJoint*>(hingeJoint)->getAngle();
|
||||
else if(type == PxJointConcreteType::eD6)
|
||||
angle = static_cast<const PxD6Joint*>(hingeJoint)->getTwistAngle();
|
||||
}
|
||||
|
||||
if(gearActor0 == hingeActor0 || gearActor1 == hingeActor0)
|
||||
sign = -1.0f;
|
||||
else if(gearActor0 == hingeActor1 || gearActor1 == hingeActor1)
|
||||
sign = 1.0f;
|
||||
else
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
|
||||
void GearJoint::updateError()
|
||||
{
|
||||
GearJointData* data = static_cast<GearJointData*>(mData);
|
||||
|
||||
if(!data->hingeJoint0 || !data->hingeJoint1)
|
||||
return;
|
||||
|
||||
PxRigidActor* gearActor0;
|
||||
PxRigidActor* gearActor1;
|
||||
getActors(gearActor0, gearActor1);
|
||||
|
||||
float Angle0 = 0.0f;
|
||||
float Sign0 = 0.0f;
|
||||
getAngleAndSign(Angle0, Sign0, data->hingeJoint0, gearActor0, gearActor1);
|
||||
|
||||
float Angle1 = 0.0f;
|
||||
float Sign1 = 0.0f;
|
||||
getAngleAndSign(Angle1, Sign1, data->hingeJoint1, gearActor0, gearActor1);
|
||||
Angle1 = -Angle1;
|
||||
|
||||
if(!mInitDone)
|
||||
{
|
||||
mInitDone = true;
|
||||
mPersistentAngle0 = Angle0;
|
||||
mPersistentAngle1 = Angle1;
|
||||
}
|
||||
|
||||
const float travelThisFrame0 = angleDiff(Angle0, mPersistentAngle0);
|
||||
const float travelThisFrame1 = angleDiff(Angle1, mPersistentAngle1);
|
||||
mVirtualAngle0 += travelThisFrame0;
|
||||
mVirtualAngle1 += travelThisFrame1;
|
||||
|
||||
// printf("travelThisFrame0: %f\n", travelThisFrame0);
|
||||
// printf("travelThisFrame1: %f\n", travelThisFrame1);
|
||||
// printf("ratio: %f\n", travelThisFrame1/travelThisFrame0);
|
||||
mPersistentAngle0 = Angle0;
|
||||
mPersistentAngle1 = Angle1;
|
||||
|
||||
const float error = Sign0*mVirtualAngle0*data->gearRatio - Sign1*mVirtualAngle1;
|
||||
// printf("error: %f\n", error);
|
||||
|
||||
data->error = error;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
void GearJoint::resetError()
|
||||
{
|
||||
mVirtualAngle0 = mVirtualAngle1 = 0.0f;
|
||||
mPersistentAngle0 = mPersistentAngle1 = 0.0f;
|
||||
mInitDone = false;
|
||||
}
|
||||
|
||||
static const bool gVizJointFrames = true;
|
||||
static const bool gVizGearAxes = false;
|
||||
|
||||
static void GearJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
{
|
||||
const GearJointData& data = *reinterpret_cast<const GearJointData*>(constantBlock);
|
||||
|
||||
// Visualize joint frames
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
if(gVizJointFrames)
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
|
||||
if(gVizGearAxes)
|
||||
{
|
||||
const PxVec3 gearAxis0 = cA2w.rotate(PxVec3(1.0f, 0.0f, 0.0f)).getNormalized();
|
||||
const PxVec3 gearAxis1 = cB2w.rotate(PxVec3(1.0f, 0.0f, 0.0f)).getNormalized();
|
||||
viz.visualizeLine(body0Transform.p+gearAxis0, body0Transform.p, 0xff0000ff);
|
||||
viz.visualizeLine(body1Transform.p+gearAxis1, body1Transform.p, 0xff0000ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 GearJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const GearJointData& data = *reinterpret_cast<const GearJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
cA2wOut = cB2w.p;
|
||||
cB2wOut = cB2w.p;
|
||||
|
||||
const PxVec3 gearAxis0 = cA2w.q.getBasisVector0();
|
||||
const PxVec3 gearAxis1 = cB2w.q.getBasisVector0();
|
||||
|
||||
Px1DConstraint& con = constraints[0];
|
||||
con.linear0 = PxVec3(0.0f);
|
||||
con.linear1 = PxVec3(0.0f);
|
||||
con.angular0 = gearAxis0*data.gearRatio;
|
||||
con.angular1 = -gearAxis1;
|
||||
con.geometricError = -data.error;
|
||||
con.minImpulse = -PX_MAX_F32;
|
||||
con.maxImpulse = PX_MAX_F32;
|
||||
con.velocityTarget = 0.f;
|
||||
con.solveHint = 0;
|
||||
con.flags = Px1DConstraintFlag::eOUTPUT_FORCE|Px1DConstraintFlag::eANGULAR_CONSTRAINT;
|
||||
con.mods.bounce.restitution = 0.0f;
|
||||
con.mods.bounce.velocityThreshold = 0.0f;
|
||||
return 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gGearJointShaders = { GearJointSolverPrep, GearJointVisualize, PxConstraintFlag::eALWAYS_UPDATE };
|
||||
|
||||
PxConstraintSolverPrep GearJoint::getPrep() const { return gGearJointShaders.solverPrep; }
|
||||
|
||||
PxGearJoint* physx::PxGearJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxGearJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxGearJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxGearJointCreate: at least one actor must be dynamic");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxGearJointCreate: actors must be different");
|
||||
|
||||
return createJointT<GearJoint, GearJointData>(physics, actor0, localFrame0, actor1, localFrame1, gGearJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void GearJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gGearJointShaders);
|
||||
|
||||
GearJointData* data = static_cast<GearJointData*>(mData);
|
||||
context.translatePxBase(data->hingeJoint0);
|
||||
context.translatePxBase(data->hingeJoint1);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<GearJoint>(GearJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxGearJoint& j = static_cast<PxGearJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxGearJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eGEAR);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxGearJoint, ratio, j , joint.getGearRatio())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
89
engine/third_party/physx/source/physxextensions/src/ExtGearJoint.h
vendored
Normal file
89
engine/third_party/physx/source/physxextensions/src/ExtGearJoint.h
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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 EXT_GEAR_JOINT_H
|
||||
#define EXT_GEAR_JOINT_H
|
||||
|
||||
#include "extensions/PxGearJoint.h"
|
||||
#include "ExtJoint.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxGearJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct GearJointData : public JointData
|
||||
{
|
||||
const PxBase* hingeJoint0; //either PxJoint or PxArticulationJointReducedCoordinate
|
||||
const PxBase* hingeJoint1; //either PxJoint or PxArticulationJointReducedCoordinate
|
||||
float gearRatio;
|
||||
float error;
|
||||
};
|
||||
|
||||
typedef JointT<PxGearJoint, GearJointData, PxGearJointGeneratedValues> GearJointT;
|
||||
|
||||
class GearJoint : public GearJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
GearJoint(PxBaseFlags baseFlags) : GearJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static GearJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<GearJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
GearJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxGearJoint
|
||||
virtual bool setHinges(const PxBase* hinge0, const PxBase* hinge1) PX_OVERRIDE;
|
||||
virtual void getHinges(const PxBase*& hinge0, const PxBase*& hinge1) const PX_OVERRIDE;
|
||||
virtual void setGearRatio(float ratio) PX_OVERRIDE;
|
||||
virtual float getGearRatio() const PX_OVERRIDE;
|
||||
//~PxGearJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void* prepareData() PX_OVERRIDE
|
||||
{
|
||||
updateError();
|
||||
return mData;
|
||||
}
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
//~PxConstraintConnector
|
||||
private:
|
||||
float mVirtualAngle0;
|
||||
float mVirtualAngle1;
|
||||
float mPersistentAngle0;
|
||||
float mPersistentAngle1;
|
||||
bool mInitDone;
|
||||
|
||||
void updateError();
|
||||
void resetError();
|
||||
};
|
||||
} // namespace Ext
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
284
engine/third_party/physx/source/physxextensions/src/ExtGjkQueryExt.cpp
vendored
Normal file
284
engine/third_party/physx/source/physxextensions/src/ExtGjkQueryExt.cpp
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
// 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/PxGjkQueryExt.h"
|
||||
#include "geometry/PxSphereGeometry.h"
|
||||
#include "geometry/PxBoxGeometry.h"
|
||||
#include "geometry/PxPlaneGeometry.h"
|
||||
#include "geometry/PxCapsuleGeometry.h"
|
||||
#include "geometry/PxConvexCoreGeometry.h"
|
||||
#include "geometry/PxConvexMeshGeometry.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "geomutils/PxContactBuffer.h"
|
||||
#include "GuConvexSupport.h"
|
||||
#include "GuConvexGeometry.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::SphereSupport::SphereSupport() : radius(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::SphereSupport::SphereSupport(PxReal _radius) : radius(_radius)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::SphereSupport::SphereSupport(const PxSphereGeometry& geom) : radius(geom.radius)
|
||||
{
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::SphereSupport::getMargin() const
|
||||
{
|
||||
return radius;
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::SphereSupport::supportLocal(const PxVec3& /*dir*/) const
|
||||
{
|
||||
return PxVec3(0.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::CapsuleSupport::CapsuleSupport() : radius(0.0f), halfHeight(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::CapsuleSupport::CapsuleSupport(PxReal _radius, PxReal _halfHeight) : radius(_radius), halfHeight(_halfHeight)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::CapsuleSupport::CapsuleSupport(const PxCapsuleGeometry& geom) : radius(geom.radius)
|
||||
{
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::CapsuleSupport::getMargin() const
|
||||
{
|
||||
return radius;
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::CapsuleSupport::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
return PxVec3(PxSign2(dir.x) * halfHeight, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::BoxSupport::BoxSupport() : halfExtents(0.0f), margin(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::BoxSupport::BoxSupport(const PxVec3& _halfExtents, PxReal _margin) : halfExtents(_halfExtents), margin(_margin)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::BoxSupport::BoxSupport(const PxBoxGeometry& box, PxReal _margin) : halfExtents(box.halfExtents), margin(_margin)
|
||||
{
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::BoxSupport::getMargin() const
|
||||
{
|
||||
return margin;
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::BoxSupport::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
const PxVec3 d = dir.getNormalized();
|
||||
return PxVec3(PxSign2(d.x) * halfExtents.x, PxSign2(d.y) * halfExtents.y, PxSign2(d.z) * halfExtents.z);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::ConvexCoreSupport::ConvexCoreSupport()
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::ConvexCoreSupport::ConvexCoreSupport(const PxConvexCoreGeometry& geom, PxReal margin)
|
||||
{
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(shapeData) >= sizeof(Gu::ConvexShape));
|
||||
|
||||
Gu::ConvexShape& convex = *reinterpret_cast<Gu::ConvexShape*>(shapeData);
|
||||
Gu::makeConvexShape(geom, PxTransform(PxIdentity), convex);
|
||||
convex.margin += margin;
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::ConvexCoreSupport::getMargin() const
|
||||
{
|
||||
const Gu::ConvexShape& convex = *reinterpret_cast<const Gu::ConvexShape*>(shapeData);
|
||||
return convex.margin;
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::ConvexCoreSupport::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
const Gu::ConvexShape& convex = *reinterpret_cast<const Gu::ConvexShape*>(shapeData);
|
||||
return convex.supportLocal(dir);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::ConvexMeshSupport::ConvexMeshSupport() :
|
||||
convexMesh (NULL),
|
||||
scale (0.0f),
|
||||
scaleRotation (0.0f),
|
||||
margin (0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::ConvexMeshSupport::ConvexMeshSupport(const PxConvexMesh& _convexMesh, const PxVec3& _scale, const PxQuat& _scaleRotation, PxReal _margin) :
|
||||
convexMesh (&_convexMesh),
|
||||
scale (_scale),
|
||||
scaleRotation (_scaleRotation),
|
||||
margin (_margin)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::ConvexMeshSupport::ConvexMeshSupport(const PxConvexMeshGeometry& _convexMesh, PxReal _margin) :
|
||||
convexMesh (_convexMesh.convexMesh),
|
||||
scale (_convexMesh.scale.scale),
|
||||
scaleRotation (_convexMesh.scale.rotation),
|
||||
margin (_margin)
|
||||
{
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::ConvexMeshSupport::getMargin() const
|
||||
{
|
||||
return margin * scale.minElement();
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::ConvexMeshSupport::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
if (convexMesh == NULL)
|
||||
return PxVec3(0.0f);
|
||||
|
||||
PxVec3 d = scaleRotation.rotateInv(scaleRotation.rotate(dir).multiply(scale));
|
||||
const PxVec3* verts = convexMesh->getVertices();
|
||||
int count = int(convexMesh->getNbVertices());
|
||||
float maxDot = -FLT_MAX;
|
||||
int index = -1;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
float dot = verts[i].dot(d);
|
||||
if (dot > maxDot)
|
||||
{
|
||||
maxDot = dot;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
return PxVec3(0);
|
||||
|
||||
return scaleRotation.rotateInv(scaleRotation.rotate(verts[index]).multiply(scale));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxGjkQueryExt::ConvexGeomSupport::ConvexGeomSupport() : mType(PxGeometryType::eINVALID)
|
||||
{
|
||||
}
|
||||
|
||||
PxGjkQueryExt::ConvexGeomSupport::ConvexGeomSupport(const PxGeometry& geom, PxReal margin)
|
||||
{
|
||||
mType = PxGeometryType::eINVALID;
|
||||
switch (geom.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
{
|
||||
mType = PxGeometryType::eSPHERE;
|
||||
const PxSphereGeometry& sphere = static_cast<const PxSphereGeometry&>(geom);
|
||||
PX_PLACEMENT_NEW(&mSupport, SphereSupport(sphere.radius + margin));
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eCAPSULE:
|
||||
{
|
||||
mType = PxGeometryType::eCAPSULE;
|
||||
const PxCapsuleGeometry& capsule = static_cast<const PxCapsuleGeometry&>(geom);
|
||||
PX_PLACEMENT_NEW(&mSupport, CapsuleSupport(capsule.radius + margin, capsule.halfHeight));
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eBOX:
|
||||
{
|
||||
mType = PxGeometryType::eBOX;
|
||||
PX_PLACEMENT_NEW(&mSupport, BoxSupport(static_cast<const PxBoxGeometry&>(geom), margin));
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eCONVEXCORE:
|
||||
{
|
||||
mType = PxGeometryType::eCONVEXCORE;
|
||||
PX_PLACEMENT_NEW(&mSupport, ConvexCoreSupport(static_cast<const PxConvexCoreGeometry&>(geom), margin));
|
||||
break;
|
||||
}
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
mType = PxGeometryType::eCONVEXMESH;
|
||||
PX_PLACEMENT_NEW(&mSupport, ConvexMeshSupport(static_cast<const PxConvexMeshGeometry&>(geom), margin));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PxGjkQueryExt::ConvexGeomSupport::~ConvexGeomSupport()
|
||||
{
|
||||
if (isValid())
|
||||
reinterpret_cast<Support&>(mSupport).~Support();
|
||||
}
|
||||
|
||||
bool PxGjkQueryExt::ConvexGeomSupport::isValid() const
|
||||
{
|
||||
return mType != PxGeometryType::eINVALID;
|
||||
}
|
||||
|
||||
PxReal PxGjkQueryExt::ConvexGeomSupport::getMargin() const
|
||||
{
|
||||
return isValid() ? reinterpret_cast<const Support&>(mSupport).getMargin() : 0.0f;
|
||||
}
|
||||
|
||||
PxVec3 PxGjkQueryExt::ConvexGeomSupport::supportLocal(const PxVec3& dir) const
|
||||
{
|
||||
return isValid() ? reinterpret_cast<const Support&>(mSupport).supportLocal(dir) : PxVec3(0.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool PxGjkQueryExt::generateContacts(const PxGjkQuery::Support& a, const PxGjkQuery::Support& b, const PxTransform& poseA, const PxTransform& poseB, PxReal contactDistance, PxReal toleranceLength, PxContactBuffer& contactBuffer)
|
||||
{
|
||||
PxVec3 pointA, pointB, separatingAxis; PxReal separation;
|
||||
if (!PxGjkQuery::proximityInfo(a, b, poseA, poseB, contactDistance, toleranceLength, pointA, pointB, separatingAxis, separation))
|
||||
return false;
|
||||
|
||||
PxContactPoint contact;
|
||||
contact.point = (pointA + pointB) * 0.5f; // VR: should I make it just pointB?
|
||||
contact.normal = separatingAxis;
|
||||
contact.separation = separation;
|
||||
contactBuffer.contact(contact);
|
||||
|
||||
return true;
|
||||
}
|
||||
376
engine/third_party/physx/source/physxextensions/src/ExtInertiaTensor.h
vendored
Normal file
376
engine/third_party/physx/source/physxextensions/src/ExtInertiaTensor.h
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
// 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 EXT_INERTIA_TENSOR_H
|
||||
#define EXT_INERTIA_TENSOR_H
|
||||
|
||||
#include "foundation/PxMat33.h"
|
||||
#include "foundation/PxMathUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
class InertiaTensorComputer
|
||||
{
|
||||
public:
|
||||
InertiaTensorComputer(bool initTozero = true);
|
||||
InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass);
|
||||
~InertiaTensorComputer();
|
||||
|
||||
PX_INLINE void zero(); //sets to zero mass
|
||||
PX_INLINE void setDiagonal(PxReal mass, const PxVec3& diagonal); //sets as a diagonal tensor
|
||||
PX_INLINE void rotate(const PxMat33& rot); //rotates the mass
|
||||
void translate(const PxVec3& t); //translates the mass
|
||||
PX_INLINE void transform(const PxTransform& transform); //transforms the mass
|
||||
PX_INLINE void scaleDensity(PxReal densityScale); //scales by a density factor
|
||||
PX_INLINE void add(const InertiaTensorComputer& it); //adds a mass
|
||||
PX_INLINE void center(); //recenters inertia around center of mass
|
||||
|
||||
void setBox(const PxVec3& halfWidths); //sets as an axis aligned box
|
||||
PX_INLINE void setBox(const PxVec3& halfWidths, const PxTransform* pose); //sets as an oriented box
|
||||
|
||||
void setSphere(PxReal radius);
|
||||
PX_INLINE void setSphere(PxReal radius, const PxTransform* pose);
|
||||
|
||||
void setCylinder(int dir, PxReal r, PxReal l);
|
||||
PX_INLINE void setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose);
|
||||
|
||||
void setCapsule(int dir, PxReal r, PxReal l);
|
||||
PX_INLINE void setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose);
|
||||
|
||||
void setEllipsoid(PxReal rx, PxReal ry, PxReal rz);
|
||||
PX_INLINE void setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose);
|
||||
|
||||
PX_INLINE PxVec3 getCenterOfMass() const { return mG; }
|
||||
PX_INLINE PxReal getMass() const { return mMass; }
|
||||
PX_INLINE PxMat33 getInertia() const { return mI; }
|
||||
|
||||
private:
|
||||
PxMat33 mI;
|
||||
PxVec3 mG;
|
||||
PxReal mMass;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
// Helper routines
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
// Special version allowing 2D quads
|
||||
PX_INLINE PxReal volume(const PxVec3& extents)
|
||||
{
|
||||
PxReal v = 1.0f;
|
||||
if(extents.x != 0.0f) v*=extents.x;
|
||||
if(extents.y != 0.0f) v*=extents.y;
|
||||
if(extents.z != 0.0f) v*=extents.z;
|
||||
return v;
|
||||
}
|
||||
|
||||
// Sphere
|
||||
PX_INLINE PxReal computeSphereRatio(PxReal radius) { return (4.0f/3.0f) * PxPi * radius * radius * radius; }
|
||||
PxReal computeSphereMass(PxReal radius, PxReal density) { return density * computeSphereRatio(radius); }
|
||||
PxReal computeSphereDensity(PxReal radius, PxReal mass) { return mass / computeSphereRatio(radius); }
|
||||
|
||||
// Box
|
||||
PX_INLINE PxReal computeBoxRatio(const PxVec3& extents) { return volume(extents); }
|
||||
PxReal computeBoxMass(const PxVec3& extents, PxReal density) { return density * computeBoxRatio(extents); }
|
||||
PxReal computeBoxDensity(const PxVec3& extents, PxReal mass) { return mass / computeBoxRatio(extents); }
|
||||
|
||||
// Ellipsoid
|
||||
PX_INLINE PxReal computeEllipsoidRatio(const PxVec3& extents) { return (4.0f/3.0f) * PxPi * volume(extents); }
|
||||
PxReal computeEllipsoidMass(const PxVec3& extents, PxReal density) { return density * computeEllipsoidRatio(extents); }
|
||||
PxReal computeEllipsoidDensity(const PxVec3& extents, PxReal mass) { return mass / computeEllipsoidRatio(extents); }
|
||||
|
||||
// Cylinder
|
||||
PX_INLINE PxReal computeCylinderRatio(PxReal r, PxReal l) { return PxPi * r * r * (2.0f*l); }
|
||||
PxReal computeCylinderMass(PxReal r, PxReal l, PxReal density) { return density * computeCylinderRatio(r, l); }
|
||||
PxReal computeCylinderDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCylinderRatio(r, l); }
|
||||
|
||||
// Capsule
|
||||
PX_INLINE PxReal computeCapsuleRatio(PxReal r, PxReal l) { return computeSphereRatio(r) + computeCylinderRatio(r, l);}
|
||||
PxReal computeCapsuleMass(PxReal r, PxReal l, PxReal density) { return density * computeCapsuleRatio(r, l); }
|
||||
PxReal computeCapsuleDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCapsuleRatio(r, l); }
|
||||
|
||||
// Cone
|
||||
PX_INLINE PxReal computeConeRatio(PxReal r, PxReal l) { return PxPi * r * r * PxAbs(l)/3.0f; }
|
||||
PxReal computeConeMass(PxReal r, PxReal l, PxReal density) { return density * computeConeRatio(r, l); }
|
||||
PxReal computeConeDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeConeRatio(r, l); }
|
||||
|
||||
void computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength);
|
||||
void computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow);
|
||||
bool jacobiTransform(PxI32 n, PxF64 a[], PxF64 w[]);
|
||||
bool diagonalizeInertiaTensor(const PxMat33& denseInertia, PxVec3& diagonalInertia, PxMat33& rotation);
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
void Ext::computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength)
|
||||
{
|
||||
//to model a hollow block, one would have to multiply coeff by up to two.
|
||||
const PxReal coeff = mass/12;
|
||||
inertia.x = coeff * (ylength*ylength + zlength*zlength);
|
||||
inertia.y = coeff * (xlength*xlength + zlength*zlength);
|
||||
inertia.z = coeff * (xlength*xlength + ylength*ylength);
|
||||
|
||||
PX_ASSERT(inertia.x != 0.0f);
|
||||
PX_ASSERT(inertia.y != 0.0f);
|
||||
PX_ASSERT(inertia.z != 0.0f);
|
||||
PX_ASSERT(inertia.isFinite());
|
||||
}
|
||||
|
||||
void Ext::computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow)
|
||||
{
|
||||
inertia.x = mass * radius * radius;
|
||||
if (hollow)
|
||||
inertia.x *= PxReal(2 / 3.0);
|
||||
else
|
||||
inertia.x *= PxReal(2 / 5.0);
|
||||
|
||||
inertia.z = inertia.y = inertia.x;
|
||||
PX_ASSERT(inertia.isFinite());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
// InertiaTensorComputer implementation
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
Ext::InertiaTensorComputer::InertiaTensorComputer(bool initTozero)
|
||||
{
|
||||
if (initTozero)
|
||||
zero();
|
||||
}
|
||||
|
||||
Ext::InertiaTensorComputer::InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass) :
|
||||
mI(inertia),
|
||||
mG(com),
|
||||
mMass(mass)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Ext::InertiaTensorComputer::~InertiaTensorComputer()
|
||||
{
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::zero()
|
||||
{
|
||||
mMass = 0.0f;
|
||||
mI = PxMat33(PxZero);
|
||||
mG = PxVec3(0);
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setDiagonal(PxReal mass, const PxVec3& diag)
|
||||
{
|
||||
mMass = mass;
|
||||
mI = PxMat33::createDiagonal(diag);
|
||||
mG = PxVec3(0);
|
||||
PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
|
||||
PX_ASSERT(PxIsFinite(mMass));
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths)
|
||||
{
|
||||
// Setup inertia tensor for a cube with unit density
|
||||
const PxReal mass = 8.0f * computeBoxRatio(halfWidths);
|
||||
const PxReal s =(1.0f/3.0f) * mass;
|
||||
|
||||
const PxReal x = halfWidths.x*halfWidths.x;
|
||||
const PxReal y = halfWidths.y*halfWidths.y;
|
||||
const PxReal z = halfWidths.z*halfWidths.z;
|
||||
|
||||
setDiagonal(mass, PxVec3(y+z, z+x, x+y) * s);
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::rotate(const PxMat33& rot)
|
||||
{
|
||||
//well known inertia tensor rotation expression is: RIR' -- this could be optimized due to symmetry, see code to do that in Body::updateGlobalInverseInertia
|
||||
mI = rot * mI * rot.getTranspose();
|
||||
PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
|
||||
//com also needs to be rotated
|
||||
mG = rot * mG;
|
||||
PX_ASSERT(mG.isFinite());
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::translate(const PxVec3& t)
|
||||
{
|
||||
if (!t.isZero()) //its common for this to be zero
|
||||
{
|
||||
PxMat33 t1, t2;
|
||||
|
||||
t1.column0 = PxVec3(0, mG.z, -mG.y);
|
||||
t1.column1 = PxVec3(-mG.z, 0, mG.x);
|
||||
t1.column2 = PxVec3(mG.y, -mG.x, 0);
|
||||
|
||||
PxVec3 sum = mG + t;
|
||||
if (sum.isZero())
|
||||
{
|
||||
mI += (t1 * t1)*mMass;
|
||||
}
|
||||
else
|
||||
{
|
||||
t2.column0 = PxVec3(0, sum.z, -sum.y);
|
||||
t2.column1 = PxVec3(-sum.z, 0, sum.x);
|
||||
t2.column2 = PxVec3(sum.y, -sum.x, 0);
|
||||
mI += (t1 * t1 - t2 * t2)*mMass;
|
||||
}
|
||||
|
||||
//move center of mass
|
||||
mG += t;
|
||||
|
||||
PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
|
||||
PX_ASSERT(mG.isFinite());
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::transform(const PxTransform& transform)
|
||||
{
|
||||
rotate(PxMat33(transform.q));
|
||||
translate(transform.p);
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths, const PxTransform* pose)
|
||||
{
|
||||
setBox(halfWidths);
|
||||
if (pose)
|
||||
transform(*pose);
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::scaleDensity(PxReal densityScale)
|
||||
{
|
||||
mI *= densityScale;
|
||||
mMass *= densityScale;
|
||||
PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
|
||||
PX_ASSERT(PxIsFinite(mMass));
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::add(const InertiaTensorComputer& it)
|
||||
{
|
||||
const PxReal TotalMass = mMass + it.mMass;
|
||||
mG = (mG * mMass + it.mG * it.mMass) / TotalMass;
|
||||
|
||||
mMass = TotalMass;
|
||||
mI += it.mI;
|
||||
PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
|
||||
PX_ASSERT(mG.isFinite());
|
||||
PX_ASSERT(PxIsFinite(mMass));
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::center()
|
||||
{
|
||||
PxVec3 center = -mG;
|
||||
translate(center);
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::setSphere(PxReal radius)
|
||||
{
|
||||
// Compute mass of the sphere
|
||||
const PxReal m = computeSphereRatio(radius);
|
||||
// Compute moment of inertia
|
||||
const PxReal s = m * radius * radius * (2.0f/5.0f);
|
||||
setDiagonal(m,PxVec3(s,s,s));
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setSphere(PxReal radius, const PxTransform* pose)
|
||||
{
|
||||
setSphere(radius);
|
||||
if (pose)
|
||||
transform(*pose);
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l)
|
||||
{
|
||||
// Compute mass of cylinder
|
||||
const PxReal m = computeCylinderRatio(r, l);
|
||||
|
||||
const PxReal i1 = r*r*m/2.0f;
|
||||
const PxReal i2 = (3.0f*r*r+4.0f*l*l)*m/12.0f;
|
||||
|
||||
switch(dir)
|
||||
{
|
||||
case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break;
|
||||
case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break;
|
||||
default: setDiagonal(m,PxVec3(i2,i2,i1)); break;
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose)
|
||||
{
|
||||
setCylinder(dir, r, l);
|
||||
if (pose)
|
||||
transform(*pose);
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l)
|
||||
{
|
||||
// Compute mass of capsule
|
||||
const PxReal m = computeCapsuleRatio(r, l);
|
||||
|
||||
const PxReal t = PxPi * r * r;
|
||||
const PxReal i1 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r));
|
||||
const PxReal i2 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r * 3.0f/2.0f) + (l*l*r * 4.0f/3.0f) + (l*l*l * 2.0f/3.0f));
|
||||
|
||||
switch(dir)
|
||||
{
|
||||
case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break;
|
||||
case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break;
|
||||
default: setDiagonal(m,PxVec3(i2,i2,i1)); break;
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose)
|
||||
{
|
||||
setCapsule(dir, r, l);
|
||||
if (pose)
|
||||
transform(*pose);
|
||||
}
|
||||
|
||||
void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz)
|
||||
{
|
||||
// Compute mass of ellipsoid
|
||||
const PxReal m = computeEllipsoidRatio(PxVec3(rx, ry, rz));
|
||||
|
||||
// Compute moment of inertia
|
||||
const PxReal s = m * (2.0f/5.0f);
|
||||
|
||||
// Setup inertia tensor for an ellipsoid centered at the origin
|
||||
setDiagonal(m,PxVec3(ry*rz,rz*rx,rx*ry)*s);
|
||||
}
|
||||
|
||||
PX_INLINE void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose)
|
||||
{
|
||||
setEllipsoid(rx,ry,rz);
|
||||
if (pose)
|
||||
transform(*pose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
164
engine/third_party/physx/source/physxextensions/src/ExtJoint.cpp
vendored
Normal file
164
engine/third_party/physx/source/physxextensions/src/ExtJoint.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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 "ExtJoint.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
// PX_SERIALIZATION
|
||||
PxConstraint* physx::resolveConstraintPtr(PxDeserializationContext& v, PxConstraint* old, PxConstraintConnector* connector, PxConstraintShaderTable &shaders)
|
||||
{
|
||||
v.translatePxBase(old);
|
||||
PxConstraint* new_nx = static_cast<PxConstraint*>(old);
|
||||
new_nx->setConstraintFunctions(*connector, shaders);
|
||||
return new_nx;
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
static void normalToTangents(const PxVec3& n, PxVec3& t1, PxVec3& t2)
|
||||
{
|
||||
const PxReal m_sqrt1_2 = PxReal(0.7071067811865475244008443621048490);
|
||||
if(fabsf(n.z) > m_sqrt1_2)
|
||||
{
|
||||
const PxReal a = n.y*n.y + n.z*n.z;
|
||||
const PxReal k = PxReal(1.0)/PxSqrt(a);
|
||||
t1 = PxVec3(0,-n.z*k,n.y*k);
|
||||
t2 = PxVec3(a*k,-n.x*t1.z,n.x*t1.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxReal a = n.x*n.x + n.y*n.y;
|
||||
const PxReal k = PxReal(1.0)/PxSqrt(a);
|
||||
t1 = PxVec3(-n.y*k,n.x*k,0);
|
||||
t2 = PxVec3(-n.z*t1.y,n.z*t1.x,a*k);
|
||||
}
|
||||
t1.normalize();
|
||||
t2.normalize();
|
||||
}
|
||||
|
||||
void PxSetJointGlobalFrame(PxJoint& joint, const PxVec3* wsAnchor, const PxVec3* axisIn)
|
||||
{
|
||||
PxRigidActor* actors[2];
|
||||
joint.getActors(actors[0], actors[1]);
|
||||
|
||||
PxTransform localPose[2];
|
||||
for(PxU32 i=0; i<2; i++)
|
||||
localPose[i] = PxTransform(PxIdentity);
|
||||
|
||||
// 1) global anchor
|
||||
if(wsAnchor)
|
||||
{
|
||||
//transform anchorPoint to local space
|
||||
for(PxU32 i=0; i<2; i++)
|
||||
localPose[i].p = actors[i] ? actors[i]->getGlobalPose().transformInv(*wsAnchor) : *wsAnchor;
|
||||
}
|
||||
|
||||
// 2) global axis
|
||||
if(axisIn)
|
||||
{
|
||||
PxVec3 localAxis[2], localNormal[2];
|
||||
|
||||
//find 2 orthogonal vectors.
|
||||
//gotta do this in world space, if we choose them
|
||||
//separately in local space they won't match up in worldspace.
|
||||
PxVec3 axisw = *axisIn;
|
||||
axisw.normalize();
|
||||
|
||||
PxVec3 normalw, binormalw;
|
||||
::normalToTangents(axisw, binormalw, normalw);
|
||||
//because axis is supposed to be the Z axis of a frame with the other two being X and Y, we need to negate
|
||||
//Y to make the frame right handed. Note that the above call makes a right handed frame if we pass X --> Y,Z, so
|
||||
//it need not be changed.
|
||||
|
||||
for(PxU32 i=0; i<2; i++)
|
||||
{
|
||||
if(actors[i])
|
||||
{
|
||||
const PxTransform& m = actors[i]->getGlobalPose();
|
||||
PxMat33 mM(m.q);
|
||||
localAxis[i] = mM.transformTranspose(axisw);
|
||||
localNormal[i] = mM.transformTranspose(normalw);
|
||||
}
|
||||
else
|
||||
{
|
||||
localAxis[i] = axisw;
|
||||
localNormal[i] = normalw;
|
||||
}
|
||||
|
||||
PxMat33 rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i]));
|
||||
|
||||
localPose[i].q = PxQuat(rot);
|
||||
localPose[i].q.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
for(PxU32 i=0; i<2; i++)
|
||||
joint.setLocalPose(static_cast<PxJointActorIndex::Enum>( i ), localPose[i]);
|
||||
}
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
void physx::Ext::omniPvdSetBaseJointParams(const PxJoint& joint, PxJointConcreteType::Enum cType)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
const PxJoint& j = static_cast<const PxJoint&>(joint);
|
||||
PxRigidActor* actors[2]; j.getActors(actors[0], actors[1]);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor0, j, actors[0])
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor1, j, actors[1])
|
||||
|
||||
PxConstraint* constraint = j.getConstraint();
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, constraint, j, constraint)
|
||||
|
||||
PxTransform actor0LocalPose = j.getLocalPose(PxJointActorIndex::eACTOR0);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor0LocalPose, j, actor0LocalPose)
|
||||
PxTransform actor1LocalPose = j.getLocalPose(PxJointActorIndex::eACTOR1);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor1LocalPose, j, actor1LocalPose)
|
||||
PxReal breakForce, breakTorque; j.getBreakForce(breakForce, breakTorque);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, breakForce, j, breakForce)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, breakTorque, j, breakTorque)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, constraintFlags, j, j.getConstraintFlags())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, invMassScale0, j, j.getInvMassScale0())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, invInertiaScale0, j, j.getInvInertiaScale0())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, invMassScale1, j, j.getInvMassScale1())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, invInertiaScale1, j, j.getInvInertiaScale1())
|
||||
const char* name = j.getName() ? j.getName() : "";
|
||||
PxU32 nameLen = PxU32(strlen(name)) + 1;
|
||||
OMNI_PVD_SET_ARRAY_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, name, j, name, nameLen)
|
||||
const char* typeName = j.getConcreteTypeName();
|
||||
PxU32 typeNameLen = PxU32(strlen(typeName)) + 1;
|
||||
OMNI_PVD_SET_ARRAY_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, concreteTypeName, j, typeName, typeNameLen)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, type, j, cType)
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
726
engine/third_party/physx/source/physxextensions/src/ExtJoint.h
vendored
Normal file
726
engine/third_party/physx/source/physxextensions/src/ExtJoint.h
vendored
Normal file
@@ -0,0 +1,726 @@
|
||||
// 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 EXT_JOINT_H
|
||||
#define EXT_JOINT_H
|
||||
|
||||
#include "PxPhysics.h"
|
||||
#include "extensions/PxConstraintExt.h"
|
||||
#include "PxRigidStatic.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
#include "PxArticulationLink.h"
|
||||
#include "PxArticulationReducedCoordinate.h"
|
||||
#include "PxScene.h"
|
||||
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxMathUtils.h"
|
||||
#include "CmUtils.h"
|
||||
#include "ExtJointData.h"
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
#include "pvd/PxPvdSceneClient.h"
|
||||
#include "ExtPvd.h"
|
||||
#include "PxPvdClient.h"
|
||||
#endif
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
// PX_SERIALIZATION
|
||||
class PxDeserializationContext;
|
||||
|
||||
PxConstraint* resolveConstraintPtr(PxDeserializationContext& v, PxConstraint* old, PxConstraintConnector* connector, PxConstraintShaderTable& shaders);
|
||||
|
||||
// ~PX_SERIALIZATION
|
||||
|
||||
namespace Ext
|
||||
{
|
||||
PX_FORCE_INLINE float computeSwingAngle(float swingYZ, float swingW)
|
||||
{
|
||||
return 4.0f * PxAtan2(swingYZ, 1.0f + swingW); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle
|
||||
}
|
||||
|
||||
template<class JointType, class DataType>
|
||||
PX_FORCE_INLINE JointType* createJointT(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1, const PxConstraintShaderTable& shaders)
|
||||
{
|
||||
JointType* j;
|
||||
PX_NEW_SERIALIZED(j, JointType)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
|
||||
|
||||
if(!physics.createConstraint(actor0, actor1, *j, shaders, sizeof(DataType)))
|
||||
PX_DELETE(j);
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
if (j)
|
||||
{
|
||||
omniPvdInitJoint(*j);
|
||||
}
|
||||
#endif
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
template<class JointType>
|
||||
PX_FORCE_INLINE JointType* createJointObject(PxU8*& address, PxDeserializationContext& context)
|
||||
{
|
||||
JointType* obj = PX_PLACEMENT_NEW(address, JointType(PxBaseFlag::eIS_RELEASABLE));
|
||||
address += sizeof(JointType);
|
||||
obj->importExtraData(context);
|
||||
obj->resolveReferences(context);
|
||||
return obj;
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
template <class Base, class DataClass, class ValueStruct>
|
||||
class JointT : public Base, public PxConstraintConnector, public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
JointT(PxBaseFlags baseFlags) : Base(baseFlags) {}
|
||||
|
||||
void exportExtraData(PxSerializationContext& stream)
|
||||
{
|
||||
if(mData)
|
||||
{
|
||||
stream.alignData(PX_SERIAL_ALIGN);
|
||||
stream.writeData(mData, sizeof(DataClass));
|
||||
}
|
||||
stream.writeName(mName);
|
||||
}
|
||||
|
||||
void importExtraData(PxDeserializationContext& context)
|
||||
{
|
||||
if(mData)
|
||||
mData = context.readExtraData<DataClass, PX_SERIAL_ALIGN>();
|
||||
context.readName(mName);
|
||||
}
|
||||
|
||||
virtual void preExportDataReset(){}
|
||||
virtual void requiresObjects(PxProcessPxBaseCallback& c)
|
||||
{
|
||||
c.process(*mPxConstraint);
|
||||
|
||||
{
|
||||
PxRigidActor* a0 = NULL;
|
||||
PxRigidActor* a1 = NULL;
|
||||
mPxConstraint->getActors(a0,a1);
|
||||
|
||||
if (a0)
|
||||
{
|
||||
c.process(*a0);
|
||||
}
|
||||
if (a1)
|
||||
{
|
||||
c.process(*a1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
// PxConstraintConnector
|
||||
virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint* c, PxPvdUpdateType::Enum updateType) const PX_OVERRIDE
|
||||
{
|
||||
if(updateType == PxPvdUpdateType::UPDATE_SIM_PROPERTIES)
|
||||
{
|
||||
Ext::Pvd::simUpdate<Base>(pvdConnection, *this);
|
||||
return true;
|
||||
}
|
||||
else if(updateType == PxPvdUpdateType::UPDATE_ALL_PROPERTIES)
|
||||
{
|
||||
Ext::Pvd::updatePvdProperties<Base, ValueStruct>(pvdConnection, *this);
|
||||
return true;
|
||||
}
|
||||
else if(updateType == PxPvdUpdateType::CREATE_INSTANCE)
|
||||
{
|
||||
Ext::Pvd::createPvdInstance<Base>(pvdConnection, *c, *this);
|
||||
return true;
|
||||
}
|
||||
else if(updateType == PxPvdUpdateType::RELEASE_INSTANCE)
|
||||
{
|
||||
Ext::Pvd::releasePvdInstance(pvdConnection, *c, *this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream&, const PxConstraint*, PxPvdUpdateType::Enum) const PX_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE
|
||||
{
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setActors(PxRigidActor* actor0, PxRigidActor* actor1) PX_OVERRIDE
|
||||
{
|
||||
//TODO SDK-DEV
|
||||
//You can get the debugger stream from the NpScene
|
||||
//Ext::Pvd::setActors( stream, this, mPxConstraint, actor0, actor1 );
|
||||
PX_CHECK_AND_RETURN(actor0 != actor1, "PxJoint::setActors: actors must be different");
|
||||
PX_CHECK_AND_RETURN((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "PxJoint::setActors: at least one actor must be non-static");
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
PxScene* scene = getScene();
|
||||
if(scene)
|
||||
{
|
||||
//if pvd not connect data stream is NULL
|
||||
physx::pvdsdk::PvdDataStream* conn = scene->getScenePvdClient()->getClientInternal()->getDataStream();
|
||||
if( conn != NULL )
|
||||
Ext::Pvd::setActors(
|
||||
*conn,
|
||||
*this,
|
||||
*mPxConstraint,
|
||||
actor0,
|
||||
actor1
|
||||
);
|
||||
}
|
||||
#endif
|
||||
mPxConstraint->setActors(actor0, actor1);
|
||||
mData->c2b[0] = getCom(actor0).transformInv(mLocalPose[0]);
|
||||
mData->c2b[1] = getCom(actor1).transformInv(mLocalPose[1]);
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor0, static_cast<PxJoint&>(*this), actor0)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor1, static_cast<PxJoint&>(*this), actor1)
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const PX_OVERRIDE
|
||||
{
|
||||
if(mPxConstraint)
|
||||
mPxConstraint->getActors(actor0,actor1);
|
||||
else
|
||||
{
|
||||
actor0 = NULL;
|
||||
actor1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// this is the local pose relative to the actor, and we store internally the local
|
||||
// pose relative to the body
|
||||
|
||||
// PxJoint
|
||||
virtual void setLocalPose(PxJointActorIndex::Enum actor, const PxTransform& pose) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(pose.isSane(), "PxJoint::setLocalPose: transform is invalid");
|
||||
const PxTransform p = pose.getNormalized();
|
||||
mLocalPose[actor] = p;
|
||||
mData->c2b[actor] = getCom(actor).transformInv(p);
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor0LocalPose, static_cast<PxJoint&>(*this), mLocalPose[0])
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, actor1LocalPose, static_cast<PxJoint&>(*this), mLocalPose[1])
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxTransform getLocalPose(PxJointActorIndex::Enum actor) const PX_OVERRIDE
|
||||
{
|
||||
return mLocalPose[actor];
|
||||
}
|
||||
|
||||
static PxTransform getGlobalPose(const PxRigidActor* actor)
|
||||
{
|
||||
if(!actor)
|
||||
return PxTransform(PxIdentity);
|
||||
return actor->getGlobalPose();
|
||||
}
|
||||
|
||||
static void getActorVelocity(const PxRigidActor* actor, PxVec3& linear, PxVec3& angular)
|
||||
{
|
||||
if(!actor || actor->is<PxRigidStatic>())
|
||||
{
|
||||
linear = angular = PxVec3(0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
linear = static_cast<const PxRigidBody*>(actor)->getLinearVelocity();
|
||||
angular = static_cast<const PxRigidBody*>(actor)->getAngularVelocity();
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxTransform getRelativeTransform() const PX_OVERRIDE
|
||||
{
|
||||
PxRigidActor* actor0, * actor1;
|
||||
mPxConstraint->getActors(actor0, actor1);
|
||||
const PxTransform t0 = getGlobalPose(actor0) * mLocalPose[0];
|
||||
const PxTransform t1 = getGlobalPose(actor1) * mLocalPose[1];
|
||||
return t0.transformInv(t1);
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxVec3 getRelativeLinearVelocity() const PX_OVERRIDE
|
||||
{
|
||||
PxRigidActor* actor0, * actor1;
|
||||
PxVec3 l0, a0, l1, a1;
|
||||
mPxConstraint->getActors(actor0, actor1);
|
||||
|
||||
const PxTransform actor0ToWorld = getGlobalPose(actor0);
|
||||
const PxTransform actor1ToWorld = getGlobalPose(actor1);
|
||||
|
||||
const PxTransform body0ToActor = getCom(actor0);
|
||||
const PxTransform body1ToActor = getCom(actor1);
|
||||
|
||||
getActorVelocity(actor0, l0, a0);
|
||||
getActorVelocity(actor1, l1, a1);
|
||||
|
||||
// the offset from center of mass to joint frame origin (in the
|
||||
// actor frame)
|
||||
const PxVec3 jointFrame0CoMOffsetLocal = mLocalPose[0].p - body0ToActor.p;
|
||||
const PxVec3 jointFrame1CoMOffsetLocal = mLocalPose[1].p - body1ToActor.p;
|
||||
|
||||
const PxVec3 jointFrame0CoMOffsetWorld = actor0ToWorld.rotate(jointFrame0CoMOffsetLocal);
|
||||
const PxVec3 jointFrame1CoMOffsetWorld = actor1ToWorld.rotate(jointFrame1CoMOffsetLocal);
|
||||
|
||||
const PxVec3 relativeVelWorld = (l1 + a1.cross(jointFrame1CoMOffsetWorld)) -
|
||||
(l0 + a0.cross(jointFrame0CoMOffsetWorld));
|
||||
|
||||
const PxQuat jointFrame0ToWorld = actor0ToWorld.q * mLocalPose[0].q;
|
||||
const PxVec3 relativeVelJointFrame0 = jointFrame0ToWorld.rotateInv(relativeVelWorld);
|
||||
|
||||
return relativeVelJointFrame0;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxVec3 getRelativeAngularVelocity() const PX_OVERRIDE
|
||||
{
|
||||
PxRigidActor* actor0, * actor1;
|
||||
PxVec3 l0, a0, l1, a1;
|
||||
mPxConstraint->getActors(actor0, actor1);
|
||||
|
||||
const PxTransform actor0ToWorld = getGlobalPose(actor0);
|
||||
|
||||
getActorVelocity(actor0, l0, a0);
|
||||
getActorVelocity(actor1, l1, a1);
|
||||
|
||||
const PxVec3 relativeVelWorld = a1 - a0;
|
||||
|
||||
const PxQuat jointFrame0ToWorld = actor0ToWorld.q * mLocalPose[0].q;
|
||||
const PxVec3 relativeVelJointFrame0 = jointFrame0ToWorld.rotateInv(relativeVelWorld);
|
||||
|
||||
return relativeVelJointFrame0;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setBreakForce(PxReal force, PxReal torque) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(force) && PxIsFinite(torque), "PxJoint::setBreakForce: invalid float");
|
||||
mPxConstraint->setBreakForce(force,torque);
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, breakForce, static_cast<PxJoint&>(*this), force)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxJoint, breakTorque, static_cast<PxJoint&>(*this), torque)
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void getBreakForce(PxReal& force, PxReal& torque) const PX_OVERRIDE
|
||||
{
|
||||
mPxConstraint->getBreakForce(force,torque);
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setConstraintFlags(PxConstraintFlags flags) PX_OVERRIDE
|
||||
{
|
||||
mPxConstraint->setFlags(flags);
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, constraintFlags, static_cast<PxJoint&>(*this), flags)
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setConstraintFlag(PxConstraintFlag::Enum flag, bool value) PX_OVERRIDE
|
||||
{
|
||||
mPxConstraint->setFlag(flag, value);
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, constraintFlags, static_cast<PxJoint&>(*this), getConstraintFlags())
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxConstraintFlags getConstraintFlags() const PX_OVERRIDE
|
||||
{
|
||||
return mPxConstraint->getFlags();
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setInvMassScale0(PxReal invMassScale) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale0: scale must be non-negative");
|
||||
mData->invMassScale.linear0 = invMassScale;
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, invMassScale0, static_cast<PxJoint&>(*this), invMassScale)
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxReal getInvMassScale0() const PX_OVERRIDE
|
||||
{
|
||||
return mData->invMassScale.linear0;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setInvInertiaScale0(PxReal invInertiaScale) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale0: scale must be non-negative");
|
||||
mData->invMassScale.angular0 = invInertiaScale;
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, invInertiaScale0, static_cast<PxJoint&>(*this), invInertiaScale)
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxReal getInvInertiaScale0() const PX_OVERRIDE
|
||||
{
|
||||
return mData->invMassScale.angular0;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setInvMassScale1(PxReal invMassScale) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale1: scale must be non-negative");
|
||||
mData->invMassScale.linear1 = invMassScale;
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, invMassScale1, static_cast<PxJoint&>(*this), invMassScale)
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxReal getInvMassScale1() const PX_OVERRIDE
|
||||
{
|
||||
return mData->invMassScale.linear1;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setInvInertiaScale1(PxReal invInertiaScale) PX_OVERRIDE
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale: scale must be non-negative");
|
||||
mData->invMassScale.angular1 = invInertiaScale;
|
||||
mPxConstraint->markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxJoint, invInertiaScale1, static_cast<PxJoint&>(*this), invInertiaScale)
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxReal getInvInertiaScale1() const PX_OVERRIDE
|
||||
{
|
||||
return mData->invMassScale.angular1;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxConstraint* getConstraint() const PX_OVERRIDE
|
||||
{
|
||||
return mPxConstraint;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void setName(const char* name) PX_OVERRIDE
|
||||
{
|
||||
mName = name;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
const char* n = name ? name : "";
|
||||
PxU32 nLen = PxU32(strlen(n)) + 1;
|
||||
OMNI_PVD_SET_ARRAY(OMNI_PVD_CONTEXT_HANDLE, PxJoint, name, static_cast<PxJoint&>(*this), n, nLen)
|
||||
#endif
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual const char* getName() const PX_OVERRIDE
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual void release() PX_OVERRIDE
|
||||
{
|
||||
mPxConstraint->release();
|
||||
}
|
||||
|
||||
// PxJoint
|
||||
virtual PxScene* getScene() const PX_OVERRIDE
|
||||
{
|
||||
return mPxConstraint ? mPxConstraint->getScene() : NULL;
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void onComShift(PxU32 actor) PX_OVERRIDE
|
||||
{
|
||||
mData->c2b[actor] = getCom(actor).transformInv(mLocalPose[actor]);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void onOriginShift(const PxVec3& shift) PX_OVERRIDE
|
||||
{
|
||||
PxRigidActor* a[2];
|
||||
mPxConstraint->getActors(a[0], a[1]);
|
||||
|
||||
if (!a[0])
|
||||
{
|
||||
mLocalPose[0].p -= shift;
|
||||
mData->c2b[0].p -= shift;
|
||||
markDirty();
|
||||
}
|
||||
else if (!a[1])
|
||||
{
|
||||
mLocalPose[1].p -= shift;
|
||||
mData->c2b[1].p -= shift;
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void* prepareData() PX_OVERRIDE
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void* getExternalReference(PxU32& typeID) PX_OVERRIDE
|
||||
{
|
||||
typeID = PxConstraintExtIDs::eJOINT;
|
||||
return static_cast<PxJoint*>( this );
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxBase* getSerializable() PX_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void onConstraintRelease() PX_OVERRIDE
|
||||
{
|
||||
PX_FREE(mData);
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual const void* getConstantBlock() const PX_OVERRIDE
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
virtual void connectToConstraint(PxConstraint* c) PX_OVERRIDE
|
||||
{
|
||||
mPxConstraint = c;
|
||||
}
|
||||
|
||||
private:
|
||||
PxTransform getCom(PxU32 index) const
|
||||
{
|
||||
PxRigidActor* a[2];
|
||||
mPxConstraint->getActors(a[0],a[1]);
|
||||
return getCom(a[index]);
|
||||
}
|
||||
|
||||
PxTransform getCom(PxRigidActor* actor) const
|
||||
{
|
||||
if (!actor)
|
||||
return PxTransform(PxIdentity);
|
||||
else if (actor->getType() == PxActorType::eRIGID_DYNAMIC || actor->getType() == PxActorType::eARTICULATION_LINK)
|
||||
return static_cast<PxRigidBody*>(actor)->getCMassLocalPose();
|
||||
else
|
||||
{
|
||||
PX_ASSERT(actor->getType() == PxActorType::eRIGID_STATIC);
|
||||
return static_cast<PxRigidStatic*>(actor)->getGlobalPose().getInverse();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
JointT(PxType concreteType, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1, const char* name) :
|
||||
Base (concreteType, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE),
|
||||
mName (NULL),
|
||||
mPxConstraint (NULL)
|
||||
{
|
||||
PX_UNUSED(name);
|
||||
Base::userData = NULL;
|
||||
|
||||
const PxU32 size = sizeof(DataClass);
|
||||
JointData* data = reinterpret_cast<JointData*>(PX_ALLOC(size, name));
|
||||
PxMarkSerializedMemory(data, size);
|
||||
|
||||
mLocalPose[0] = localFrame0.getNormalized();
|
||||
mLocalPose[1] = localFrame1.getNormalized();
|
||||
data->c2b[0] = getCom(actor0).transformInv(mLocalPose[0]);
|
||||
data->c2b[1] = getCom(actor1).transformInv(mLocalPose[1]);
|
||||
data->invMassScale.linear0 = 1.0f;
|
||||
data->invMassScale.angular0 = 1.0f;
|
||||
data->invMassScale.linear1 = 1.0f;
|
||||
data->invMassScale.angular1 = 1.0f;
|
||||
|
||||
mData = data;
|
||||
}
|
||||
|
||||
virtual ~JointT()
|
||||
{
|
||||
if(Base::getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
|
||||
PX_FREE(mData);
|
||||
|
||||
OMNI_PVD_DESTROY(OMNI_PVD_CONTEXT_HANDLE, PxJoint, static_cast<Base&>(*this))
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE DataClass& data() const
|
||||
{
|
||||
return *static_cast<DataClass*>(mData);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void markDirty()
|
||||
{
|
||||
mPxConstraint->markDirty();
|
||||
}
|
||||
|
||||
void wakeUpActors()
|
||||
{
|
||||
PxRigidActor* a[2];
|
||||
mPxConstraint->getActors(a[0], a[1]);
|
||||
for(PxU32 i = 0; i < 2; i++)
|
||||
{
|
||||
if(a[i] && a[i]->getScene())
|
||||
{
|
||||
if(a[i]->getType() == PxActorType::eRIGID_DYNAMIC)
|
||||
{
|
||||
PxRigidDynamic* rd = static_cast<PxRigidDynamic*>(a[i]);
|
||||
if(!(rd->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
|
||||
{
|
||||
const PxScene* scene = rd->getScene();
|
||||
const PxReal wakeCounterResetValue = scene->getWakeCounterResetValue();
|
||||
const PxReal wakeCounter = rd->getWakeCounter();
|
||||
if(wakeCounter < wakeCounterResetValue)
|
||||
{
|
||||
rd->wakeUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(a[i]->getType() == PxActorType::eARTICULATION_LINK)
|
||||
{
|
||||
PxArticulationLink* link = reinterpret_cast<PxArticulationLink*>(a[i]);
|
||||
PxArticulationReducedCoordinate& articulation = link->getArticulation();
|
||||
const PxReal wakeCounter = articulation.getWakeCounter();
|
||||
const PxScene* scene = link->getScene();
|
||||
const PxReal wakeCounterResetValue = scene->getWakeCounterResetValue();
|
||||
if(wakeCounter < wakeCounterResetValue)
|
||||
{
|
||||
articulation.wakeUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxQuat getTwistOrSwing(bool needTwist) const
|
||||
{
|
||||
const PxQuat q = getRelativeTransform().q;
|
||||
// PT: TODO: we don't need to compute both quats here
|
||||
PxQuat swing, twist;
|
||||
PxSeparateSwingTwist(q, swing, twist);
|
||||
return needTwist ? twist : swing;
|
||||
}
|
||||
|
||||
PxReal getTwistAngle_Internal() const
|
||||
{
|
||||
const PxQuat twist = getTwistOrSwing(true);
|
||||
|
||||
// PT: the angle-axis formulation creates the quat like this:
|
||||
//
|
||||
// const float a = angleRadians * 0.5f;
|
||||
// const float s = PxSin(a);
|
||||
// w = PxCos(a);
|
||||
// x = unitAxis.x * s;
|
||||
// y = unitAxis.y * s;
|
||||
// z = unitAxis.z * s;
|
||||
//
|
||||
// With the twist axis = (1;0;0) this gives:
|
||||
//
|
||||
// w = PxCos(angleRadians * 0.5f);
|
||||
// x = PxSin(angleRadians * 0.5f);
|
||||
// y = 0.0f;
|
||||
// z = 0.0f;
|
||||
//
|
||||
// Thus the quat's "getAngle" function returns:
|
||||
//
|
||||
// angle = PxAcos(w) * 2.0f;
|
||||
//
|
||||
// PxAcos will return an angle between 0 and PI in radians, so "getAngle" will return an angle between 0 and PI*2.
|
||||
|
||||
PxReal angle = twist.getAngle();
|
||||
|
||||
if(twist.x<0.0f)
|
||||
angle = -angle;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
PxReal getSwingYAngle_Internal() const
|
||||
{
|
||||
PxQuat swing = getTwistOrSwing(false);
|
||||
|
||||
if(swing.w < 0.0f) // choose the shortest rotation
|
||||
swing = -swing;
|
||||
|
||||
const PxReal angle = computeSwingAngle(swing.y, swing.w);
|
||||
PX_ASSERT(angle>-PxPi && angle<=PxPi); // since |y| < w+1, the atan magnitude is < PI/4
|
||||
return angle;
|
||||
}
|
||||
|
||||
PxReal getSwingZAngle_Internal() const
|
||||
{
|
||||
PxQuat swing = getTwistOrSwing(false);
|
||||
|
||||
if(swing.w < 0.0f) // choose the shortest rotation
|
||||
swing = -swing;
|
||||
|
||||
const PxReal angle = computeSwingAngle(swing.z, swing.w);
|
||||
PX_ASSERT(angle>-PxPi && angle <= PxPi); // since |y| < w+1, the atan magnitude is < PI/4
|
||||
return angle;
|
||||
}
|
||||
|
||||
const char* mName;
|
||||
PxTransform mLocalPose[2];
|
||||
PxConstraint* mPxConstraint;
|
||||
JointData* mData;
|
||||
};
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
void omniPvdSetBaseJointParams(const PxJoint& joint, PxJointConcreteType::Enum cType);
|
||||
template<typename JointType> void omniPvdInitJoint(JointType& joint);
|
||||
#endif
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
49
engine/third_party/physx/source/physxextensions/src/ExtJointData.h
vendored
Normal file
49
engine/third_party/physx/source/physxextensions/src/ExtJointData.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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 EXT_JOINT_DATA_H
|
||||
#define EXT_JOINT_DATA_H
|
||||
|
||||
#include "extensions/PxJointLimit.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
struct JointData
|
||||
{
|
||||
PxConstraintInvMassScale invMassScale;
|
||||
PxTransform32 c2b[2];
|
||||
protected:
|
||||
~JointData() {}
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
}
|
||||
|
||||
#endif
|
||||
64
engine/third_party/physx/source/physxextensions/src/ExtJointMetaDataExtensions.h
vendored
Normal file
64
engine/third_party/physx/source/physxextensions/src/ExtJointMetaDataExtensions.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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 EXT_JOINT_META_DATA_EXTENSIONS_H
|
||||
#define EXT_JOINT_META_DATA_EXTENSIONS_H
|
||||
#include "PvdMetaDataExtensions.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
namespace pvdsdk
|
||||
{
|
||||
|
||||
|
||||
struct PxExtensionPvdOnlyProperties
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
FirstProp = PxExtensionsPropertyInfoName::LastPxPropertyInfoName,
|
||||
DEFINE_ENUM_RANGE( PxJoint_Actors, 2 ),
|
||||
DEFINE_ENUM_RANGE( PxJoint_BreakForce, 2 ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_DriveVelocity, 2 ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_Motion, PxD6Axis::eCOUNT ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_Drive, PxD6Drive::eCOUNT * ( PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStop - PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStart ) ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_LinearLimit, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_SwingLimit, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxD6Joint_TwistLimit, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxPrismaticJoint_Limit, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxRevoluteJoint_Limit, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxSphericalJoint_LimitCone, 100 ),
|
||||
DEFINE_ENUM_RANGE( PxJoint_LocalPose, 2 )
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
464
engine/third_party/physx/source/physxextensions/src/ExtParticleClothCooker.cpp
vendored
Normal file
464
engine/third_party/physx/source/physxextensions/src/ExtParticleClothCooker.cpp
vendored
Normal file
@@ -0,0 +1,464 @@
|
||||
// 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/PxParticleClothCooker.h"
|
||||
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxSort.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
#include "foundation/PxHashSet.h"
|
||||
#include "GuInternal.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace ExtGpu
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct Edge
|
||||
{
|
||||
Edge(PxU32 v0, PxU32 v1, PxU32 triangle0, PxU32 triangle1, bool isLongest0, bool isLongest1)
|
||||
{
|
||||
a = PxMin(v0, v1);
|
||||
b = PxMax(v0, v1);
|
||||
triangleA = triangle0;
|
||||
triangleB = triangle1;
|
||||
longestA = isLongest0;
|
||||
longestB = isLongest1;
|
||||
PX_ASSERT_WITH_MESSAGE(a != b, "PxCreateInflatableFromMesh encountered a degenerate edge inside a triangle.");
|
||||
}
|
||||
PxU32 a, b;
|
||||
PxU32 triangleA, triangleB;
|
||||
bool longestA, longestB; //true if it is the longest edge of triangle
|
||||
|
||||
bool operator<(const Edge& other) const
|
||||
{
|
||||
if(a == other.a)
|
||||
return b < other.b;
|
||||
return a < other.a;
|
||||
}
|
||||
bool operator==(const Edge& other) const
|
||||
{
|
||||
if(a == other.a)
|
||||
return b == other.b;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class EdgeHash
|
||||
{
|
||||
public:
|
||||
uint32_t operator()(const Edge& e) const
|
||||
{
|
||||
return PxComputeHash(e.a) ^ PxComputeHash(e.b);
|
||||
}
|
||||
bool equal(const Edge& e0, const Edge& e1) const
|
||||
{
|
||||
return e0.a == e1.a && e0.b == e1.b;
|
||||
}
|
||||
};
|
||||
|
||||
class EdgeSet : public PxHashSet<Edge, EdgeHash>
|
||||
{
|
||||
public:
|
||||
typedef PxHashSet<Edge, EdgeHash> Base;
|
||||
typedef Base::Iterator Iterator;
|
||||
|
||||
void insert(const Edge& newEdge)
|
||||
{
|
||||
PX_ASSERT(newEdge.a < newEdge.b);
|
||||
bool exists;
|
||||
Edge* edge = mBase.create(newEdge, exists);
|
||||
if (!exists)
|
||||
{
|
||||
PX_PLACEMENT_NEW(edge, Edge)(newEdge);
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT_WITH_MESSAGE(edge->triangleB == 0xffffffff, "Edge with more than 2 triangles found in PxCreateInflatableFromMesh");
|
||||
edge->triangleB = newEdge.triangleA; //Add triangle info from duplicate to Unique edge
|
||||
edge->longestB = newEdge.longestA;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void partialSum(T* begin, T* end, T* dest)
|
||||
{
|
||||
*dest = *begin;
|
||||
dest++;
|
||||
begin++;
|
||||
while(begin!=end)
|
||||
{
|
||||
*dest = dest[-1] + *begin;
|
||||
dest++;
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
outAdjacencies is a list of adjacent vertices in outAdjacencies
|
||||
outAdjacencyIndices is a list of indices to quickly find adjacent vertices in outAdjacencies.
|
||||
|
||||
all the adjacent vertices to vertex V are stored in outAdjacencies starting at outAdjacencyIndices[V] and ending at outAdjacencyIndices[V+1]
|
||||
so the first vertex is outAdjacencies[outAdjacencyIndices[V]], and the last one is outAdjacencies[outAdjacencyIndices[V+1]-1]
|
||||
|
||||
*/
|
||||
void gatherAdjacencies(PxArray<PxU32>& outAdjacencyIndices, PxArray<PxU32>& outAdjacencies,
|
||||
PxU32 vertexCount, PxArray<Edge> const& inUniqueEdges, bool ignoreDiagonals = false
|
||||
)
|
||||
{
|
||||
PX_ASSERT(outAdjacencyIndices.size() == 0);
|
||||
PX_ASSERT(outAdjacencies.size() == 0);
|
||||
|
||||
outAdjacencyIndices.resize(vertexCount+1, 0);
|
||||
|
||||
//calculate valency
|
||||
for(PxU32 i = 0; i < inUniqueEdges.size(); i++)
|
||||
{
|
||||
const Edge& edge = inUniqueEdges[i];
|
||||
if(ignoreDiagonals && edge.longestA && edge.longestB)
|
||||
continue;
|
||||
outAdjacencyIndices[edge.a]++;
|
||||
outAdjacencyIndices[edge.b]++;
|
||||
}
|
||||
|
||||
partialSum(outAdjacencyIndices.begin(), outAdjacencyIndices.end(), outAdjacencyIndices.begin());
|
||||
outAdjacencyIndices.back() = outAdjacencyIndices[vertexCount-1];
|
||||
outAdjacencies.resize(outAdjacencyIndices.back(),0xffffffff);
|
||||
|
||||
for(PxU32 i = 0; i < inUniqueEdges.size(); i++)
|
||||
{
|
||||
const Edge& edge = inUniqueEdges[i];
|
||||
if(ignoreDiagonals && edge.longestA && edge.longestB)
|
||||
continue;
|
||||
outAdjacencyIndices[edge.a]--;
|
||||
outAdjacencies[outAdjacencyIndices[edge.a]]=edge.b;
|
||||
outAdjacencyIndices[edge.b]--;
|
||||
outAdjacencies[outAdjacencyIndices[edge.b]] = edge.a;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename A>
|
||||
A MaxArg(T const& vA, T const& vB, A const& aA, A const& aB)
|
||||
{
|
||||
if(vA > vB)
|
||||
return aA;
|
||||
return aB;
|
||||
}
|
||||
|
||||
PxU32 GetOppositeVertex(PxU32* inTriangleIndices, PxU32 triangleIndex, PxU32 a, PxU32 b)
|
||||
{
|
||||
for(int i = 0; i<3; i++)
|
||||
{
|
||||
if(inTriangleIndices[triangleIndex+i] != a && inTriangleIndices[triangleIndex + i] !=b)
|
||||
return inTriangleIndices[triangleIndex + i];
|
||||
}
|
||||
PX_ASSERT_WITH_MESSAGE(0, "Degenerate Triangle found in PxCreateInflatableFromMesh");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Edge GetAlternateDiagonal(Edge const& edge, PxU32* inTriangleIndices)
|
||||
{
|
||||
PxU32 vA = GetOppositeVertex(inTriangleIndices, edge.triangleA, edge.a, edge.b);
|
||||
PxU32 vB = GetOppositeVertex(inTriangleIndices, edge.triangleB, edge.a, edge.b);
|
||||
bool longestA = true;
|
||||
bool longestB = true;
|
||||
PxU32 tA = 0xffffffff;
|
||||
PxU32 tB = 0xffffffff;
|
||||
return Edge(vA, vB, tA, tB, longestA, longestB);
|
||||
}
|
||||
} //namespace
|
||||
|
||||
class PxParticleClothCookerImpl : public PxParticleClothCooker, public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
PxParticleClothCookerImpl(PxU32 vertexCount, physx::PxVec4* inVertices, PxU32 triangleIndexCount, PxU32* inTriangleIndices,
|
||||
PxU32 constraintTypeFlags, PxVec3 verticalDirection, PxReal bendingConstraintMaxAngle)
|
||||
:
|
||||
mVertexCount(vertexCount),
|
||||
mVertices(inVertices),
|
||||
mTriangleIndexCount(triangleIndexCount),
|
||||
mTriangleIndices(inTriangleIndices),
|
||||
mConstraintTypeFlags(constraintTypeFlags),
|
||||
mVerticalDirection(verticalDirection),
|
||||
mBendingConstraintMaxAngle(bendingConstraintMaxAngle)
|
||||
{
|
||||
}
|
||||
virtual void release()
|
||||
{
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief generate the constraint and triangle per vertex information.
|
||||
*/
|
||||
virtual void cookConstraints(const PxParticleClothConstraint* constraints, const PxU32 numConstraints);
|
||||
virtual PxU32* getTriangleIndices() { return mTriangleIndexBuffer.begin(); }
|
||||
virtual PxU32 getTriangleIndicesCount() { return mTriangleIndexBuffer.size(); }
|
||||
virtual PxParticleClothConstraint* getConstraints() { return mConstraintBuffer.begin(); }
|
||||
virtual PxU32 getConstraintCount() { return mConstraintBuffer.size(); }
|
||||
|
||||
/**
|
||||
\brief Computes the volume of a closed mesh and the contraintScale. Expects vertices in local space - 'close' to origin.
|
||||
*/
|
||||
virtual void calculateMeshVolume();
|
||||
virtual float getMeshVolume() {return mMeshVolume;}
|
||||
|
||||
private:
|
||||
PxArray<PxU32> mTriangleIndexBuffer;
|
||||
PxArray<PxParticleClothConstraint> mConstraintBuffer;
|
||||
|
||||
PxU32 mVertexCount;
|
||||
physx::PxVec4* mVertices; //we don't own this
|
||||
PxU32 mTriangleIndexCount;
|
||||
PxU32* mTriangleIndices; //we don't own this
|
||||
PxU32 mConstraintTypeFlags;
|
||||
PxVec3 mVerticalDirection;
|
||||
float mBendingConstraintMaxAngle;
|
||||
|
||||
float mMeshVolume;
|
||||
|
||||
void addTriangle(PxArray<PxU32>& trianglesPerVertex, PxU32 triangleIndex)
|
||||
{
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
PxU32 vertexIndex = mTriangleIndices[triangleIndex + j];
|
||||
mTriangleIndexBuffer.pushBack(vertexIndex);
|
||||
trianglesPerVertex[vertexIndex]++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void PxParticleClothCookerImpl::cookConstraints(const PxParticleClothConstraint* constraints, const PxU32 numConstraints)
|
||||
{
|
||||
EdgeSet edgeSet;
|
||||
edgeSet.reserve(mTriangleIndexCount);
|
||||
|
||||
PxArray<PxU32> trianglesPerVertex;
|
||||
trianglesPerVertex.resize(mVertexCount, 0);
|
||||
|
||||
mTriangleIndexBuffer.clear();
|
||||
mTriangleIndexBuffer.reserve(mTriangleIndexCount);
|
||||
|
||||
mConstraintBuffer.clear();
|
||||
mConstraintBuffer.reserve(mVertexCount*12);
|
||||
|
||||
//Add all edges to Edges
|
||||
for(PxU32 i = 0; i<mTriangleIndexCount; i+=3)
|
||||
{
|
||||
//Get vertex indices
|
||||
PxU32 v0 = mTriangleIndices[i + 0];
|
||||
PxU32 v1 = mTriangleIndices[i + 1];
|
||||
PxU32 v2 = mTriangleIndices[i + 2];
|
||||
|
||||
//Get vertex points
|
||||
PxVec3 p0 = mVertices[v0].getXYZ();
|
||||
PxVec3 p1 = mVertices[v1].getXYZ();
|
||||
PxVec3 p2 = mVertices[v2].getXYZ();
|
||||
|
||||
//check which edge is the longest
|
||||
float len0 = (p0 - p1).magnitude();
|
||||
float len1 = (p1 - p2).magnitude();
|
||||
float len2 = (p2 - p0).magnitude();
|
||||
int longest = MaxArg(len0, PxMax(len1,len2), 0, MaxArg(len1, len2, 1, 2));
|
||||
|
||||
//Store edges
|
||||
edgeSet.insert(Edge(v0, v1, i, 0xffffffff, longest == 0, false));
|
||||
edgeSet.insert(Edge(v1, v2, i, 0xffffffff, longest == 1, false));
|
||||
edgeSet.insert(Edge(v2, v0, i, 0xffffffff, longest == 2, false));
|
||||
|
||||
//Add triangle to mTriangleIndexBuffer and increment trianglesPerVertex values
|
||||
addTriangle(trianglesPerVertex,i);
|
||||
}
|
||||
|
||||
if (constraints)
|
||||
{
|
||||
//skip constraints cooking if provided by user
|
||||
mConstraintBuffer.assign(constraints, constraints + numConstraints);
|
||||
return;
|
||||
}
|
||||
|
||||
trianglesPerVertex.clear();
|
||||
trianglesPerVertex.shrink();
|
||||
|
||||
PxArray<Edge> uniqueEdges;
|
||||
uniqueEdges.reserve(mTriangleIndexCount); //over allocate to avoid resizes
|
||||
for (EdgeSet::Iterator iter = edgeSet.getIterator(); !iter.done(); ++iter)
|
||||
{
|
||||
const Edge& e = *iter;
|
||||
uniqueEdges.pushBack(e);
|
||||
}
|
||||
|
||||
//Maximum angle before it is a horizontal constraint
|
||||
const float cosAngle45 = cosf(45.0f / 360.0f * PxTwoPi);
|
||||
|
||||
//Add all horizontal, vertical and shearing constraints
|
||||
PxU32 constraintCount = uniqueEdges.size(); //we are going to push back more edges, but we don't need to process them
|
||||
for(PxU32 i = 0; i < constraintCount; i++)
|
||||
{
|
||||
const Edge& edge = uniqueEdges[i];
|
||||
PxParticleClothConstraint c;
|
||||
c.particleIndexA = edge.a;
|
||||
c.particleIndexB = edge.b;
|
||||
|
||||
//Get vertices's
|
||||
PxVec3 vA = mVertices[c.particleIndexA].getXYZ();
|
||||
PxVec3 vB = mVertices[c.particleIndexB].getXYZ();
|
||||
|
||||
//Calculate rest length
|
||||
c.length = (vA - vB).magnitude();
|
||||
|
||||
if(edge.longestA && edge.longestB && (mConstraintTypeFlags & PxParticleClothConstraint::eTYPE_DIAGONAL_CONSTRAINT))
|
||||
{
|
||||
//Shearing constraint
|
||||
c.constraintType = c.eTYPE_DIAGONAL_CONSTRAINT;
|
||||
//add constraint
|
||||
mConstraintBuffer.pushBack(c);
|
||||
|
||||
//We only have one of the quad diagonals in a triangle mesh, get the other one here
|
||||
const Edge alternateEdge = GetAlternateDiagonal(edge, mTriangleIndices);
|
||||
c.particleIndexA = alternateEdge.a;
|
||||
c.particleIndexB = alternateEdge.b;
|
||||
|
||||
//Get vertices's
|
||||
PxVec3 vA2 = mVertices[c.particleIndexA].getXYZ();
|
||||
PxVec3 vB2 = mVertices[c.particleIndexB].getXYZ();
|
||||
|
||||
//Calculate rest length
|
||||
c.length = (vA2 - vB2).magnitude();
|
||||
|
||||
//add constraint
|
||||
mConstraintBuffer.pushBack(c);
|
||||
|
||||
if (mConstraintTypeFlags & PxParticleClothConstraint::eTYPE_DIAGONAL_BENDING_CONSTRAINT)
|
||||
{
|
||||
if (!edgeSet.contains(alternateEdge))
|
||||
{
|
||||
edgeSet.insert(alternateEdge);
|
||||
uniqueEdges.pushBack(alternateEdge); //Add edge for bending constraint step
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//horizontal/vertical constraint
|
||||
PxVec3 dir = (vA - vB) / c.length;
|
||||
if(mVerticalDirection.dot(dir)> cosAngle45)
|
||||
c.constraintType = c.eTYPE_VERTICAL_CONSTRAINT;
|
||||
else
|
||||
c.constraintType = c.eTYPE_HORIZONTAL_CONSTRAINT;
|
||||
|
||||
if(mConstraintTypeFlags & c.constraintType)
|
||||
{
|
||||
//add constraint
|
||||
mConstraintBuffer.pushBack(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(mConstraintTypeFlags & PxParticleClothConstraint::eTYPE_BENDING_CONSTRAINT))
|
||||
return;
|
||||
|
||||
//Get adjacency information needed for the bending constraints
|
||||
PxArray<PxU32> adjacencyIndices;
|
||||
PxArray<PxU32> adjacencies;
|
||||
gatherAdjacencies(adjacencyIndices, adjacencies, mVertexCount, uniqueEdges, !(mConstraintTypeFlags & PxParticleClothConstraint::eTYPE_DIAGONAL_BENDING_CONSTRAINT));
|
||||
|
||||
//Maximum angle we consider to be parallel for the bending constraints
|
||||
const float maxCosAngle = PxCos(mBendingConstraintMaxAngle);
|
||||
|
||||
for(PxU32 i = 0; i<mVertexCount; i++)
|
||||
{
|
||||
//For each vertex, find all adjacent vertex pairs, and add bending constraints for pairs that form roughly a straight line
|
||||
PxVec3 center = mVertices[i].getXYZ();
|
||||
|
||||
for(PxU32 adjA = adjacencyIndices[i]; PxI32(adjA) < PxI32(adjacencyIndices[i+1])-1; adjA++)
|
||||
{
|
||||
PxVec3 a = mVertices[adjacencies[adjA]].getXYZ();
|
||||
PxVec3 dir1 = (a-center).getNormalized();
|
||||
|
||||
float bestCosAngle = -1.0f;
|
||||
PxU32 bestAdjB = 0xffffffff;
|
||||
|
||||
//Choose the most parallel adjB
|
||||
for(PxU32 adjB = adjA+1; adjB < adjacencyIndices[i + 1]; adjB++)
|
||||
{
|
||||
PxVec3 b = mVertices[adjacencies[adjB]].getXYZ();
|
||||
PxVec3 dir2 = (b - center).getNormalized();
|
||||
float cosAngleAbs = PxAbs(dir1.dot(dir2));
|
||||
if(cosAngleAbs > bestCosAngle)
|
||||
{
|
||||
bestCosAngle = cosAngleAbs;
|
||||
bestAdjB = adjB;
|
||||
}
|
||||
}
|
||||
|
||||
//Check if the lines a-center and center-b are roughly parallel
|
||||
if(bestCosAngle > maxCosAngle)
|
||||
{
|
||||
//Add bending constraint
|
||||
PxParticleClothConstraint c;
|
||||
c.particleIndexA = adjacencies[adjA];
|
||||
c.particleIndexB = adjacencies[bestAdjB];
|
||||
|
||||
PX_ASSERT(c.particleIndexA != c.particleIndexB);
|
||||
|
||||
//Get vertices's
|
||||
PxVec3 vA = mVertices[c.particleIndexA].getXYZ();
|
||||
PxVec3 vB = mVertices[c.particleIndexB].getXYZ();
|
||||
|
||||
//Calculate rest length
|
||||
c.length = (vA - vB).magnitude();
|
||||
|
||||
c.constraintType = c.eTYPE_BENDING_CONSTRAINT;
|
||||
//add constraint
|
||||
mConstraintBuffer.pushBack(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxParticleClothCookerImpl::calculateMeshVolume()
|
||||
{
|
||||
// the physx api takes volume*6 now.
|
||||
mMeshVolume = Gu::computeTriangleMeshVolume(mVertices, mTriangleIndices, mTriangleIndexCount / 3) * 6.0f;
|
||||
}
|
||||
|
||||
} // namespace ExtGpu
|
||||
|
||||
ExtGpu::PxParticleClothCooker* PxCreateParticleClothCooker(PxU32 vertexCount, PxVec4* inVertices, PxU32 triangleIndexCount, PxU32* inTriangleIndices,
|
||||
PxU32 constraintTypeFlags, PxVec3 verticalDirection, PxReal bendingConstraintMaxAngle)
|
||||
{
|
||||
return PX_NEW(ExtGpu::PxParticleClothCookerImpl)(vertexCount, inVertices, triangleIndexCount, inTriangleIndices,
|
||||
constraintTypeFlags, verticalDirection, bendingConstraintMaxAngle);
|
||||
}
|
||||
|
||||
} // namespace physx
|
||||
826
engine/third_party/physx/source/physxextensions/src/ExtParticleExt.cpp
vendored
Normal file
826
engine/third_party/physx/source/physxextensions/src/ExtParticleExt.cpp
vendored
Normal file
@@ -0,0 +1,826 @@
|
||||
// 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 "PxParticleBuffer.h"
|
||||
#include "extensions/PxCudaHelpersExt.h"
|
||||
#include "extensions/PxParticleExt.h"
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "PxScene.h"
|
||||
#include "PxPhysics.h"
|
||||
#include "PxRigidBody.h"
|
||||
#include "cudamanager/PxCudaContextManager.h"
|
||||
#include "cudamanager/PxCudaContext.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace ExtGpu
|
||||
{
|
||||
|
||||
void PxDmaDataToDevice(PxCudaContextManager* cudaContextManager, PxParticleBuffer* particleBuffer, const PxParticleBufferDesc& desc)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
cudaContextManager->acquireContext();
|
||||
|
||||
PxVec4* posInvMass = particleBuffer->getPositionInvMasses();
|
||||
PxVec4* velocities = particleBuffer->getVelocities();
|
||||
PxU32* phases = particleBuffer->getPhases();
|
||||
PxParticleVolume* volumes = particleBuffer->getParticleVolumes();
|
||||
|
||||
PxCudaContext* cudaContext = cudaContextManager->getCudaContext();
|
||||
|
||||
//KS - TODO - use an event to wait for this
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(posInvMass), desc.positions, desc.numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(velocities), desc.velocities, desc.numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(phases), desc.phases, desc.numActiveParticles * sizeof(PxU32), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(volumes), desc.volumes, desc.numVolumes * sizeof(PxParticleVolume), 0);
|
||||
|
||||
particleBuffer->setNbActiveParticles(desc.numActiveParticles);
|
||||
particleBuffer->setNbParticleVolumes(desc.numVolumes);
|
||||
|
||||
cudaContext->streamSynchronize(0);
|
||||
|
||||
cudaContextManager->releaseContext();
|
||||
#else
|
||||
PX_UNUSED(cudaContextManager);
|
||||
PX_UNUSED(particleBuffer);
|
||||
PX_UNUSED(desc);
|
||||
#endif
|
||||
}
|
||||
|
||||
PxParticleBuffer* PxCreateAndPopulateParticleBuffer(const PxParticleBufferDesc& desc, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
PxParticleBuffer* particleBuffer = PxGetPhysics().createParticleBuffer(desc.maxParticles, desc.maxVolumes, cudaContextManager);
|
||||
PxDmaDataToDevice(cudaContextManager, particleBuffer, desc);
|
||||
return particleBuffer;
|
||||
}
|
||||
|
||||
PxParticleAndDiffuseBuffer* PxCreateAndPopulateParticleAndDiffuseBuffer(const PxParticleAndDiffuseBufferDesc& desc, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
PxParticleAndDiffuseBuffer* particleBuffer = PxGetPhysics().createParticleAndDiffuseBuffer(desc.maxParticles, desc.maxVolumes, desc.maxDiffuseParticles, cudaContextManager);
|
||||
PxDmaDataToDevice(cudaContextManager, particleBuffer, desc);
|
||||
particleBuffer->setMaxActiveDiffuseParticles(desc.maxActiveDiffuseParticles);
|
||||
return particleBuffer;
|
||||
}
|
||||
|
||||
|
||||
PxParticleClothBuffer* PxCreateAndPopulateParticleClothBuffer(const PxParticleBufferDesc& desc, const PxParticleClothDesc& clothDesc, PxPartitionedParticleCloth& output, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
cudaContextManager->acquireContext();
|
||||
|
||||
PxParticleClothBuffer* clothBuffer = PxGetPhysics().createParticleClothBuffer(desc.maxParticles, desc.maxVolumes, clothDesc.nbCloths, clothDesc.nbTriangles, clothDesc.nbSprings, cudaContextManager);
|
||||
|
||||
PxVec4* posInvMass = clothBuffer->getPositionInvMasses();
|
||||
PxVec4* velocities = clothBuffer->getVelocities();
|
||||
PxU32* phases = clothBuffer->getPhases();
|
||||
PxParticleVolume* volumes = clothBuffer->getParticleVolumes();
|
||||
PxU32* triangles = clothBuffer->getTriangles();
|
||||
PxVec4* restPositions = clothBuffer->getRestPositions();
|
||||
|
||||
PxCudaContext* cudaContext = cudaContextManager->getCudaContext();
|
||||
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(posInvMass), desc.positions, desc.numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(velocities), desc.velocities, desc.numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(phases), desc.phases, desc.numActiveParticles * sizeof(PxU32), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(volumes), desc.volumes, desc.numVolumes * sizeof(PxParticleVolume), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(triangles), clothDesc.triangles, clothDesc.nbTriangles * sizeof(PxU32) * 3, 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(restPositions), clothDesc.restPositions, desc.numActiveParticles * sizeof(PxVec4), 0);
|
||||
|
||||
clothBuffer->setNbActiveParticles(desc.numActiveParticles);
|
||||
clothBuffer->setNbParticleVolumes(desc.numVolumes);
|
||||
clothBuffer->setNbTriangles(clothDesc.nbTriangles);
|
||||
|
||||
clothBuffer->setCloths(output);
|
||||
|
||||
cudaContext->streamSynchronize(0);
|
||||
|
||||
cudaContextManager->releaseContext();
|
||||
|
||||
return clothBuffer;
|
||||
#else
|
||||
PX_UNUSED(desc);
|
||||
PX_UNUSED(clothDesc);
|
||||
PX_UNUSED(output);
|
||||
PX_UNUSED(cudaContextManager);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
PxParticleRigidBuffer* PxCreateAndPopulateParticleRigidBuffer(const PxParticleBufferDesc& desc, const PxParticleRigidDesc& rigidDesc, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
cudaContextManager->acquireContext();
|
||||
|
||||
PxParticleRigidBuffer* rigidBuffer = PxGetPhysics().createParticleRigidBuffer(desc.maxParticles, desc.maxVolumes, rigidDesc.maxRigids, cudaContextManager);
|
||||
|
||||
PxVec4* posInvMassd = rigidBuffer->getPositionInvMasses();
|
||||
PxVec4* velocitiesd = rigidBuffer->getVelocities();
|
||||
PxU32* phasesd = rigidBuffer->getPhases();
|
||||
PxParticleVolume* volumesd = rigidBuffer->getParticleVolumes();
|
||||
PxU32* rigidOffsetsd = rigidBuffer->getRigidOffsets();
|
||||
PxReal* rigidCoefficientsd = rigidBuffer->getRigidCoefficients();
|
||||
PxVec4* rigidTranslationsd = rigidBuffer->getRigidTranslations();
|
||||
PxVec4* rigidRotationsd = rigidBuffer->getRigidRotations();
|
||||
PxVec4* rigidLocalPositionsd = rigidBuffer->getRigidLocalPositions();
|
||||
PxVec4* rigidLocalNormalsd = rigidBuffer->getRigidLocalNormals();
|
||||
|
||||
PxCudaContext* cudaContext = cudaContextManager->getCudaContext();
|
||||
|
||||
const PxU32 numRigids = rigidDesc.numActiveRigids;
|
||||
const PxU32 numActiveParticles = desc.numActiveParticles;
|
||||
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(posInvMassd), desc.positions, numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(velocitiesd), desc.velocities, numActiveParticles * sizeof(PxVec4), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(phasesd), desc.phases, numActiveParticles * sizeof(PxU32), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(volumesd), desc.volumes, desc.numVolumes * sizeof(PxParticleVolume), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidOffsetsd), rigidDesc.rigidOffsets, sizeof(PxU32) * (numRigids + 1), 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidCoefficientsd), rigidDesc.rigidCoefficients, sizeof(PxReal) * numRigids, 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidTranslationsd), rigidDesc.rigidTranslations, sizeof(PxVec4) * numRigids, 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidRotationsd), rigidDesc.rigidRotations, sizeof(PxQuat) * numRigids, 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidLocalPositionsd), rigidDesc.rigidLocalPositions, sizeof(PxVec4) * desc.numActiveParticles, 0);
|
||||
cudaContext->memcpyHtoDAsync(CUdeviceptr(rigidLocalNormalsd), rigidDesc.rigidLocalNormals, sizeof(PxVec4) * desc.numActiveParticles, 0);
|
||||
|
||||
rigidBuffer->setNbActiveParticles(numActiveParticles);
|
||||
rigidBuffer->setNbRigids(numRigids);
|
||||
rigidBuffer->setNbParticleVolumes(desc.numVolumes);
|
||||
|
||||
cudaContext->streamSynchronize(0);
|
||||
|
||||
cudaContextManager->releaseContext();
|
||||
|
||||
return rigidBuffer;
|
||||
#else
|
||||
PX_UNUSED(desc);
|
||||
PX_UNUSED(rigidDesc);
|
||||
PX_UNUSED(cudaContextManager);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxParticleAttachmentBuffer::PxParticleAttachmentBuffer(PxParticleBuffer& particleBuffer, PxPBDParticleSystem& particleSystem) : mParticleBuffer(particleBuffer),
|
||||
mDeviceAttachments(NULL), mDeviceFilters(NULL), mNumDeviceAttachments(0), mNumDeviceFilters(0), mCudaContextManager(particleSystem.getCudaContextManager()),
|
||||
mParticleSystem(particleSystem), mDirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
PxParticleAttachmentBuffer::~PxParticleAttachmentBuffer()
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
mCudaContextManager->acquireContext();
|
||||
|
||||
PxCudaContext* cudaContext = mCudaContextManager->getCudaContext();
|
||||
|
||||
if (mDeviceAttachments)
|
||||
cudaContext->memFree((CUdeviceptr)mDeviceAttachments);
|
||||
if (mDeviceFilters)
|
||||
cudaContext->memFree((CUdeviceptr)mDeviceFilters);
|
||||
|
||||
mDeviceAttachments = NULL;
|
||||
mDeviceFilters = NULL;
|
||||
|
||||
mCudaContextManager->releaseContext();
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxParticleAttachmentBuffer::copyToDevice(CUstream stream)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
mCudaContextManager->acquireContext();
|
||||
|
||||
PxCudaContext* cudaContext = mCudaContextManager->getCudaContext();
|
||||
|
||||
if (mAttachments.size() > mNumDeviceAttachments)
|
||||
{
|
||||
if (mDeviceAttachments)
|
||||
cudaContext->memFree((CUdeviceptr)mDeviceAttachments);
|
||||
|
||||
cudaContext->memAlloc((CUdeviceptr*)&mDeviceAttachments, sizeof(PxParticleRigidAttachment)*mAttachments.size());
|
||||
mNumDeviceAttachments = mAttachments.size();
|
||||
}
|
||||
if (mFilters.size() > mNumDeviceFilters)
|
||||
{
|
||||
if (mDeviceFilters)
|
||||
cudaContext->memFree((CUdeviceptr)mDeviceFilters);
|
||||
|
||||
cudaContext->memAlloc((CUdeviceptr*)&mDeviceFilters, sizeof(PxParticleRigidFilterPair)*mFilters.size());
|
||||
mNumDeviceFilters = mFilters.size();
|
||||
}
|
||||
|
||||
if (mAttachments.size())
|
||||
cudaContext->memcpyHtoDAsync((CUdeviceptr)mDeviceAttachments, mAttachments.begin(), sizeof(PxParticleRigidAttachment)*mAttachments.size(), stream);
|
||||
|
||||
if (mFilters.size())
|
||||
cudaContext->memcpyHtoDAsync((CUdeviceptr)mDeviceFilters, mFilters.begin(), sizeof(PxParticleRigidFilterPair)*mFilters.size(), stream);
|
||||
|
||||
mParticleBuffer.setRigidAttachments(mDeviceAttachments, mAttachments.size());
|
||||
mParticleBuffer.setRigidFilters(mDeviceFilters, mFilters.size());
|
||||
|
||||
mDirty = true;
|
||||
|
||||
for (PxU32 i = 0; i < mNewReferencedBodies.size(); ++i)
|
||||
{
|
||||
if (mReferencedBodies[mNewReferencedBodies[i]] > 0)
|
||||
mParticleSystem.addRigidAttachment(mNewReferencedBodies[i]);
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < mDestroyedRefrencedBodies.size(); ++i)
|
||||
{
|
||||
if (mReferencedBodies[mDestroyedRefrencedBodies[i]] == 0)
|
||||
mParticleSystem.removeRigidAttachment(mDestroyedRefrencedBodies[i]);
|
||||
}
|
||||
|
||||
mNewReferencedBodies.resize(0);
|
||||
mDestroyedRefrencedBodies.resize(0);
|
||||
|
||||
mCudaContextManager->releaseContext();
|
||||
#else
|
||||
PX_UNUSED(stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxParticleAttachmentBuffer::addRigidAttachment(PxRigidActor* rigidActor, const PxU32 particleID, const PxVec3& localPose, PxConeLimitedConstraint* coneLimit)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(coneLimit == NULL || coneLimit->isValid(), "PxParticleAttachmentBuffer::addRigidAttachment: PxConeLimitedConstraint needs to be valid if specified.");
|
||||
|
||||
PX_ASSERT(particleID < mParticleBuffer.getNbActiveParticles());
|
||||
PxParticleRigidAttachment attachment(PxConeLimitedConstraint(), PxVec4(0.0f));
|
||||
|
||||
if (rigidActor == NULL)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleAttachmentBuffer::addRigidAttachment: rigidActor cannot be NULL.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (coneLimit)
|
||||
{
|
||||
attachment.mConeLimitParams.axisAngle = PxVec4(coneLimit->mAxis, coneLimit->mAngle);
|
||||
attachment.mConeLimitParams.lowHighLimits = PxVec4(coneLimit->mLowLimit, coneLimit->mHighLimit, 0.f, 0.f);
|
||||
}
|
||||
|
||||
if (rigidActor->getType() == PxActorType::eRIGID_STATIC)
|
||||
{
|
||||
// attachments to rigid static work in global space
|
||||
attachment.mLocalPose0 = PxVec4(static_cast<PxRigidBody*>(rigidActor)->getGlobalPose().transform(localPose), 0.0f);
|
||||
attachment.mID0 = PxNodeIndex().getInd();
|
||||
}
|
||||
else
|
||||
{
|
||||
// others use body space.
|
||||
PxRigidBody* rigid = static_cast<PxRigidBody*>(rigidActor);
|
||||
PxTransform body2Actor = rigid->getCMassLocalPose();
|
||||
attachment.mLocalPose0 = PxVec4(body2Actor.transformInv(localPose), 0.f);
|
||||
attachment.mID0 = rigid->getInternalIslandNodeIndex().getInd();
|
||||
}
|
||||
attachment.mID1 = particleID;
|
||||
|
||||
//Insert in order...
|
||||
|
||||
PxU32 l = 0, r = PxU32(mAttachments.size());
|
||||
|
||||
while (l < r) //If difference is just 1, we've found an item...
|
||||
{
|
||||
PxU32 index = (l + r) / 2;
|
||||
|
||||
if (attachment < mAttachments[index])
|
||||
r = index;
|
||||
else if (attachment > mAttachments[index])
|
||||
l = index + 1;
|
||||
else
|
||||
l = r = index; //This is a match so insert before l
|
||||
}
|
||||
|
||||
mAttachments.insert();
|
||||
|
||||
for (PxU32 i = mAttachments.size()-1; i > l; --i)
|
||||
{
|
||||
mAttachments[i] = mAttachments[i - 1];
|
||||
}
|
||||
mAttachments[l] = attachment;
|
||||
|
||||
mDirty = true;
|
||||
|
||||
if (rigidActor)
|
||||
{
|
||||
PxU32& refCount = mReferencedBodies[rigidActor];
|
||||
|
||||
if (refCount == 0)
|
||||
mNewReferencedBodies.pushBack(rigidActor);
|
||||
refCount++;
|
||||
}
|
||||
}
|
||||
|
||||
bool PxParticleAttachmentBuffer::removeRigidAttachment(PxRigidActor* rigidActor, const PxU32 particleID)
|
||||
{
|
||||
PX_ASSERT(particleID < mParticleBuffer.getNbActiveParticles());
|
||||
|
||||
if (rigidActor == NULL)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleAttachmentBuffer::removeRigidAttachment: rigidActor cannot be NULL.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rigidActor)
|
||||
{
|
||||
PxU32& refCount = mReferencedBodies[rigidActor];
|
||||
refCount--;
|
||||
|
||||
if (refCount == 0)
|
||||
mDestroyedRefrencedBodies.pushBack(rigidActor);
|
||||
}
|
||||
|
||||
PxParticleRigidFilterPair attachment;
|
||||
attachment.mID0 = rigidActor->getType() != PxActorType::eRIGID_STATIC ? static_cast<PxRigidBody*>(rigidActor)->getInternalIslandNodeIndex().getInd() :
|
||||
PxNodeIndex().getInd();
|
||||
attachment.mID1 = particleID;
|
||||
PxU32 l = 0, r = PxU32(mAttachments.size());
|
||||
|
||||
while (l < r) //If difference is just 1, we've found an item...
|
||||
{
|
||||
PxU32 index = (l + r) / 2;
|
||||
|
||||
if (attachment < mAttachments[index])
|
||||
r = index;
|
||||
else if (attachment > mAttachments[index])
|
||||
l = index + 1;
|
||||
else
|
||||
l = r = index; //This is a match so insert before l
|
||||
}
|
||||
|
||||
if (mAttachments[l] == attachment)
|
||||
{
|
||||
mDirty = true;
|
||||
//Remove
|
||||
mAttachments.remove(l);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PxParticleAttachmentBuffer::addRigidFilter(PxRigidActor* rigidActor, const PxU32 particleID)
|
||||
{
|
||||
PX_ASSERT(particleID < mParticleBuffer.getNbActiveParticles());
|
||||
PxParticleRigidFilterPair attachment;
|
||||
attachment.mID0 = rigidActor->getType() != PxActorType::eRIGID_STATIC ? static_cast<PxRigidBody*>(rigidActor)->getInternalIslandNodeIndex().getInd() :
|
||||
PxNodeIndex().getInd();
|
||||
attachment.mID1 = particleID;
|
||||
|
||||
//Insert in order...
|
||||
|
||||
PxU32 l = 0, r = PxU32(mFilters.size());
|
||||
|
||||
while (l < r) //If difference is just 1, we've found an item...
|
||||
{
|
||||
PxU32 index = (l + r) / 2;
|
||||
|
||||
if (attachment < mFilters[index])
|
||||
r = index;
|
||||
else if (attachment > mFilters[index])
|
||||
l = index + 1;
|
||||
else
|
||||
l = r = index; //This is a match so insert before l
|
||||
}
|
||||
|
||||
mFilters.insert();
|
||||
|
||||
for (PxU32 i = mFilters.size() - 1; i > l; --i)
|
||||
{
|
||||
mFilters[i] = mFilters[i - 1];
|
||||
}
|
||||
mFilters[l] = attachment;
|
||||
|
||||
mDirty = true;
|
||||
}
|
||||
|
||||
bool PxParticleAttachmentBuffer::removeRigidFilter(PxRigidActor* rigidActor, const PxU32 particleID)
|
||||
{
|
||||
PX_ASSERT(particleID < mParticleBuffer.getNbActiveParticles());
|
||||
PxParticleRigidFilterPair attachment;
|
||||
attachment.mID0 = rigidActor->getType() != PxActorType::eRIGID_STATIC ? static_cast<PxRigidBody*>(rigidActor)->getInternalIslandNodeIndex().getInd() :
|
||||
PxNodeIndex().getInd();
|
||||
attachment.mID1 = particleID;
|
||||
PxU32 l = 0, r = PxU32(mFilters.size());
|
||||
|
||||
while (l < r) //If difference is just 1, we've found an item...
|
||||
{
|
||||
PxU32 index = (l + r) / 2;
|
||||
|
||||
if (attachment < mFilters[index])
|
||||
r = index;
|
||||
else if (attachment > mFilters[index])
|
||||
l = index + 1;
|
||||
else
|
||||
l = r = index; //This is a match so insert before l
|
||||
}
|
||||
|
||||
if (mFilters[l] == attachment)
|
||||
{
|
||||
mDirty = true;
|
||||
//Remove
|
||||
mFilters.remove(l);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PxParticleAttachmentBuffer* PxCreateParticleAttachmentBuffer(PxParticleBuffer& buffer, PxParticleSystem& particleSystem)
|
||||
{
|
||||
return PX_NEW(PxParticleAttachmentBuffer)(buffer, particleSystem);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ParticleClothBuffersImpl : public PxParticleClothBufferHelper, public PxUserAllocated
|
||||
{
|
||||
ParticleClothBuffersImpl(const PxU32 maxCloths, const PxU32 maxTriangles, const PxU32 maxSprings, const PxU32 maxParticles, PxCudaContextManager* cudaContextManager)
|
||||
: mCudaContextManager(cudaContextManager)
|
||||
{
|
||||
mMaxParticles = maxParticles;
|
||||
mClothDesc.nbParticles = 0;
|
||||
|
||||
mMaxTriangles = maxTriangles;
|
||||
mClothDesc.nbTriangles = 0;
|
||||
|
||||
mMaxSprings = maxSprings;
|
||||
mClothDesc.nbSprings = 0;
|
||||
|
||||
mMaxCloths = maxCloths;
|
||||
mClothDesc.nbCloths = 0;
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
mClothDesc.restPositions = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *mCudaContextManager, maxParticles);
|
||||
mClothDesc.triangles = PX_EXT_PINNED_MEMORY_ALLOC(PxU32, *mCudaContextManager, maxTriangles * 3);
|
||||
mClothDesc.springs = PX_EXT_PINNED_MEMORY_ALLOC(PxParticleSpring, *mCudaContextManager, maxSprings);
|
||||
mClothDesc.cloths = PX_EXT_PINNED_MEMORY_ALLOC(PxParticleCloth, *mCudaContextManager, maxCloths);
|
||||
#endif
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mClothDesc.cloths);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mClothDesc.restPositions);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mClothDesc.triangles);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mClothDesc.springs);
|
||||
#endif
|
||||
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
PxU32 getMaxCloths() const { return mMaxCloths; }
|
||||
PxU32 getNumCloths() const { return mClothDesc.nbCloths; }
|
||||
PxU32 getMaxSprings() const { return mMaxSprings; }
|
||||
PxU32 getNumSprings() const { return mClothDesc.nbSprings; }
|
||||
PxU32 getMaxTriangles() const { return mMaxTriangles; }
|
||||
PxU32 getNumTriangles() const { return mClothDesc.nbTriangles; }
|
||||
PxU32 getMaxParticles() const { return mMaxParticles; }
|
||||
PxU32 getNumParticles() const { return mClothDesc.nbParticles; }
|
||||
|
||||
void addCloth(const PxParticleCloth& particleCloth, const PxU32* triangles, const PxU32 numTriangles,
|
||||
const PxParticleSpring* springs, const PxU32 numSprings, const PxVec4* restPositions, const PxU32 numParticles)
|
||||
{
|
||||
if (mClothDesc.nbCloths + 1 > mMaxCloths)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleClothBufferHelper::addCloth: exceeding maximal number of cloths that can be added.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mClothDesc.nbSprings + numSprings > mMaxSprings)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleClothBufferHelper::addCloth: exceeding maximal number of springs that can be added.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mClothDesc.nbTriangles + numTriangles > mMaxTriangles)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleClothBufferHelper::addCloth: exceeding maximal number of triangles that can be added.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mClothDesc.nbParticles + numParticles > mMaxParticles)
|
||||
{
|
||||
PxGetFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxParticleClothBufferHelper::addCloth: exceeding maximal number of particles that can be added.");
|
||||
return;
|
||||
}
|
||||
|
||||
mClothDesc.cloths[mClothDesc.nbCloths] = particleCloth;
|
||||
mClothDesc.nbCloths += 1;
|
||||
|
||||
for (PxU32 i = 0; i < numSprings; ++i)
|
||||
{
|
||||
PxParticleSpring& dst = mClothDesc.springs[mClothDesc.nbSprings + i];
|
||||
dst = springs[i];
|
||||
dst.ind0 += mClothDesc.nbParticles;
|
||||
dst.ind1 += mClothDesc.nbParticles;
|
||||
}
|
||||
mClothDesc.nbSprings += numSprings;
|
||||
|
||||
for (PxU32 i = 0; i < numTriangles*3; ++i)
|
||||
{
|
||||
PxU32& dst = mClothDesc.triangles[mClothDesc.nbTriangles*3 + i];
|
||||
dst = triangles[i] + mClothDesc.nbParticles;
|
||||
}
|
||||
mClothDesc.nbTriangles += numTriangles;
|
||||
|
||||
PxMemCopy(mClothDesc.restPositions + mClothDesc.nbParticles, restPositions, sizeof(PxVec4)*numParticles);
|
||||
mClothDesc.nbParticles += numParticles;
|
||||
}
|
||||
|
||||
void addCloth(const PxReal blendScale, const PxReal restVolume, const PxReal pressure, const PxU32* triangles, const PxU32 numTriangles,
|
||||
const PxParticleSpring* springs, const PxU32 numSprings, const PxVec4* restPositions, const PxU32 numParticles)
|
||||
{
|
||||
PX_UNUSED(blendScale);
|
||||
PxParticleCloth particleCloth;
|
||||
//particleCloth.clothBlendScale = blendScale;
|
||||
particleCloth.restVolume = restVolume;
|
||||
particleCloth.pressure = pressure;
|
||||
particleCloth.startVertexIndex = mClothDesc.nbParticles;
|
||||
particleCloth.numVertices = numParticles;
|
||||
particleCloth.startTriangleIndex = mClothDesc.nbTriangles * 3;
|
||||
particleCloth.numTriangles = numTriangles;
|
||||
|
||||
addCloth(particleCloth, triangles, numTriangles, springs, numSprings, restPositions, numParticles);
|
||||
}
|
||||
|
||||
PxParticleClothDesc& getParticleClothDesc()
|
||||
{
|
||||
return mClothDesc;
|
||||
}
|
||||
|
||||
PxU32 mMaxCloths;
|
||||
PxU32 mMaxSprings;
|
||||
PxU32 mMaxTriangles;
|
||||
PxU32 mMaxParticles;
|
||||
PxParticleClothDesc mClothDesc;
|
||||
PxCudaContextManager* mCudaContextManager;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ParticleVolumeBuffersImpl : public PxParticleVolumeBufferHelper, public PxUserAllocated
|
||||
{
|
||||
ParticleVolumeBuffersImpl(PxU32 maxVolumes, PxU32 maxTriangles, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
mMaxVolumes = maxVolumes;
|
||||
mNumVolumes = 0;
|
||||
mMaxTriangles = maxTriangles;
|
||||
mNumTriangles = 0;
|
||||
mParticleVolumeMeshes = reinterpret_cast<PxParticleVolumeMesh*>(PX_ALLOC(sizeof(PxParticleVolumeMesh) * maxVolumes, "ParticleVolumeBuffersImpl::mParticleVolumeMeshes"));
|
||||
mTriangles = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32) * maxTriangles * 3, "ParticleVolumeBuffersImpl::mTriangles"));
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
mParticleVolumes = PX_EXT_PINNED_MEMORY_ALLOC(PxParticleVolume, *cudaContextManager, maxVolumes);
|
||||
mCudaContextManager = cudaContextManager;
|
||||
#else
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mParticleVolumes);
|
||||
#endif
|
||||
|
||||
PX_FREE(mParticleVolumeMeshes);
|
||||
PX_FREE(mTriangles);
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
virtual PxU32 getMaxVolumes() const
|
||||
{
|
||||
return mMaxVolumes;
|
||||
}
|
||||
|
||||
virtual PxU32 getNumVolumes() const
|
||||
{
|
||||
return mNumVolumes;
|
||||
}
|
||||
|
||||
virtual PxU32 getMaxTriangles() const
|
||||
{
|
||||
return mMaxTriangles;
|
||||
}
|
||||
|
||||
virtual PxU32 getNumTriangles() const
|
||||
{
|
||||
return mNumTriangles;
|
||||
}
|
||||
|
||||
virtual PxParticleVolume* getParticleVolumes()
|
||||
{
|
||||
return mParticleVolumes;
|
||||
}
|
||||
|
||||
virtual PxParticleVolumeMesh* getParticleVolumeMeshes()
|
||||
{
|
||||
return mParticleVolumeMeshes;
|
||||
}
|
||||
|
||||
virtual PxU32* getTriangles()
|
||||
{
|
||||
return mTriangles;
|
||||
}
|
||||
|
||||
virtual void addVolume(const PxParticleVolume& volume, const PxParticleVolumeMesh& volumeMesh, const PxU32* triangles, const PxU32 numTriangles)
|
||||
{
|
||||
if (mNumVolumes < mMaxVolumes && mNumTriangles + numTriangles <= mMaxTriangles)
|
||||
{
|
||||
PX_ASSERT(volumeMesh.startIndex == mNumTriangles);
|
||||
|
||||
mParticleVolumes[mNumVolumes] = volume;
|
||||
mParticleVolumeMeshes[mNumVolumes] = volumeMesh;
|
||||
mNumVolumes++;
|
||||
|
||||
for (PxU32 i = 0; i < numTriangles*3; ++i)
|
||||
{
|
||||
mTriangles[mNumTriangles*3 + i] = triangles[i] + volumeMesh.startIndex;
|
||||
}
|
||||
mNumTriangles += numTriangles;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void addVolume(const PxU32 particleOffset, const PxU32 numParticles, const PxU32* triangles, const PxU32 numTriangles)
|
||||
{
|
||||
if (mNumVolumes < mMaxVolumes && mNumTriangles + numTriangles <= mMaxTriangles)
|
||||
{
|
||||
PxParticleVolume particleVolume;
|
||||
particleVolume.bound.setEmpty();
|
||||
particleVolume.particleIndicesOffset = particleOffset;
|
||||
particleVolume.numParticles = numParticles;
|
||||
PxParticleVolumeMesh particleVolumeMesh;
|
||||
particleVolumeMesh.startIndex = mNumTriangles;
|
||||
particleVolumeMesh.count = numTriangles;
|
||||
|
||||
mParticleVolumes[mNumVolumes] = particleVolume;
|
||||
mParticleVolumeMeshes[mNumVolumes] = particleVolumeMesh;
|
||||
mNumVolumes++;
|
||||
|
||||
for (PxU32 i = 0; i < numTriangles*3; ++i)
|
||||
{
|
||||
mTriangles[mNumTriangles*3 + i] = triangles[i] + particleOffset;
|
||||
}
|
||||
mNumTriangles += numTriangles;
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 mMaxVolumes;
|
||||
PxU32 mNumVolumes;
|
||||
PxU32 mMaxTriangles;
|
||||
PxU32 mNumTriangles;
|
||||
PxParticleVolume* mParticleVolumes;
|
||||
PxParticleVolumeMesh* mParticleVolumeMeshes;
|
||||
PxU32* mTriangles;
|
||||
PxCudaContextManager* mCudaContextManager;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ParticleRigidBuffersImpl : public PxParticleRigidBufferHelper, public PxUserAllocated
|
||||
{
|
||||
ParticleRigidBuffersImpl(PxU32 maxRigids, PxU32 maxParticles, PxCudaContextManager* cudaContextManager)
|
||||
: mCudaContextManager(cudaContextManager)
|
||||
{
|
||||
mRigidDesc.maxRigids = maxRigids;
|
||||
mRigidDesc.numActiveRigids = 0;
|
||||
mMaxParticles = maxParticles;
|
||||
mNumParticles = 0;
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
mRigidDesc.rigidOffsets = PX_EXT_PINNED_MEMORY_ALLOC(PxU32, *mCudaContextManager, maxRigids + 1);
|
||||
mRigidDesc.rigidCoefficients = PX_EXT_PINNED_MEMORY_ALLOC(PxReal, *mCudaContextManager, maxRigids);
|
||||
mRigidDesc.rigidTranslations = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *mCudaContextManager, maxRigids);
|
||||
mRigidDesc.rigidRotations = PX_EXT_PINNED_MEMORY_ALLOC(PxQuat, *mCudaContextManager, maxRigids);
|
||||
mRigidDesc.rigidLocalPositions = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *mCudaContextManager, maxParticles);
|
||||
mRigidDesc.rigidLocalNormals = PX_EXT_PINNED_MEMORY_ALLOC(PxVec4, *mCudaContextManager, maxParticles);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidOffsets);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidCoefficients);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidTranslations);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidRotations);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidLocalPositions);
|
||||
PX_EXT_PINNED_MEMORY_FREE(*mCudaContextManager, mRigidDesc.rigidLocalNormals);
|
||||
#endif
|
||||
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
|
||||
virtual PxU32 getMaxRigids() const { return mRigidDesc.maxRigids; }
|
||||
virtual PxU32 getNumRigids() const { return mRigidDesc.numActiveRigids; }
|
||||
virtual PxU32 getMaxParticles() const { return mMaxParticles; }
|
||||
virtual PxU32 getNumParticles() const { return mNumParticles; }
|
||||
|
||||
void addRigid(const PxVec3& translation, const PxQuat& rotation, const PxReal coefficient,
|
||||
const PxVec4* localPositions, const PxVec4* localNormals, PxU32 numParticles)
|
||||
{
|
||||
PX_ASSERT(numParticles > 0);
|
||||
const PxU32 numRigids = mRigidDesc.numActiveRigids;
|
||||
|
||||
if (numParticles > 0 && numRigids < mRigidDesc.maxRigids && mNumParticles + numParticles <= mMaxParticles)
|
||||
{
|
||||
mRigidDesc.rigidOffsets[numRigids] = mNumParticles;
|
||||
mRigidDesc.rigidOffsets[numRigids + 1] = mNumParticles + numParticles;
|
||||
mRigidDesc.rigidTranslations[numRigids] = PxVec4(translation, 0.0f);
|
||||
mRigidDesc.rigidRotations[numRigids] = rotation;
|
||||
mRigidDesc.rigidCoefficients[numRigids] = coefficient;
|
||||
PxMemCopy(mRigidDesc.rigidLocalPositions + mNumParticles, localPositions, numParticles * sizeof(PxVec4));
|
||||
PxMemCopy(mRigidDesc.rigidLocalNormals + mNumParticles, localNormals, numParticles * sizeof(PxVec4));
|
||||
mRigidDesc.numActiveRigids += 1;
|
||||
mNumParticles += numParticles;
|
||||
}
|
||||
}
|
||||
|
||||
PxParticleRigidDesc& getParticleRigidDesc()
|
||||
{
|
||||
return mRigidDesc;
|
||||
}
|
||||
|
||||
PxU32 mMaxParticles;
|
||||
PxU32 mNumParticles;
|
||||
PxParticleRigidDesc mRigidDesc;
|
||||
PxCudaContextManager* mCudaContextManager;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxParticleVolumeBufferHelper* PxCreateParticleVolumeBufferHelper(PxU32 maxVolumes, PxU32 maxTriangles, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
PxParticleVolumeBufferHelper* ret = NULL;
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
ret = PX_NEW(ParticleVolumeBuffersImpl)(maxVolumes, maxTriangles, cudaContextManager);
|
||||
#else
|
||||
PX_UNUSED(maxVolumes);
|
||||
PX_UNUSED(maxTriangles);
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
PxParticleClothBufferHelper* PxCreateParticleClothBufferHelper(const PxU32 maxCloths, const PxU32 maxTriangles, const PxU32 maxSprings, const PxU32 maxParticles, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
PxParticleClothBufferHelper* ret = NULL;
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
ret = PX_NEW(ParticleClothBuffersImpl)(maxCloths, maxTriangles, maxSprings, maxParticles, cudaContextManager);
|
||||
#else
|
||||
PX_UNUSED(maxCloths);
|
||||
PX_UNUSED(maxTriangles);
|
||||
PX_UNUSED(maxSprings);
|
||||
PX_UNUSED(maxParticles);
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
PxParticleRigidBufferHelper* PxCreateParticleRigidBufferHelper(const PxU32 maxRigids, const PxU32 maxParticles, PxCudaContextManager* cudaContextManager)
|
||||
{
|
||||
PxParticleRigidBufferHelper* ret = NULL;
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
ret = PX_NEW(ParticleRigidBuffersImpl)(maxRigids, maxParticles, cudaContextManager);
|
||||
#else
|
||||
PX_UNUSED(maxRigids);
|
||||
PX_UNUSED(maxParticles);
|
||||
PX_UNUSED(cudaContextManager);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace ExtGpu
|
||||
} //namespace physx
|
||||
35
engine/third_party/physx/source/physxextensions/src/ExtPlatform.h
vendored
Normal file
35
engine/third_party/physx/source/physxextensions/src/ExtPlatform.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include <assert.h>
|
||||
#include "foundation/PxThread.h"
|
||||
|
||||
#endif
|
||||
209
engine/third_party/physx/source/physxextensions/src/ExtPrismaticJoint.cpp
vendored
Normal file
209
engine/third_party/physx/source/physxextensions/src/ExtPrismaticJoint.cpp
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
// 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 "ExtPrismaticJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
PrismaticJoint::PrismaticJoint(const PxTolerancesScale& scale, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
PrismaticJointT(PxJointConcreteType::ePRISMATIC, actor0, localFrame0, actor1, localFrame1, "PrismaticJointData")
|
||||
{
|
||||
PrismaticJointData* data = static_cast<PrismaticJointData*>(mData);
|
||||
|
||||
data->limit = PxJointLinearLimitPair(scale);
|
||||
data->jointFlags = PxPrismaticJointFlags();
|
||||
}
|
||||
|
||||
PxPrismaticJointFlags PrismaticJoint::getPrismaticJointFlags() const
|
||||
{
|
||||
return data().jointFlags;
|
||||
}
|
||||
|
||||
void PrismaticJoint::setPrismaticJointFlags(PxPrismaticJointFlags flags)
|
||||
{
|
||||
data().jointFlags = flags; markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, jointFlags, static_cast<PxPrismaticJoint&>(*this), flags)
|
||||
}
|
||||
|
||||
void PrismaticJoint::setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value)
|
||||
{
|
||||
if(value)
|
||||
data().jointFlags |= flag;
|
||||
else
|
||||
data().jointFlags &= ~flag;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, jointFlags, static_cast<PxPrismaticJoint&>(*this), getPrismaticJointFlags())
|
||||
}
|
||||
|
||||
PxJointLinearLimitPair PrismaticJoint::getLimit() const
|
||||
{
|
||||
return data().limit;
|
||||
}
|
||||
|
||||
void PrismaticJoint::setLimit(const PxJointLinearLimitPair& limit)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(limit.isValid(), "PxPrismaticJoint::setLimit: invalid parameter");
|
||||
data().limit = limit;
|
||||
markDirty();
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxPrismaticJoint& j = static_cast<PxPrismaticJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitLower, j, limit.lower)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitUpper, j, limit.upper)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PrismaticJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
|
||||
if((flags & PxConstraintVisualizationFlag::eLIMITS) && (data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED))
|
||||
{
|
||||
viz.visualizeLinearLimit(cA2w, cB2w, data.limit.lower);
|
||||
viz.visualizeLinearLimit(cA2w, cB2w, data.limit.upper);
|
||||
}
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 PrismaticJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
joint::applyNeighborhoodOperator(cA2w, cB2w);
|
||||
|
||||
const bool limitEnabled = data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED;
|
||||
const PxJointLinearLimitPair& limit = data.limit;
|
||||
const bool limitIsLocked = limitEnabled && limit.lower >= limit.upper;
|
||||
|
||||
const PxVec3 bOriginInA = cA2w.transformInv(cB2w.p);
|
||||
|
||||
PxVec3 ra, rb, axis;
|
||||
ch.prepareLockedAxes(cA2w.q, cB2w.q, bOriginInA, limitIsLocked ? 7ul : 6ul, 7ul, ra, rb, &axis);
|
||||
cA2wOut = ra + bA2w.p;
|
||||
cB2wOut = rb + bB2w.p;
|
||||
|
||||
if(limitEnabled && !limitIsLocked)
|
||||
{
|
||||
const PxReal ordinate = bOriginInA.x;
|
||||
|
||||
ch.linearLimit(axis, ordinate, limit.upper, limit);
|
||||
ch.linearLimit(-axis, -ordinate, -limit.lower, limit);
|
||||
}
|
||||
|
||||
return ch.getCount();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gPrismaticJointShaders = { PrismaticJointSolverPrep, PrismaticJointVisualize, PxConstraintFlag::Enum(0) };
|
||||
|
||||
PxConstraintSolverPrep PrismaticJoint::getPrep() const { return gPrismaticJointShaders.solverPrep; }
|
||||
|
||||
PxPrismaticJoint* physx::PxPrismaticJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxPrismaticJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxPrismaticJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxPrismaticJointCreate: at least one actor must be dynamic");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxPrismaticJointCreate: actors must be different");
|
||||
|
||||
return createJointT<PrismaticJoint, PrismaticJointData>(physics, actor0, localFrame0, actor1, localFrame1, gPrismaticJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void PrismaticJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gPrismaticJointShaders);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
void PrismaticJoint::updateOmniPvdProperties() const
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
const PxPrismaticJoint& j = static_cast<const PxPrismaticJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, position, j, getPosition())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, velocity, j, getVelocity())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<PrismaticJoint>(PrismaticJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxPrismaticJoint& j = static_cast<PxPrismaticJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::ePRISMATIC);
|
||||
|
||||
PxJointLinearLimitPair limit = joint.getLimit();
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitLower, j, limit.lower)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitUpper, j, limit.upper)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, position, j, joint.getPosition())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxPrismaticJoint, velocity, j, joint.getVelocity())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
85
engine/third_party/physx/source/physxextensions/src/ExtPrismaticJoint.h
vendored
Normal file
85
engine/third_party/physx/source/physxextensions/src/ExtPrismaticJoint.h
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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 EXT_PRISMATIC_JOINT_H
|
||||
#define EXT_PRISMATIC_JOINT_H
|
||||
|
||||
#include "common/PxTolerancesScale.h"
|
||||
#include "extensions/PxPrismaticJoint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxPrismaticJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct PrismaticJointData : public JointData
|
||||
{
|
||||
PxJointLinearLimitPair limit;
|
||||
|
||||
PxPrismaticJointFlags jointFlags;
|
||||
|
||||
private:
|
||||
PrismaticJointData(const PxJointLinearLimitPair& pair) : limit(pair) {}
|
||||
};
|
||||
|
||||
typedef JointT<PxPrismaticJoint, PrismaticJointData, PxPrismaticJointGeneratedValues> PrismaticJointT;
|
||||
|
||||
class PrismaticJoint : public PrismaticJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
PrismaticJoint(PxBaseFlags baseFlags) : PrismaticJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static PrismaticJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<PrismaticJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
PrismaticJoint(const PxTolerancesScale& scale, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxPrismaticJoint
|
||||
virtual PxReal getPosition() const PX_OVERRIDE { return getRelativeTransform().p.x; }
|
||||
virtual PxReal getVelocity() const PX_OVERRIDE { return getRelativeLinearVelocity().x; }
|
||||
virtual void setLimit(const PxJointLinearLimitPair& limit) PX_OVERRIDE;
|
||||
virtual PxJointLinearLimitPair getLimit() const PX_OVERRIDE;
|
||||
virtual void setPrismaticJointFlags(PxPrismaticJointFlags flags) PX_OVERRIDE;
|
||||
virtual void setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value) PX_OVERRIDE;
|
||||
virtual PxPrismaticJointFlags getPrismaticJointFlags() const PX_OVERRIDE;
|
||||
//~PxPrismaticJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE;
|
||||
#endif
|
||||
//~PxConstraintConnector
|
||||
};
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
158
engine/third_party/physx/source/physxextensions/src/ExtPvd.cpp
vendored
Normal file
158
engine/third_party/physx/source/physxextensions/src/ExtPvd.cpp
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
// 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.
|
||||
|
||||
// suppress LNK4221
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
PX_DUMMY_SYMBOL
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
#include "ExtPvd.h"
|
||||
#include "PxExtensionMetaDataObjects.h"
|
||||
|
||||
#include "ExtD6Joint.h"
|
||||
#include "ExtFixedJoint.h"
|
||||
#include "ExtSphericalJoint.h"
|
||||
#include "ExtDistanceJoint.h"
|
||||
#include "ExtRevoluteJoint.h"
|
||||
#include "ExtPrismaticJoint.h"
|
||||
#include "ExtJointMetaDataExtensions.h"
|
||||
#include "PvdMetaDataPropertyVisitor.h"
|
||||
#include "PvdMetaDataDefineProperties.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
using namespace physx::Vd;
|
||||
|
||||
template<typename TObjType, typename TOperator>
|
||||
static inline void visitPvdInstanceProperties( TOperator inOperator )
|
||||
{
|
||||
PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( makePvdPropertyFilter( inOperator ), 0 );
|
||||
}
|
||||
|
||||
template<typename TObjType, typename TOperator>
|
||||
static inline void visitPvdProperties( TOperator inOperator )
|
||||
{
|
||||
PvdPropertyFilter<TOperator> theFilter( makePvdPropertyFilter( inOperator ) );
|
||||
PxU32 thePropCount = PxClassInfoTraits<TObjType>().Info.visitBaseProperties( theFilter );
|
||||
PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( theFilter, thePropCount );
|
||||
}
|
||||
|
||||
Pvd::PvdNameSpace::PvdNameSpace(physx::pvdsdk::PvdDataStream& conn, const char* /*name*/)
|
||||
: mConnection(conn)
|
||||
{
|
||||
}
|
||||
|
||||
Pvd::PvdNameSpace::~PvdNameSpace()
|
||||
{
|
||||
}
|
||||
|
||||
void Pvd::releasePvdInstance(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint)
|
||||
{
|
||||
if(!pvdConnection.isConnected())
|
||||
return;
|
||||
//remove from scene and from any attached actors.
|
||||
PxRigidActor* actor0, *actor1;
|
||||
c.getActors( actor0, actor1 );
|
||||
PxScene* scene = c.getScene();
|
||||
if(scene) pvdConnection.removeObjectRef( scene, "Joints", &joint );
|
||||
if ( actor0 && actor0->getScene() ) pvdConnection.removeObjectRef( actor0, "Joints", &joint );
|
||||
if ( actor1 && actor1->getScene()) pvdConnection.removeObjectRef( actor1, "Joints", &joint );
|
||||
pvdConnection.destroyInstance(&joint);
|
||||
}
|
||||
|
||||
template<typename TObjType>
|
||||
static void registerProperties( PvdDataStream& inStream )
|
||||
{
|
||||
inStream.createClass<TObjType>();
|
||||
PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() );
|
||||
PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() );
|
||||
visitPvdInstanceProperties<TObjType>( theDefinitionObj );
|
||||
}
|
||||
|
||||
template<typename TObjType, typename TValueStructType>
|
||||
static void registerPropertiesAndValueStruct( PvdDataStream& inStream )
|
||||
{
|
||||
inStream.createClass<TObjType>();
|
||||
inStream.deriveClass<PxJoint,TObjType>();
|
||||
PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() );
|
||||
{
|
||||
PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() );
|
||||
visitPvdInstanceProperties<TObjType>( theDefinitionObj );
|
||||
}
|
||||
{
|
||||
PvdClassInfoValueStructDefine theDefinitionObj( theHelper );
|
||||
visitPvdProperties<TObjType>( theDefinitionObj );
|
||||
theHelper.addPropertyMessage<TObjType,TValueStructType>();
|
||||
}
|
||||
}
|
||||
|
||||
void Pvd::sendClassDescriptions(physx::pvdsdk::PvdDataStream& inStream)
|
||||
{
|
||||
if (inStream.isClassExist<PxJoint>())
|
||||
return;
|
||||
|
||||
{ //PxJoint
|
||||
registerProperties<PxJoint>( inStream );
|
||||
inStream.createProperty<PxJoint,ObjectRef>( "Parent", "parents" );
|
||||
registerPropertiesAndValueStruct<PxDistanceJoint,PxDistanceJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxFixedJoint,PxFixedJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxPrismaticJoint,PxPrismaticJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxSphericalJoint,PxSphericalJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxRevoluteJoint,PxRevoluteJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxD6Joint,PxD6JointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxGearJoint,PxGearJointGeneratedValues>( inStream);
|
||||
registerPropertiesAndValueStruct<PxRackAndPinionJoint,PxRackAndPinionJointGeneratedValues>( inStream);
|
||||
}
|
||||
}
|
||||
|
||||
void Pvd::setActors( physx::pvdsdk::PvdDataStream& inStream, const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 )
|
||||
{
|
||||
PxRigidActor* actor0, *actor1;
|
||||
c.getActors( actor0, actor1 );
|
||||
if ( actor0 )
|
||||
inStream.removeObjectRef( actor0, "Joints", &inJoint );
|
||||
if ( actor1 )
|
||||
inStream.removeObjectRef( actor1, "Joints", &inJoint );
|
||||
|
||||
if ( newActor0 && newActor0->getScene())
|
||||
inStream.pushBackObjectRef( newActor0, "Joints", &inJoint );
|
||||
if ( newActor1 && newActor1->getScene())
|
||||
inStream.pushBackObjectRef( newActor1, "Joints", &inJoint );
|
||||
|
||||
inStream.setPropertyValue( &inJoint, "Actors.actor0", reinterpret_cast<const void*>(newActor0) );
|
||||
inStream.setPropertyValue( &inJoint, "Actors.actor1", reinterpret_cast<const void*>(newActor1) );
|
||||
const void* parent = newActor0 ? newActor0 : newActor1;
|
||||
inStream.setPropertyValue( &inJoint, "Parent", parent );
|
||||
|
||||
if((newActor0 && !newActor0->getScene()) || (newActor1 && !newActor1->getScene()))
|
||||
{
|
||||
inStream.removeObjectRef( c.getScene(), "Joints", &inJoint );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PX_SUPPORT_PVD
|
||||
200
engine/third_party/physx/source/physxextensions/src/ExtPvd.h
vendored
Normal file
200
engine/third_party/physx/source/physxextensions/src/ExtPvd.h
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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 EXT_PVD_H
|
||||
#define EXT_PVD_H
|
||||
|
||||
#if PX_SUPPORT_PVD
|
||||
|
||||
#include "extensions/PxJoint.h"
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "PxPvdDataStream.h"
|
||||
#include "PvdTypeNames.h"
|
||||
#include "PxPvdObjectModelBaseTypes.h"
|
||||
|
||||
#if PX_LINUX && PX_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
#endif
|
||||
#include "PxExtensionMetaDataObjects.h"
|
||||
#if PX_LINUX && PX_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxJoint;
|
||||
class PxD6Joint;
|
||||
class PxDistanceJoint;
|
||||
class PxFixedJoint;
|
||||
class PxPrismaticJoint;
|
||||
class PxRevoluteJoint;
|
||||
class PxSphericalJoint;
|
||||
class PxGearJoint;
|
||||
class PxRackAndPinionJoint;
|
||||
}
|
||||
|
||||
#define JOINT_GROUP 3
|
||||
namespace physx
|
||||
{
|
||||
namespace pvdsdk {
|
||||
#define DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP( type ) DEFINE_PVD_TYPE_NAME_MAP( physx::type, "physx3", #type )
|
||||
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6Joint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6JointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxGearJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxGearJointGeneratedValues)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRackAndPinionJoint)
|
||||
DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRackAndPinionJointGeneratedValues)
|
||||
#undef DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP
|
||||
} //pvdsdk
|
||||
} // physx
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
using namespace physx::pvdsdk;
|
||||
|
||||
class Pvd: public physx::PxUserAllocated
|
||||
{
|
||||
Pvd& operator=(const Pvd&);
|
||||
public:
|
||||
class PvdNameSpace
|
||||
{
|
||||
|
||||
public:
|
||||
PvdNameSpace(PvdDataStream& conn, const char* name);
|
||||
~PvdNameSpace();
|
||||
private:
|
||||
PvdNameSpace& operator=(const PvdNameSpace&);
|
||||
PvdDataStream& mConnection;
|
||||
};
|
||||
|
||||
static void setActors( PvdDataStream& PvdDataStream,
|
||||
const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 );
|
||||
|
||||
template<typename TObjType>
|
||||
static void createInstance( PvdDataStream& inStream, const PxConstraint& c, const TObjType& inSource )
|
||||
{
|
||||
inStream.createInstance( &inSource );
|
||||
inStream.pushBackObjectRef( c.getScene(), "Joints", &inSource );
|
||||
|
||||
class ConstraintUpdateCmd : public PvdDataStream::PvdCommand
|
||||
{
|
||||
ConstraintUpdateCmd &operator=(const ConstraintUpdateCmd&) { PX_ASSERT(0); return *this; } //PX_NOCOPY doesn't work for local classes
|
||||
public:
|
||||
|
||||
const PxConstraint& mConstraint;
|
||||
const PxJoint& mJoint;
|
||||
|
||||
PxRigidActor* actor0, *actor1;
|
||||
ConstraintUpdateCmd(const PxConstraint& constraint, const PxJoint& joint):PvdDataStream::PvdCommand(), mConstraint(constraint), mJoint(joint)
|
||||
{
|
||||
mConstraint.getActors( actor0, actor1 );
|
||||
}
|
||||
|
||||
//Assigned is needed for copying
|
||||
ConstraintUpdateCmd(const ConstraintUpdateCmd& cmd)
|
||||
:PvdDataStream::PvdCommand(), mConstraint(cmd.mConstraint), mJoint(cmd.mJoint)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool canRun(PvdInstanceDataStream &inStream_ )
|
||||
{
|
||||
PX_ASSERT(inStream_.isInstanceValid(&mJoint));
|
||||
//When run this command, the constraint maybe buffer removed
|
||||
return ((actor0 == NULL) || inStream_.isInstanceValid(actor0))
|
||||
&& ((actor1 == NULL) || inStream_.isInstanceValid(actor1));
|
||||
}
|
||||
virtual void run( PvdInstanceDataStream &inStream_ )
|
||||
{
|
||||
//When run this command, the constraint maybe buffer removed
|
||||
if(!inStream_.isInstanceValid(&mJoint))
|
||||
return;
|
||||
|
||||
PxRigidActor* actor0_, *actor1_;
|
||||
mConstraint.getActors( actor0_, actor1_ );
|
||||
|
||||
if ( actor0_ && (inStream_.isInstanceValid(actor0_)) )
|
||||
inStream_.pushBackObjectRef( actor0_, "Joints", &mJoint );
|
||||
if ( actor1_ && (inStream_.isInstanceValid(actor1_)) )
|
||||
inStream_.pushBackObjectRef( actor1_, "Joints", &mJoint );
|
||||
const void* parent = actor0_ ? actor0_ : actor1_;
|
||||
inStream_.setPropertyValue( &mJoint, "Parent", parent );
|
||||
}
|
||||
};
|
||||
|
||||
ConstraintUpdateCmd* cmd = PX_PLACEMENT_NEW(inStream.allocateMemForCmd(sizeof(ConstraintUpdateCmd)),
|
||||
ConstraintUpdateCmd)(c, inSource);
|
||||
|
||||
if(cmd->canRun( inStream ))
|
||||
cmd->run( inStream );
|
||||
else
|
||||
inStream.pushPvdCommand( *cmd );
|
||||
}
|
||||
|
||||
template<typename jointtype, typename structValue>
|
||||
static void updatePvdProperties(PvdDataStream& pvdConnection, const jointtype& joint)
|
||||
{
|
||||
structValue theValueStruct( &joint );
|
||||
pvdConnection.setPropertyMessage( &joint, theValueStruct );
|
||||
}
|
||||
|
||||
template<typename jointtype>
|
||||
static void simUpdate(PvdDataStream& /*pvdConnection*/, const jointtype& /*joint*/) {}
|
||||
|
||||
template<typename jointtype>
|
||||
static void createPvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const jointtype& joint)
|
||||
{
|
||||
createInstance<jointtype>( pvdConnection, c, joint );
|
||||
}
|
||||
|
||||
static void releasePvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint);
|
||||
static void sendClassDescriptions(PvdDataStream& pvdConnection);
|
||||
};
|
||||
} // ext
|
||||
|
||||
} // physx
|
||||
|
||||
#endif // PX_SUPPORT_PVD
|
||||
#endif // EXT_PVD_H
|
||||
96
engine/third_party/physx/source/physxextensions/src/ExtPxStringTable.cpp
vendored
Normal file
96
engine/third_party/physx/source/physxextensions/src/ExtPxStringTable.cpp
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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/PxAllocatorCallback.h"
|
||||
#include "foundation/PxString.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "extensions/PxStringTableExt.h"
|
||||
#include "PxProfileAllocatorWrapper.h" //tools for using a custom allocator
|
||||
|
||||
using namespace physx;
|
||||
using namespace physx::profile;
|
||||
|
||||
namespace
|
||||
{
|
||||
class PxStringTableImpl : public PxStringTable, public PxUserAllocated
|
||||
{
|
||||
typedef PxProfileHashMap<const char*, PxU32> THashMapType;
|
||||
PxProfileAllocatorWrapper mWrapper;
|
||||
THashMapType mHashMap;
|
||||
public:
|
||||
|
||||
PxStringTableImpl( PxAllocatorCallback& inAllocator )
|
||||
: mWrapper ( inAllocator )
|
||||
, mHashMap ( mWrapper )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PxStringTableImpl()
|
||||
{
|
||||
for ( THashMapType::Iterator iter = mHashMap.getIterator();
|
||||
iter.done() == false;
|
||||
++iter )
|
||||
PX_PROFILE_DELETE( mWrapper, const_cast<char*>( iter->first ) );
|
||||
mHashMap.clear();
|
||||
}
|
||||
|
||||
virtual const char* allocateStr( const char* inSrc )
|
||||
{
|
||||
if ( inSrc == NULL )
|
||||
inSrc = "";
|
||||
const THashMapType::Entry* existing( mHashMap.find( inSrc ) );
|
||||
if ( existing == NULL )
|
||||
{
|
||||
size_t len( strlen( inSrc ) );
|
||||
len += 1;
|
||||
char* newMem = reinterpret_cast<char*>(mWrapper.getAllocator().allocate( len, "PxStringTableImpl: const char*", PX_FL));
|
||||
physx::Pxstrlcpy( newMem, len, inSrc );
|
||||
mHashMap.insert( newMem, 1 );
|
||||
return newMem;
|
||||
}
|
||||
else
|
||||
{
|
||||
++const_cast<THashMapType::Entry*>(existing)->second;
|
||||
return existing->first;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the string table and all the strings associated with it.
|
||||
*/
|
||||
virtual void release()
|
||||
{
|
||||
PX_PROFILE_DELETE( mWrapper.getAllocator(), this );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
PxStringTable& physx::PxStringTableExt::createStringTable( PxAllocatorCallback& inAllocator )
|
||||
{
|
||||
return *PX_PROFILE_NEW( inAllocator, PxStringTableImpl )( inAllocator );
|
||||
}
|
||||
392
engine/third_party/physx/source/physxextensions/src/ExtRackAndPinionJoint.cpp
vendored
Normal file
392
engine/third_party/physx/source/physxextensions/src/ExtRackAndPinionJoint.cpp
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
// 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 "ExtRackAndPinionJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
#include "extensions/PxRevoluteJoint.h"
|
||||
#include "extensions/PxPrismaticJoint.h"
|
||||
#include "PxArticulationJointReducedCoordinate.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
PX_IMPLEMENT_OUTPUT_ERROR
|
||||
|
||||
RackAndPinionJoint::RackAndPinionJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
RackAndPinionJointT(PxJointConcreteType::eRACK_AND_PINION, actor0, localFrame0, actor1, localFrame1, "RackAndPinionJointData")
|
||||
{
|
||||
RackAndPinionJointData* data = static_cast<RackAndPinionJointData*>(mData);
|
||||
data->hingeJoint = NULL;
|
||||
data->prismaticJoint = NULL;
|
||||
data->ratio = 1.0f;
|
||||
data->px = 0.0f;
|
||||
data->vangle = 0.0f;
|
||||
|
||||
resetError();
|
||||
}
|
||||
|
||||
void RackAndPinionJoint::setRatio(float ratio)
|
||||
{
|
||||
RackAndPinionJointData* data = reinterpret_cast<RackAndPinionJointData*>(mData);
|
||||
data->ratio = ratio;
|
||||
resetError();
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRackAndPinionJoint, ratio, static_cast<PxRackAndPinionJoint&>(*this), ratio)
|
||||
}
|
||||
|
||||
float RackAndPinionJoint::getRatio() const
|
||||
{
|
||||
RackAndPinionJointData* data = reinterpret_cast<RackAndPinionJointData*>(mData);
|
||||
return data->ratio;
|
||||
}
|
||||
|
||||
bool RackAndPinionJoint::setData(PxU32 nbRackTeeth, PxU32 nbPinionTeeth, float rackLength)
|
||||
{
|
||||
if(!nbRackTeeth)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setData: nbRackTeeth cannot be zero.");
|
||||
|
||||
if(!nbPinionTeeth)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setData: nbPinionTeeth cannot be zero.");
|
||||
|
||||
if(rackLength<=0.0f)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setData: rackLength must be positive.");
|
||||
|
||||
RackAndPinionJointData* data = reinterpret_cast<RackAndPinionJointData*>(mData);
|
||||
data->ratio = (PxTwoPi*nbRackTeeth)/(rackLength*nbPinionTeeth);
|
||||
resetError();
|
||||
markDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RackAndPinionJoint::setJoints(const PxBase* hinge, const PxBase* prismatic)
|
||||
{
|
||||
RackAndPinionJointData* data = static_cast<RackAndPinionJointData*>(mData);
|
||||
|
||||
if(hinge)
|
||||
{
|
||||
const PxType type0 = hinge->getConcreteType();
|
||||
if(type0 == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* joint0 = static_cast<const PxArticulationJointReducedCoordinate*>(hinge);
|
||||
const PxArticulationJointType::Enum artiJointType0 = joint0->getJointType();
|
||||
if(artiJointType0 != PxArticulationJointType::eREVOLUTE && artiJointType0 != PxArticulationJointType::eREVOLUTE_UNWRAPPED)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setJoints: passed joint must be a revolute joint.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(type0 != PxJointConcreteType::eREVOLUTE && type0 != PxJointConcreteType::eD6)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setJoints: passed hinge joint must be either a revolute joint or a D6 joint.");
|
||||
}
|
||||
}
|
||||
|
||||
if(prismatic)
|
||||
{
|
||||
const PxType type1 = prismatic->getConcreteType();
|
||||
if(type1 == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* joint1 = static_cast<const PxArticulationJointReducedCoordinate*>(prismatic);
|
||||
const PxArticulationJointType::Enum artiJointType1 = joint1->getJointType();
|
||||
if(artiJointType1 != PxArticulationJointType::ePRISMATIC)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setJoints: passed joint must be a prismatic joint.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(type1 != PxJointConcreteType::ePRISMATIC && type1 != PxJointConcreteType::eD6)
|
||||
return outputError<PxErrorCode::eINVALID_PARAMETER>(__LINE__, "PxRackAndPinionJoint::setJoints: passed prismatic joint must be either a prismatic joint or a D6 joint.");
|
||||
}
|
||||
}
|
||||
|
||||
data->hingeJoint = hinge;
|
||||
data->prismaticJoint = prismatic;
|
||||
resetError();
|
||||
markDirty();
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
const PxBase* joints[] = { hinge, prismatic };
|
||||
PxU32 jointCount = sizeof(joints) / sizeof(joints[0]);
|
||||
OMNI_PVD_SET_ARRAY(OMNI_PVD_CONTEXT_HANDLE, PxRackAndPinionJoint, joints, static_cast<PxRackAndPinionJoint&>(*this), joints, jointCount)
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RackAndPinionJoint::getJoints(const PxBase*& hinge, const PxBase*& prismatic) const
|
||||
{
|
||||
const RackAndPinionJointData* data = static_cast<const RackAndPinionJointData*>(mData);
|
||||
hinge = data->hingeJoint;
|
||||
prismatic = data->prismaticJoint;
|
||||
}
|
||||
|
||||
static float angleDiff(float angle0, float angle1)
|
||||
{
|
||||
const float diff = fmodf( angle1 - angle0 + PxPi, PxTwoPi) - PxPi;
|
||||
return diff < -PxPi ? diff + PxTwoPi : diff;
|
||||
}
|
||||
|
||||
void RackAndPinionJoint::updateError()
|
||||
{
|
||||
RackAndPinionJointData* data = static_cast<RackAndPinionJointData*>(mData);
|
||||
|
||||
if(!data->hingeJoint || !data->prismaticJoint)
|
||||
return;
|
||||
|
||||
PxRigidActor* rackActor0;
|
||||
PxRigidActor* rackActor1;
|
||||
getActors(rackActor0, rackActor1);
|
||||
|
||||
float Angle0 = 0.0f;
|
||||
float Sign0 = 0.0f;
|
||||
{
|
||||
PxRigidActor* hingeActor0;
|
||||
PxRigidActor* hingeActor1;
|
||||
|
||||
const PxType type = data->hingeJoint->getConcreteType();
|
||||
if(type == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* artiHingeJoint = static_cast<const PxArticulationJointReducedCoordinate*>(data->hingeJoint);
|
||||
|
||||
hingeActor0 = &artiHingeJoint->getParentArticulationLink();
|
||||
hingeActor1 = &artiHingeJoint->getChildArticulationLink();
|
||||
|
||||
Angle0 = artiHingeJoint->getJointPosition(PxArticulationAxis::eTWIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxJoint* hingeJoint = static_cast<const PxJoint*>(data->hingeJoint);
|
||||
|
||||
hingeJoint->getActors(hingeActor0, hingeActor1);
|
||||
|
||||
if(type == PxJointConcreteType::eREVOLUTE)
|
||||
Angle0 = static_cast<const PxRevoluteJoint*>(hingeJoint)->getAngle();
|
||||
else if (type == PxJointConcreteType::eD6)
|
||||
Angle0 = static_cast<const PxD6Joint*>(hingeJoint)->getTwistAngle();
|
||||
}
|
||||
|
||||
if(rackActor0 == hingeActor0 || rackActor1 == hingeActor0)
|
||||
Sign0 = -1.0f;
|
||||
else if (rackActor0 == hingeActor1 || rackActor1 == hingeActor1)
|
||||
Sign0 = 1.0f;
|
||||
else
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
|
||||
if(!mInitDone)
|
||||
{
|
||||
mInitDone = true;
|
||||
mPersistentAngle0 = Angle0;
|
||||
}
|
||||
|
||||
const float travelThisFrame0 = angleDiff(Angle0, mPersistentAngle0);
|
||||
mVirtualAngle0 += travelThisFrame0;
|
||||
// printf("mVirtualAngle0: %f\n", mVirtualAngle0);
|
||||
|
||||
mPersistentAngle0 = Angle0;
|
||||
|
||||
float px = 0.0f;
|
||||
float Sign1 = 0.0f;
|
||||
{
|
||||
PxRigidActor* prismaticActor0;
|
||||
PxRigidActor* prismaticActor1;
|
||||
|
||||
const PxType type = data->prismaticJoint->getConcreteType();
|
||||
if(type == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE)
|
||||
{
|
||||
const PxArticulationJointReducedCoordinate* artiPrismaticJoint = static_cast<const PxArticulationJointReducedCoordinate*>(data->prismaticJoint);
|
||||
|
||||
prismaticActor0 = &artiPrismaticJoint->getParentArticulationLink();
|
||||
prismaticActor1 = &artiPrismaticJoint->getChildArticulationLink();
|
||||
|
||||
px = artiPrismaticJoint->getJointPosition(PxArticulationAxis::eX);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxJoint* prismaticJoint = static_cast<const PxJoint*>(data->prismaticJoint);
|
||||
|
||||
prismaticJoint->getActors(prismaticActor0, prismaticActor1);
|
||||
|
||||
if(type==PxJointConcreteType::ePRISMATIC)
|
||||
px = static_cast<const PxPrismaticJoint*>(prismaticJoint)->getPosition();
|
||||
else if(type==PxJointConcreteType::eD6)
|
||||
px = prismaticJoint->getRelativeTransform().p.x;
|
||||
}
|
||||
|
||||
if(rackActor0 == prismaticActor0 || rackActor1 == prismaticActor0)
|
||||
Sign1 = -1.0f;
|
||||
else if(rackActor0 == prismaticActor1 || rackActor1 == prismaticActor1)
|
||||
Sign1 = 1.0f;
|
||||
else
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
|
||||
// printf("px: %f\n", px);
|
||||
data->px = Sign1*px;
|
||||
data->vangle = Sign0*mVirtualAngle0;
|
||||
markDirty();
|
||||
}
|
||||
|
||||
void RackAndPinionJoint::resetError()
|
||||
{
|
||||
mVirtualAngle0 = 0.0f;
|
||||
mPersistentAngle0 = 0.0f;
|
||||
mInitDone = false;
|
||||
}
|
||||
|
||||
static void RackAndPinionJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
{
|
||||
const RackAndPinionJointData& data = *reinterpret_cast<const RackAndPinionJointData*>(constantBlock);
|
||||
|
||||
// Visualize joint frames
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
}
|
||||
|
||||
if(0)
|
||||
{
|
||||
const RackAndPinionJointData& data = *reinterpret_cast<const RackAndPinionJointData*>(constantBlock);
|
||||
|
||||
if(0)
|
||||
{
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
|
||||
const PxVec3 gearAxis0 = cA2w.q.getBasisVector0();
|
||||
const PxVec3 rackPrismaticAxis = cB2w.q.getBasisVector0();
|
||||
viz.visualizeLine(cA2w.p, cA2w.p + gearAxis0, 0xff0000ff);
|
||||
viz.visualizeLine(cB2w.p, cB2w.p + rackPrismaticAxis, 0xff0000ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 RackAndPinionJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const RackAndPinionJointData& data = *reinterpret_cast<const RackAndPinionJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
cA2wOut = cB2w.p;
|
||||
cB2wOut = cB2w.p;
|
||||
|
||||
const PxVec3 gearAxis = cA2w.q.getBasisVector0();
|
||||
const PxVec3 rackPrismaticAxis = cB2w.q.getBasisVector0();
|
||||
|
||||
// PT: this optional bit of code tries to fix the ratio for cases where the "same" rack is moved e.g. above or below a gear.
|
||||
// In that case the rack would move in one direction or another depending on its position compared to the gear, and to avoid
|
||||
// having to use a negative ratio in one of these cases this code tries to compute the proper sign and handle both cases the
|
||||
// same way from the user's perspective. This created unexpected issues in ill-defined cases where e.g. the gear and the rack
|
||||
// completely overlap, and we end up with a +0 or -0 for "dp" in the code below. So now this code disables itself in these
|
||||
// cases but it would probably be better to disable it entirely. We don't do it though since it could break existing scenes.
|
||||
// We might want to revisit these decisions at some point.
|
||||
float Coeff = 1.0f;
|
||||
const float epsilon = 0.001f;
|
||||
const PxVec3 delta = cB2w.p - cA2w.p;
|
||||
if(delta.magnitudeSquared()>epsilon*epsilon)
|
||||
{
|
||||
const PxVec3 velocity = gearAxis.cross(delta);
|
||||
if(velocity.magnitudeSquared()>epsilon*epsilon)
|
||||
{
|
||||
const float dp = velocity.dot(rackPrismaticAxis);
|
||||
Coeff = fabsf(dp)>epsilon ? PxSign(dp) : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Px1DConstraint& con = constraints[0];
|
||||
con.linear0 = PxVec3(0.0f);
|
||||
con.linear1 = rackPrismaticAxis * data.ratio*Coeff;
|
||||
con.angular0 = gearAxis;
|
||||
con.angular1 = PxVec3(0.0f);
|
||||
con.geometricError = -Coeff*data.px*data.ratio - data.vangle;
|
||||
con.minImpulse = -PX_MAX_F32;
|
||||
con.maxImpulse = PX_MAX_F32;
|
||||
con.velocityTarget = 0.f;
|
||||
con.solveHint = 0;
|
||||
con.flags = Px1DConstraintFlag::eOUTPUT_FORCE|Px1DConstraintFlag::eANGULAR_CONSTRAINT;
|
||||
con.mods.bounce.restitution = 0.0f;
|
||||
con.mods.bounce.velocityThreshold = 0.0f;
|
||||
return 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gRackAndPinionJointShaders = { RackAndPinionJointSolverPrep, RackAndPinionJointVisualize, PxConstraintFlag::eALWAYS_UPDATE };
|
||||
|
||||
PxConstraintSolverPrep RackAndPinionJoint::getPrep() const { return gRackAndPinionJointShaders.solverPrep; }
|
||||
|
||||
PxRackAndPinionJoint* physx::PxRackAndPinionJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxRackAndPinionJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxRackAndPinionJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxRackAndPinionJointCreate: at least one actor must be dynamic");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxRackAndPinionJointCreate: actors must be different");
|
||||
|
||||
return createJointT<RackAndPinionJoint, RackAndPinionJointData>(physics, actor0, localFrame0, actor1, localFrame1, gRackAndPinionJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void RackAndPinionJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gRackAndPinionJointShaders);
|
||||
|
||||
RackAndPinionJointData* data = static_cast<RackAndPinionJointData*>(mData);
|
||||
context.translatePxBase(data->hingeJoint);
|
||||
context.translatePxBase(data->prismaticJoint);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<RackAndPinionJoint>(RackAndPinionJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxRackAndPinionJoint& j = static_cast<PxRackAndPinionJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRackAndPinionJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eRACK_AND_PINION);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRackAndPinionJoint, ratio, j, joint.getRatio())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
90
engine/third_party/physx/source/physxextensions/src/ExtRackAndPinionJoint.h
vendored
Normal file
90
engine/third_party/physx/source/physxextensions/src/ExtRackAndPinionJoint.h
vendored
Normal 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 EXT_RACK_AND_PINION_JOINT_H
|
||||
#define EXT_RACK_AND_PINION_JOINT_H
|
||||
|
||||
#include "extensions/PxRackAndPinionJoint.h"
|
||||
#include "ExtJoint.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxRackAndPinionJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct RackAndPinionJointData : public JointData
|
||||
{
|
||||
const PxBase* hingeJoint;
|
||||
const PxBase* prismaticJoint;
|
||||
float ratio;
|
||||
float px;
|
||||
float vangle;
|
||||
};
|
||||
|
||||
typedef JointT<PxRackAndPinionJoint, RackAndPinionJointData, PxRackAndPinionJointGeneratedValues> RackAndPinionJointT;
|
||||
|
||||
class RackAndPinionJoint : public RackAndPinionJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
RackAndPinionJoint(PxBaseFlags baseFlags) : RackAndPinionJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static RackAndPinionJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<RackAndPinionJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
RackAndPinionJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxRackAndPinionJoint
|
||||
virtual bool setJoints(const PxBase* hinge, const PxBase* prismatic) PX_OVERRIDE;
|
||||
virtual void getJoints(const PxBase*& hinge, const PxBase*& prismatic) const PX_OVERRIDE;
|
||||
virtual void setRatio(float ratio) PX_OVERRIDE;
|
||||
virtual float getRatio() const PX_OVERRIDE;
|
||||
virtual bool setData(PxU32 nbRackTeeth, PxU32 nbPinionTeeth, float rackLength) PX_OVERRIDE;
|
||||
//~PxRackAndPinionJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual void* prepareData() PX_OVERRIDE
|
||||
{
|
||||
updateError();
|
||||
return mData;
|
||||
}
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
//~PxConstraintConnector
|
||||
|
||||
private:
|
||||
float mVirtualAngle0;
|
||||
float mPersistentAngle0;
|
||||
bool mInitDone;
|
||||
|
||||
void updateError();
|
||||
void resetError();
|
||||
};
|
||||
} // namespace Ext
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
319
engine/third_party/physx/source/physxextensions/src/ExtRaycastCCD.cpp
vendored
Normal file
319
engine/third_party/physx/source/physxextensions/src/ExtRaycastCCD.cpp
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
// 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 "geometry/PxBoxGeometry.h"
|
||||
#include "geometry/PxSphereGeometry.h"
|
||||
#include "geometry/PxCapsuleGeometry.h"
|
||||
#include "geometry/PxConvexMeshGeometry.h"
|
||||
#include "geometry/PxConvexMesh.h"
|
||||
#include "extensions/PxShapeExt.h"
|
||||
#include "extensions/PxRaycastCCD.h"
|
||||
#include "PxScene.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
|
||||
#include "foundation/PxArray.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class RaycastCCDManagerInternal
|
||||
{
|
||||
PX_NOCOPY(RaycastCCDManagerInternal)
|
||||
public:
|
||||
RaycastCCDManagerInternal(PxScene* scene) : mScene(scene) {}
|
||||
~RaycastCCDManagerInternal(){}
|
||||
|
||||
bool registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape);
|
||||
bool unregisterRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape);
|
||||
|
||||
void doRaycastCCD(bool doDynamicDynamicCCD);
|
||||
|
||||
struct CCDObject
|
||||
{
|
||||
PX_FORCE_INLINE CCDObject(PxRigidDynamic* actor, PxShape* shape, const PxVec3& witness) : mActor(actor), mShape(shape), mWitness(witness) {}
|
||||
PxRigidDynamic* mActor;
|
||||
PxShape* mShape;
|
||||
PxVec3 mWitness;
|
||||
};
|
||||
|
||||
private:
|
||||
PxScene* mScene;
|
||||
physx::PxArray<CCDObject> mObjects;
|
||||
};
|
||||
}
|
||||
|
||||
static PxVec3 getShapeCenter(PxShape* shape, const PxTransform& pose)
|
||||
{
|
||||
PxVec3 offset(0.0f);
|
||||
const PxGeometry& geom = shape->getGeometry();
|
||||
if(geom.getType()==PxGeometryType::eCONVEXMESH)
|
||||
{
|
||||
const PxConvexMeshGeometry& geometry = static_cast<const PxConvexMeshGeometry&>(geom);
|
||||
|
||||
PxReal mass;
|
||||
PxMat33 localInertia;
|
||||
PxVec3 localCenterOfMass;
|
||||
geometry.convexMesh->getMassInformation(mass, localInertia, localCenterOfMass);
|
||||
|
||||
offset += localCenterOfMass;
|
||||
}
|
||||
return pose.transform(offset);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxVec3 getShapeCenter(PxRigidActor* actor, PxShape* shape)
|
||||
{
|
||||
const PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
|
||||
return getShapeCenter(shape, pose);
|
||||
}
|
||||
|
||||
static PxReal computeInternalRadius(PxRigidActor* actor, PxShape* shape, const PxVec3& dir)
|
||||
{
|
||||
const PxBounds3 bounds = PxShapeExt::getWorldBounds(*shape, *actor);
|
||||
const PxReal diagonal = (bounds.maximum - bounds.minimum).magnitude();
|
||||
const PxReal offsetFromOrigin = diagonal * 2.0f;
|
||||
|
||||
PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
|
||||
|
||||
PxReal internalRadius = 0.0f;
|
||||
const PxReal length = offsetFromOrigin*2.0f;
|
||||
|
||||
const PxGeometry& geom = shape->getGeometry();
|
||||
switch(geom.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
{
|
||||
const PxSphereGeometry& geometry = static_cast<const PxSphereGeometry&>(geom);
|
||||
internalRadius = geometry.radius;
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eBOX:
|
||||
case PxGeometryType::eCAPSULE:
|
||||
{
|
||||
pose.p = PxVec3(0.0f);
|
||||
const PxVec3 virtualOrigin = pose.p + dir * offsetFromOrigin;
|
||||
|
||||
PxRaycastHit hit;
|
||||
PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry(), pose, length, PxHitFlags(0), 1, &hit);
|
||||
PX_UNUSED(nbHits);
|
||||
PX_ASSERT(nbHits);
|
||||
|
||||
internalRadius = offsetFromOrigin - hit.distance;
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
PxVec3 shapeCenter = getShapeCenter(shape, pose);
|
||||
shapeCenter -= pose.p;
|
||||
pose.p = PxVec3(0.0f);
|
||||
|
||||
const PxVec3 virtualOrigin = shapeCenter + dir * offsetFromOrigin;
|
||||
PxRaycastHit hit;
|
||||
PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry(), pose, length, PxHitFlags(0), 1, &hit);
|
||||
PX_UNUSED(nbHits);
|
||||
PX_ASSERT(nbHits);
|
||||
|
||||
internalRadius = offsetFromOrigin - hit.distance;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return internalRadius;
|
||||
}
|
||||
|
||||
class CCDRaycastFilterCallback : public PxQueryFilterCallback
|
||||
{
|
||||
public:
|
||||
CCDRaycastFilterCallback(PxRigidActor* actor, PxShape* shape) : mActor(actor), mShape(shape){}
|
||||
|
||||
PxRigidActor* mActor;
|
||||
PxShape* mShape;
|
||||
|
||||
virtual PxQueryHitType::Enum preFilter(const PxFilterData&, const PxShape* shape, const PxRigidActor* actor, PxHitFlags&)
|
||||
{
|
||||
if(mActor==actor && mShape==shape)
|
||||
return PxQueryHitType::eNONE;
|
||||
return PxQueryHitType::eBLOCK;
|
||||
}
|
||||
|
||||
virtual PxQueryHitType::Enum postFilter(const PxFilterData&, const PxQueryHit&, const PxShape*, const PxRigidActor*)
|
||||
{
|
||||
return PxQueryHitType::eNONE;
|
||||
}
|
||||
};
|
||||
|
||||
static bool CCDRaycast(PxScene* scene, PxRigidActor* actor, PxShape* shape, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, PxRaycastHit& hit, bool dyna_dyna)
|
||||
{
|
||||
const PxQueryFlags qf(dyna_dyna ? PxQueryFlags(PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC|PxQueryFlag::ePREFILTER) : PxQueryFlags(PxQueryFlag::eSTATIC));
|
||||
const PxQueryFilterData filterData(PxFilterData(), qf);
|
||||
|
||||
CCDRaycastFilterCallback CB(actor, shape);
|
||||
|
||||
PxRaycastBuffer buf1;
|
||||
scene->raycast(origin, unitDir, distance, buf1, PxHitFlags(0), filterData, &CB);
|
||||
hit = buf1.block;
|
||||
return buf1.hasBlock;
|
||||
}
|
||||
|
||||
static PxRigidDynamic* canDoCCD(PxRigidActor& actor, PxShape* /*shape*/)
|
||||
{
|
||||
if(actor.getConcreteType()!=PxConcreteType::eRIGID_DYNAMIC)
|
||||
return NULL; // PT: no need to do it for statics
|
||||
PxRigidDynamic* dyna = static_cast<PxRigidDynamic*>(&actor);
|
||||
|
||||
const PxU32 nbShapes = dyna->getNbShapes();
|
||||
if(nbShapes!=1)
|
||||
return NULL; // PT: only works with simple actors for now
|
||||
|
||||
if(dyna->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
|
||||
return NULL; // PT: no need to do it for kinematics
|
||||
|
||||
return dyna;
|
||||
}
|
||||
|
||||
static bool doRaycastCCD(PxScene* scene, const RaycastCCDManagerInternal::CCDObject& object, PxTransform& newPose, PxVec3& newShapeCenter, bool dyna_dyna)
|
||||
{
|
||||
PxRigidDynamic* dyna = canDoCCD(*object.mActor, object.mShape);
|
||||
if(!dyna)
|
||||
return true;
|
||||
|
||||
bool updateCCDWitness = true;
|
||||
|
||||
const PxVec3 offset = newPose.p - newShapeCenter;
|
||||
const PxVec3& origin = object.mWitness;
|
||||
const PxVec3& dest = newShapeCenter;
|
||||
|
||||
PxVec3 dir = dest - origin;
|
||||
const PxReal length = dir.magnitude();
|
||||
if(length!=0.0f)
|
||||
{
|
||||
dir /= length;
|
||||
|
||||
const PxReal internalRadius = computeInternalRadius(object.mActor, object.mShape, dir);
|
||||
|
||||
PxRaycastHit hit;
|
||||
if(internalRadius!=0.0f && CCDRaycast(scene, object.mActor, object.mShape, origin, dir, length, hit, dyna_dyna))
|
||||
{
|
||||
updateCCDWitness = false;
|
||||
|
||||
const PxReal radiusLimit = internalRadius * 0.75f;
|
||||
if(hit.distance>radiusLimit)
|
||||
{
|
||||
newShapeCenter = origin + dir * (hit.distance - radiusLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hit.actor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC)
|
||||
return true;
|
||||
|
||||
newShapeCenter = origin;
|
||||
}
|
||||
|
||||
newPose.p = offset + newShapeCenter;
|
||||
const PxTransform shapeLocalPose = object.mShape->getLocalPose();
|
||||
const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse();
|
||||
const PxTransform newGlobalPose = newPose * inverseShapeLocalPose;
|
||||
dyna->setGlobalPose(newGlobalPose);
|
||||
}
|
||||
}
|
||||
return updateCCDWitness;
|
||||
}
|
||||
|
||||
bool RaycastCCDManagerInternal::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
|
||||
{
|
||||
if(!actor || !shape)
|
||||
return false;
|
||||
|
||||
mObjects.pushBack(CCDObject(actor, shape, getShapeCenter(actor, shape)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RaycastCCDManagerInternal::unregisterRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
|
||||
{
|
||||
if(!actor || !shape)
|
||||
return false;
|
||||
|
||||
const PxU32 nbObjects = mObjects.size();
|
||||
for(PxU32 i=0;i<nbObjects;i++)
|
||||
{
|
||||
if(mObjects[i].mActor==actor && mObjects[i].mShape==shape)
|
||||
{
|
||||
mObjects[i] = mObjects[nbObjects-1];
|
||||
mObjects.popBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RaycastCCDManagerInternal::doRaycastCCD(bool doDynamicDynamicCCD)
|
||||
{
|
||||
const PxU32 nbObjects = mObjects.size();
|
||||
for(PxU32 i=0;i<nbObjects;i++)
|
||||
{
|
||||
CCDObject& object = mObjects[i];
|
||||
|
||||
if(object.mActor->isSleeping())
|
||||
continue;
|
||||
|
||||
PxTransform newPose = PxShapeExt::getGlobalPose(*object.mShape, *object.mActor);
|
||||
PxVec3 newShapeCenter = getShapeCenter(object.mShape, newPose);
|
||||
|
||||
if(::doRaycastCCD(mScene, object, newPose, newShapeCenter, doDynamicDynamicCCD))
|
||||
object.mWitness = newShapeCenter;
|
||||
}
|
||||
}
|
||||
|
||||
RaycastCCDManager::RaycastCCDManager(PxScene* scene)
|
||||
{
|
||||
mImpl = new RaycastCCDManagerInternal(scene);
|
||||
}
|
||||
|
||||
RaycastCCDManager::~RaycastCCDManager()
|
||||
{
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
bool RaycastCCDManager::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
|
||||
{
|
||||
return mImpl->registerRaycastCCDObject(actor, shape);
|
||||
}
|
||||
|
||||
bool RaycastCCDManager::unregisterRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
|
||||
{
|
||||
return mImpl->unregisterRaycastCCDObject(actor, shape);
|
||||
}
|
||||
|
||||
void RaycastCCDManager::doRaycastCCD(bool doDynamicDynamicCCD)
|
||||
{
|
||||
mImpl->doRaycastCCD(doDynamicDynamicCCD);
|
||||
}
|
||||
438
engine/third_party/physx/source/physxextensions/src/ExtRemeshingExt.cpp
vendored
Normal file
438
engine/third_party/physx/source/physxextensions/src/ExtRemeshingExt.cpp
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
// 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/PxRemeshingExt.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static void assignTriangle(PxArray<PxU32>& triangles, PxU32 triIndex, PxU32 a, PxU32 b, PxU32 c)
|
||||
{
|
||||
triangles[3 * triIndex] = a;
|
||||
triangles[3 * triIndex + 1] = b;
|
||||
triangles[3 * triIndex + 2] = c;
|
||||
}
|
||||
|
||||
static void addTriangle(PxArray<PxU32>& triangles, PxU32 a, PxU32 b, PxU32 c)
|
||||
{
|
||||
triangles.pushBack(a);
|
||||
triangles.pushBack(b);
|
||||
triangles.pushBack(c);
|
||||
}
|
||||
|
||||
static void subdivideTriangle(int i, int ab, int bc, int ac, PxArray<PxU32>& triangles, PxArray<PxVec3>& points)
|
||||
{
|
||||
PxU32 tri[3] = { triangles[3 * i],triangles[3 * i + 1],triangles[3 * i + 2] };
|
||||
if (ab >= 0 && bc >= 0 && ac >= 0)
|
||||
{
|
||||
addTriangle(triangles, tri[0], ab, ac);
|
||||
addTriangle(triangles, tri[1], bc, ab);
|
||||
addTriangle(triangles, tri[2], ac, bc);
|
||||
assignTriangle(triangles, i, ab, bc, ac);
|
||||
}
|
||||
else if (ac >= 0 && ab >= 0)
|
||||
{
|
||||
float dB = (points[ac] - points[tri[1]]).magnitudeSquared();
|
||||
float dC = (points[ab] - points[tri[2]]).magnitudeSquared();
|
||||
if (dB < dC)
|
||||
{
|
||||
addTriangle(triangles, tri[1], tri[2], ac);
|
||||
addTriangle(triangles, tri[1], ac, ab);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTriangle(triangles, tri[1], tri[2], ab);
|
||||
addTriangle(triangles, tri[2], ac, ab);
|
||||
}
|
||||
assignTriangle(triangles, i, tri[0], ab, ac);
|
||||
}
|
||||
else if (ab >= 0 && bc >= 0)
|
||||
{
|
||||
float dA = (points[bc] - points[tri[0]]).magnitudeSquared();
|
||||
float dC = (points[ab] - points[tri[2]]).magnitudeSquared();
|
||||
if (dC < dA)
|
||||
{
|
||||
addTriangle(triangles, tri[2], tri[0], ab);
|
||||
addTriangle(triangles, tri[2], ab, bc);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTriangle(triangles, tri[2], tri[0], bc);
|
||||
addTriangle(triangles, tri[0], ab, bc);
|
||||
}
|
||||
assignTriangle(triangles, i, tri[1], bc, ab);
|
||||
}
|
||||
else if (bc >= 0 && ac >= 0)
|
||||
{
|
||||
float dA = (points[bc] - points[tri[0]]).magnitudeSquared();
|
||||
float dB = (points[ac] - points[tri[1]]).magnitudeSquared();
|
||||
if (dA < dB)
|
||||
{
|
||||
addTriangle(triangles, tri[0], tri[1], bc);
|
||||
addTriangle(triangles, tri[0], bc, ac);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTriangle(triangles, tri[0], tri[1], ac);
|
||||
addTriangle(triangles, tri[1], bc, ac);
|
||||
}
|
||||
assignTriangle(triangles, i, tri[2], ac, bc);
|
||||
}
|
||||
else if (ab >= 0)
|
||||
{
|
||||
addTriangle(triangles, tri[1], tri[2], ab);
|
||||
assignTriangle(triangles, i, tri[2], tri[0], ab);
|
||||
}
|
||||
else if (bc >= 0)
|
||||
{
|
||||
addTriangle(triangles, tri[2], tri[0], bc);
|
||||
assignTriangle(triangles, i, tri[0], tri[1], bc);
|
||||
}
|
||||
else if (ac >= 0)
|
||||
{
|
||||
addTriangle(triangles, tri[1], tri[2], ac);
|
||||
assignTriangle(triangles, i, tri[0], tri[1], ac);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU64 key(PxU32 a, PxU32 b)
|
||||
{
|
||||
if (a < b)
|
||||
return ((PxU64(a)) << 32) | (PxU64(b));
|
||||
else
|
||||
return ((PxU64(b)) << 32) | (PxU64(a));
|
||||
}
|
||||
|
||||
static void checkEdge(PxU32 a, PxU32 b, PxHashMap<PxU64, PxI32>& edges, PxArray<PxVec3>& points, PxReal maxEdgeLength)
|
||||
{
|
||||
if ((points[a] - points[b]).magnitudeSquared() < maxEdgeLength * maxEdgeLength)
|
||||
return;
|
||||
|
||||
PxU64 k = key(a, b);
|
||||
if (edges.find(k))
|
||||
return;
|
||||
|
||||
edges.insert(k, points.size());
|
||||
points.pushBack(0.5f * (points[a] + points[b]));
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxI32 getEdge(PxU32 a, PxU32 b, PxHashMap<PxU64, PxI32>& edges)
|
||||
{
|
||||
if (const PxPair<const PxU64, PxI32>* ptr = edges.find(key(a, b)))
|
||||
return ptr->second;
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Info
|
||||
{
|
||||
PxI32 StartIndex;
|
||||
PxI32 Count;
|
||||
|
||||
Info(PxI32 startIndex, PxI32 count)
|
||||
{
|
||||
StartIndex = startIndex;
|
||||
Count = count;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void checkEdge(PxU32 a, PxU32 b, PxHashMap<PxU64, Info>& edges, PxArray<PxVec3>& points, PxReal maxEdgeLength)
|
||||
{
|
||||
if (a > b)
|
||||
PxSwap(a, b);
|
||||
|
||||
PxReal l = (points[a] - points[b]).magnitudeSquared();
|
||||
if (l < maxEdgeLength * maxEdgeLength)
|
||||
return;
|
||||
|
||||
l = PxSqrt(l);
|
||||
|
||||
PxU32 numSubdivisions = (PxU32)(l / maxEdgeLength);
|
||||
if (numSubdivisions <= 1)
|
||||
return;
|
||||
|
||||
PxU64 k = key(a, b);
|
||||
if (edges.find(k))
|
||||
return;
|
||||
|
||||
edges.insert(k, Info(points.size(), numSubdivisions - 1));
|
||||
for (PxU32 i = 1; i < numSubdivisions; ++i)
|
||||
{
|
||||
PxReal p = (PxReal)i / numSubdivisions;
|
||||
points.pushBack((1 - p) * points[a] + p * points[b]);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE Info getEdge(PxU32 a, PxU32 b, PxHashMap<PxU64, Info>& edges)
|
||||
{
|
||||
const PxPair<const PxU64, Info>* value = edges.find(key(a, b));
|
||||
if (value)
|
||||
return value->second;
|
||||
return Info(-1, -1);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void addPoints(PxArray<PxU32>& polygon, const Info& ab, bool reverse)
|
||||
{
|
||||
if (reverse)
|
||||
{
|
||||
for (PxI32 i = ab.Count - 1; i >= 0; --i)
|
||||
polygon.pushBack(ab.StartIndex + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (PxI32 i = 0; i < ab.Count; ++i)
|
||||
polygon.pushBack(ab.StartIndex + i);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxReal angle(const PxVec3& l, const PxVec3& r)
|
||||
{
|
||||
PxReal d = l.dot(r) / PxSqrt(l.magnitudeSquared() * r.magnitudeSquared());
|
||||
if (d <= -1) return PxPi;
|
||||
if (d >= 1) return 0.0f;
|
||||
return PxAcos(d);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxReal evaluateCost(const PxArray<PxVec3>& vertices, PxU32 a, PxU32 b, PxU32 c)
|
||||
{
|
||||
const PxVec3& aa = vertices[a];
|
||||
const PxVec3& bb = vertices[b];
|
||||
const PxVec3& cc = vertices[c];
|
||||
|
||||
PxReal a1 = angle(bb - aa, cc - aa);
|
||||
PxReal a2 = angle(aa - bb, cc - bb);
|
||||
PxReal a3 = angle(aa - cc, bb - cc);
|
||||
|
||||
return PxMax(a1, PxMax(a2, a3));
|
||||
|
||||
//return (aa - bb).magnitude() + (aa - cc).magnitude() + (bb - cc).magnitude();
|
||||
}
|
||||
|
||||
static void triangulateConvex(PxU32 originalTriangleIndexTimes3, PxArray<PxU32>& polygon, const PxArray<PxVec3>& vertices, PxArray<PxU32>& triangles, PxArray<PxI32>& offsets)
|
||||
{
|
||||
offsets.forceSize_Unsafe(0);
|
||||
offsets.reserve(polygon.size());
|
||||
for (PxU32 i = 0; i < polygon.size(); ++i)
|
||||
offsets.pushBack(1);
|
||||
|
||||
PxI32 start = 0;
|
||||
PxU32 count = polygon.size();
|
||||
PxU32 triCounter = 0;
|
||||
while (count > 2)
|
||||
{
|
||||
PxReal minCost = FLT_MAX;
|
||||
PxI32 best = -1;
|
||||
PxI32 i = start;
|
||||
for (PxU32 j = 0; j < count; ++j)
|
||||
{
|
||||
PxU32 a = polygon[i];
|
||||
|
||||
PX_ASSERT(offsets[i] >= 0);
|
||||
|
||||
PxI32 n = (i + offsets[i]) % polygon.size();
|
||||
|
||||
PX_ASSERT(offsets[n] >= 0);
|
||||
|
||||
PxU32 b = polygon[n];
|
||||
PxU32 nn = (n + offsets[n]) % polygon.size();
|
||||
|
||||
PX_ASSERT(offsets[nn] >= 0);
|
||||
|
||||
PxU32 c = polygon[nn];
|
||||
|
||||
PxReal cost = evaluateCost(vertices, a, b, c);
|
||||
if (cost < minCost)
|
||||
{
|
||||
minCost = cost;
|
||||
best = i;
|
||||
}
|
||||
i = n;
|
||||
}
|
||||
{
|
||||
PxU32 a = polygon[best];
|
||||
PxI32 n = (best + offsets[best]) % polygon.size();
|
||||
PxU32 b = polygon[n];
|
||||
PxU32 nn = (n + offsets[n]) % polygon.size();
|
||||
PxU32 c = polygon[nn];
|
||||
|
||||
if (n == start)
|
||||
start += offsets[n];
|
||||
|
||||
offsets[best] += offsets[n];
|
||||
offsets[n] = -1;
|
||||
|
||||
PX_ASSERT(offsets[(best + offsets[best]) % polygon.size()] >= 0);
|
||||
|
||||
if (triCounter == 0)
|
||||
{
|
||||
triangles[originalTriangleIndexTimes3 + 0] = a;
|
||||
triangles[originalTriangleIndexTimes3 + 1] = b;
|
||||
triangles[originalTriangleIndexTimes3 + 2] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
triangles.pushBack(a);
|
||||
triangles.pushBack(b);
|
||||
triangles.pushBack(c);
|
||||
}
|
||||
++triCounter;
|
||||
}
|
||||
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static bool limitMaxEdgeLengthAdaptive(PxArray<PxU32>& triangles, PxArray<PxVec3>& points, PxReal maxEdgeLength, PxArray<PxU32>* triangleMap = NULL)
|
||||
{
|
||||
PxHashMap<PxU64, Info> edges;
|
||||
bool split = false;
|
||||
|
||||
//Analyze edges
|
||||
for (PxU32 i = 0; i < triangles.size(); i += 3)
|
||||
{
|
||||
const PxU32* t = &triangles[i];
|
||||
checkEdge(t[0], t[1], edges, points, maxEdgeLength);
|
||||
checkEdge(t[1], t[2], edges, points, maxEdgeLength);
|
||||
checkEdge(t[0], t[2], edges, points, maxEdgeLength);
|
||||
}
|
||||
|
||||
PxArray<PxI32> offsets;
|
||||
PxArray<PxU32> polygon;
|
||||
|
||||
//Subdivide triangles if required
|
||||
PxU32 size = triangles.size();
|
||||
for (PxU32 i = 0; i < size; i += 3)
|
||||
{
|
||||
const PxU32* t = &triangles[i];
|
||||
Info ab = getEdge(t[0], t[1], edges);
|
||||
Info bc = getEdge(t[1], t[2], edges);
|
||||
Info ac = getEdge(t[0], t[2], edges);
|
||||
if (ab.StartIndex >= 0 || bc.StartIndex >= 0 || ac.StartIndex >= 0)
|
||||
{
|
||||
polygon.forceSize_Unsafe(0);
|
||||
polygon.pushBack(t[0]);
|
||||
addPoints(polygon, ab, t[0] > t[1]);
|
||||
polygon.pushBack(t[1]);
|
||||
addPoints(polygon, bc, t[1] > t[2]);
|
||||
polygon.pushBack(t[2]);
|
||||
addPoints(polygon, ac, t[2] > t[0]);
|
||||
|
||||
PxU32 s = triangles.size();
|
||||
triangulateConvex(i, polygon, points, triangles, offsets);
|
||||
split = true;
|
||||
|
||||
if (triangleMap != NULL)
|
||||
{
|
||||
for (PxU32 j = s; j < triangles.size(); ++j)
|
||||
triangleMap->pushBack((*triangleMap)[i]);
|
||||
}
|
||||
}
|
||||
/*else
|
||||
{
|
||||
result.pushBack(t[0]);
|
||||
result.pushBack(t[1]);
|
||||
result.pushBack(t[2]);
|
||||
if (triangleMap != NULL)
|
||||
triangleMap->pushBack((*triangleMap)[i]);
|
||||
}*/
|
||||
}
|
||||
return split;
|
||||
}
|
||||
|
||||
bool PxRemeshingExt::reduceSliverTriangles(PxArray<PxU32>& triangles, PxArray<PxVec3>& points, PxReal maxEdgeLength, PxU32 maxIterations, PxArray<PxU32>* triangleMap, PxU32 triangleCountThreshold)
|
||||
{
|
||||
bool split = limitMaxEdgeLengthAdaptive(triangles, points, maxEdgeLength, triangleMap);
|
||||
if (!split)
|
||||
return false;
|
||||
|
||||
for (PxU32 i = 1; i < maxIterations; ++i)
|
||||
{
|
||||
split = limitMaxEdgeLengthAdaptive(triangles, points, maxEdgeLength, triangleMap);
|
||||
|
||||
if (!split)
|
||||
break;
|
||||
|
||||
if (triangles.size() >= triangleCountThreshold)
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxRemeshingExt::limitMaxEdgeLength(PxArray<PxU32>& triangles, PxArray<PxVec3>& points, PxReal maxEdgeLength, PxU32 maxIterations, PxArray<PxU32>* triangleMap, PxU32 triangleCountThreshold)
|
||||
{
|
||||
if (triangleMap)
|
||||
{
|
||||
triangleMap->clear();
|
||||
triangleMap->reserve(triangles.size() / 3);
|
||||
for (PxU32 i = 0; i < triangles.size() / 3; ++i)
|
||||
triangleMap->pushBack(i);
|
||||
}
|
||||
|
||||
PxU32 numIndices = triangles.size();
|
||||
PxHashMap<PxU64, PxI32> edges;
|
||||
bool success = true;
|
||||
for (PxU32 k = 0; k < maxIterations && success; ++k)
|
||||
{
|
||||
success = false;
|
||||
edges.clear();
|
||||
|
||||
//Analyze edges
|
||||
for (PxU32 i = 0; i < triangles.size(); i += 3)
|
||||
{
|
||||
checkEdge(triangles[i], triangles[i + 1], edges, points, maxEdgeLength);
|
||||
checkEdge(triangles[i + 1], triangles[i + 2], edges, points, maxEdgeLength);
|
||||
checkEdge(triangles[i], triangles[i + 2], edges, points, maxEdgeLength);
|
||||
}
|
||||
|
||||
//Subdivide triangles if required
|
||||
PxU32 size = triangles.size();
|
||||
for (PxU32 i = 0; i < size; i += 3)
|
||||
{
|
||||
PxI32 ab = getEdge(triangles[i], triangles[i + 1], edges);
|
||||
PxI32 bc = getEdge(triangles[i + 1], triangles[i + 2], edges);
|
||||
PxI32 ac = getEdge(triangles[i], triangles[i + 2], edges);
|
||||
if (ab >= 0 || bc >= 0 || ac >= 0)
|
||||
{
|
||||
PxU32 s = triangles.size();
|
||||
subdivideTriangle(i / 3, ab, bc, ac, triangles, points);
|
||||
success = true;
|
||||
if (triangleMap)
|
||||
{
|
||||
for (PxU32 j = s / 3; j < triangles.size() / 3; ++j)
|
||||
triangleMap->pushBack((*triangleMap)[i / 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (triangles.size() >= triangleCountThreshold)
|
||||
break;
|
||||
}
|
||||
return numIndices != triangles.size();
|
||||
}
|
||||
327
engine/third_party/physx/source/physxextensions/src/ExtRevoluteJoint.cpp
vendored
Normal file
327
engine/third_party/physx/source/physxextensions/src/ExtRevoluteJoint.cpp
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
// 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 "ExtRevoluteJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
RevoluteJoint::RevoluteJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
RevoluteJointT(PxJointConcreteType::eREVOLUTE, actor0, localFrame0, actor1, localFrame1, "RevoluteJointData")
|
||||
{
|
||||
RevoluteJointData* data = static_cast<RevoluteJointData*>(mData);
|
||||
|
||||
data->driveForceLimit = PX_MAX_F32;
|
||||
data->driveVelocity = 0.0f;
|
||||
data->driveGearRatio = 1.0f;
|
||||
data->limit = PxJointAngularLimitPair(-PxPi/2, PxPi/2);
|
||||
data->jointFlags = PxRevoluteJointFlags();
|
||||
}
|
||||
|
||||
PxReal RevoluteJoint::getAngle() const
|
||||
{
|
||||
return getTwistAngle_Internal();
|
||||
}
|
||||
|
||||
PxReal RevoluteJoint::getVelocity() const
|
||||
{
|
||||
return getRelativeAngularVelocity().magnitude();
|
||||
}
|
||||
|
||||
PxJointAngularLimitPair RevoluteJoint::getLimit() const
|
||||
{
|
||||
return data().limit;
|
||||
}
|
||||
|
||||
void RevoluteJoint::setLimit(const PxJointAngularLimitPair& limit)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(limit.isValid(), "PxRevoluteJoint::setLimit: limit invalid");
|
||||
PX_CHECK_AND_RETURN(limit.lower>-PxTwoPi && limit.upper<PxTwoPi , "PxRevoluteJoint::twist limit must be strictly between -2*PI and 2*PI");
|
||||
|
||||
data().limit = limit;
|
||||
markDirty();
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxRevoluteJoint& j = static_cast<PxRevoluteJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitLower, j, limit.lower)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitUpper, j, limit.upper)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
#endif
|
||||
}
|
||||
|
||||
PxReal RevoluteJoint::getDriveVelocity() const
|
||||
{
|
||||
return data().driveVelocity;
|
||||
}
|
||||
|
||||
void RevoluteJoint::setDriveVelocity(PxReal velocity, bool autowake)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(velocity), "PxRevoluteJoint::setDriveVelocity: invalid parameter");
|
||||
data().driveVelocity = velocity;
|
||||
if(autowake)
|
||||
wakeUpActors();
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveVelocity, static_cast<PxRevoluteJoint&>(*this), velocity)
|
||||
}
|
||||
|
||||
PxReal RevoluteJoint::getDriveForceLimit() const
|
||||
{
|
||||
return data().driveForceLimit;
|
||||
}
|
||||
|
||||
void RevoluteJoint::setDriveForceLimit(PxReal forceLimit)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(forceLimit), "PxRevoluteJoint::setDriveForceLimit: invalid parameter");
|
||||
data().driveForceLimit = forceLimit;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveForceLimit, static_cast<PxRevoluteJoint&>(*this), forceLimit)
|
||||
}
|
||||
|
||||
PxReal RevoluteJoint::getDriveGearRatio() const
|
||||
{
|
||||
return data().driveGearRatio;
|
||||
}
|
||||
|
||||
void RevoluteJoint::setDriveGearRatio(PxReal gearRatio)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(PxIsFinite(gearRatio) && gearRatio>0, "PxRevoluteJoint::setDriveGearRatio: invalid parameter");
|
||||
data().driveGearRatio = gearRatio;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveGearRatio, static_cast<PxRevoluteJoint&>(*this), gearRatio)
|
||||
}
|
||||
|
||||
PxRevoluteJointFlags RevoluteJoint::getRevoluteJointFlags() const
|
||||
{
|
||||
return data().jointFlags;
|
||||
}
|
||||
|
||||
void RevoluteJoint::setRevoluteJointFlags(PxRevoluteJointFlags flags)
|
||||
{
|
||||
data().jointFlags = flags;
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, jointFlags, static_cast<PxRevoluteJoint&>(*this), flags)
|
||||
}
|
||||
|
||||
void RevoluteJoint::setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value)
|
||||
{
|
||||
if(value)
|
||||
data().jointFlags |= flag;
|
||||
else
|
||||
data().jointFlags &= ~flag;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, jointFlags, static_cast<PxRevoluteJoint&>(*this), getRevoluteJointFlags())
|
||||
}
|
||||
|
||||
static PxQuat computeTwist(const PxTransform& cA2w, const PxTransform& cB2w)
|
||||
{
|
||||
// PT: following code is the same as this part of the "getAngle" function:
|
||||
// const PxQuat q = getRelativeTransform().q;
|
||||
// PxQuat swing, twist;
|
||||
// PxSeparateSwingTwist(q, swing, twist);
|
||||
// But it's done a little bit more efficiently since we don't need the swing quat.
|
||||
|
||||
// PT: rotation part of "const PxTransform cB2cA = cA2w.transformInv(cB2w);"
|
||||
const PxQuat cB2cAq = cA2w.q.getConjugate() * cB2w.q;
|
||||
|
||||
// PT: twist part of "PxSeparateSwingTwist(cB2cAq,swing,twist)" (more or less)
|
||||
return PxQuat(cB2cAq.x, 0.0f, 0.0f, cB2cAq.w);
|
||||
}
|
||||
|
||||
// PT: this version is similar to the "getAngle" function, but the twist is computed slightly differently.
|
||||
static PX_FORCE_INLINE PxReal computePhi(const PxTransform& cA2w, const PxTransform& cB2w)
|
||||
{
|
||||
PxQuat twist = computeTwist(cA2w, cB2w);
|
||||
twist.normalize();
|
||||
|
||||
PxReal angle = twist.getAngle();
|
||||
if(twist.x<0.0f)
|
||||
angle = -angle;
|
||||
return angle;
|
||||
}
|
||||
|
||||
static void RevoluteJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
|
||||
if((data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED) && (flags & PxConstraintVisualizationFlag::eLIMITS))
|
||||
viz.visualizeAngularLimit(cA2w, data.limit.lower, data.limit.upper);
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 RevoluteJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool useExtendedLimits,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
const PxJointAngularLimitPair& limit = data.limit;
|
||||
|
||||
const bool limitEnabled = data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED;
|
||||
const bool limitIsLocked = limitEnabled && limit.lower >= limit.upper;
|
||||
|
||||
// PT: it is a mistake to use the neighborhood operator since it
|
||||
// prevents us from using the quat's double-cover feature.
|
||||
if(!useExtendedLimits)
|
||||
joint::applyNeighborhoodOperator(cA2w, cB2w);
|
||||
|
||||
PxVec3 ra, rb, axis;
|
||||
ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, PxU32(limitIsLocked ? 7 : 6), ra, rb, &axis);
|
||||
cA2wOut = ra + bA2w.p;
|
||||
cB2wOut = rb + bB2w.p;
|
||||
|
||||
if(limitIsLocked)
|
||||
return ch.getCount();
|
||||
|
||||
if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_ENABLED)
|
||||
{
|
||||
Px1DConstraint* c = ch.getConstraintRow();
|
||||
|
||||
c->solveHint = PxConstraintSolveHint::eNONE;
|
||||
c->linear0 = PxVec3(0.0f);
|
||||
c->angular0 = -axis;
|
||||
c->linear1 = PxVec3(0.0f);
|
||||
c->angular1 = -axis * data.driveGearRatio;
|
||||
c->velocityTarget = data.driveVelocity;
|
||||
c->minImpulse = -data.driveForceLimit;
|
||||
c->maxImpulse = data.driveForceLimit;
|
||||
c->flags |= Px1DConstraintFlag::eANGULAR_CONSTRAINT;
|
||||
if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_FREESPIN)
|
||||
{
|
||||
if(data.driveVelocity > 0.0f)
|
||||
c->minImpulse = 0.0f;
|
||||
if(data.driveVelocity < 0.0f)
|
||||
c->maxImpulse = 0.0f;
|
||||
}
|
||||
c->flags |= Px1DConstraintFlag::eHAS_DRIVE_LIMIT;
|
||||
}
|
||||
|
||||
if(limitEnabled)
|
||||
{
|
||||
const PxReal phi = computePhi(cA2w, cB2w);
|
||||
ch.anglePair(phi, data.limit.lower, data.limit.upper, axis, limit);
|
||||
}
|
||||
|
||||
return ch.getCount();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gRevoluteJointShaders = { RevoluteJointSolverPrep, RevoluteJointVisualize, PxConstraintFlag::Enum(0) };
|
||||
|
||||
PxConstraintSolverPrep RevoluteJoint::getPrep() const { return gRevoluteJointShaders.solverPrep; }
|
||||
|
||||
// PT: for tests / benchmarks
|
||||
PxConstraintSolverPrep getRevoluteJointPrep() { return gRevoluteJointShaders.solverPrep; }
|
||||
|
||||
PxRevoluteJoint* physx::PxRevoluteJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxRevoluteJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxRevoluteJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxRevoluteJointCreate: actors must be different");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxRevoluteJointCreate: at least one actor must be dynamic");
|
||||
|
||||
return createJointT<RevoluteJoint, RevoluteJointData>(physics, actor0, localFrame0, actor1, localFrame1, gRevoluteJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void RevoluteJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gRevoluteJointShaders);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
void RevoluteJoint::updateOmniPvdProperties() const
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
const PxRevoluteJoint& j = static_cast<const PxRevoluteJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, angle, j, getAngle())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, velocity, j, getVelocity())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<RevoluteJoint>(RevoluteJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxRevoluteJoint& j = static_cast<PxRevoluteJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eREVOLUTE);
|
||||
|
||||
PxJointAngularLimitPair limit = joint.getLimit();
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitLower, j, limit.lower)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitUpper, j, limit.upper)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveVelocity, j, joint.getDriveVelocity())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveForceLimit, j, joint.getDriveForceLimit())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, driveGearRatio, j, joint.getDriveGearRatio())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, jointFlags, j, joint.getRevoluteJointFlags())
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, angle, j, joint.getAngle())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxRevoluteJoint, velocity, j, joint.getVelocity())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
96
engine/third_party/physx/source/physxextensions/src/ExtRevoluteJoint.h
vendored
Normal file
96
engine/third_party/physx/source/physxextensions/src/ExtRevoluteJoint.h
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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 EXT_REVOLUTE_JOINT_H
|
||||
#define EXT_REVOLUTE_JOINT_H
|
||||
|
||||
#include "extensions/PxRevoluteJoint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
#include "foundation/PxIntrinsics.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxRevoluteJointGeneratedValues;
|
||||
|
||||
namespace Ext
|
||||
{
|
||||
struct RevoluteJointData : public JointData
|
||||
{
|
||||
PxReal driveVelocity;
|
||||
PxReal driveForceLimit;
|
||||
PxReal driveGearRatio;
|
||||
|
||||
PxJointAngularLimitPair limit;
|
||||
|
||||
PxRevoluteJointFlags jointFlags;
|
||||
// private: // PT: must be public for a benchmark
|
||||
RevoluteJointData(const PxJointAngularLimitPair& pair) : limit(pair) {}
|
||||
};
|
||||
|
||||
typedef JointT<PxRevoluteJoint, RevoluteJointData, PxRevoluteJointGeneratedValues> RevoluteJointT;
|
||||
|
||||
class RevoluteJoint : public RevoluteJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
RevoluteJoint(PxBaseFlags baseFlags) : RevoluteJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static RevoluteJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<RevoluteJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
RevoluteJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxRevoluteJoint
|
||||
virtual PxReal getAngle() const PX_OVERRIDE;
|
||||
virtual PxReal getVelocity() const PX_OVERRIDE;
|
||||
virtual void setLimit(const PxJointAngularLimitPair& limit) PX_OVERRIDE;
|
||||
virtual PxJointAngularLimitPair getLimit() const PX_OVERRIDE;
|
||||
virtual void setDriveVelocity(PxReal velocity, bool autowake = true) PX_OVERRIDE;
|
||||
virtual PxReal getDriveVelocity() const PX_OVERRIDE;
|
||||
virtual void setDriveForceLimit(PxReal forceLimit) PX_OVERRIDE;
|
||||
virtual PxReal getDriveForceLimit() const PX_OVERRIDE;
|
||||
virtual void setDriveGearRatio(PxReal gearRatio) PX_OVERRIDE;
|
||||
virtual PxReal getDriveGearRatio() const PX_OVERRIDE;
|
||||
virtual void setRevoluteJointFlags(PxRevoluteJointFlags flags) PX_OVERRIDE;
|
||||
virtual void setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value) PX_OVERRIDE;
|
||||
virtual PxRevoluteJointFlags getRevoluteJointFlags() const PX_OVERRIDE;
|
||||
//~PxRevoluteJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE;
|
||||
#endif
|
||||
//~PxConstraintConnector
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
89
engine/third_party/physx/source/physxextensions/src/ExtRigidActorExt.cpp
vendored
Normal file
89
engine/third_party/physx/source/physxextensions/src/ExtRigidActorExt.cpp
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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/PxRigidActorExt.h"
|
||||
#include "foundation/PxFPU.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxInlineArray.h"
|
||||
#include "geometry/PxGeometryQuery.h"
|
||||
|
||||
#include "cooking/PxBVHDesc.h"
|
||||
#include "cooking/PxCooking.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxBounds3* PxRigidActorExt::getRigidActorShapeLocalBoundsList(const PxRigidActor& actor, PxU32& numBounds)
|
||||
{
|
||||
const PxU32 numShapes = actor.getNbShapes();
|
||||
if(numShapes == 0)
|
||||
return NULL;
|
||||
|
||||
PxInlineArray<PxShape*, 64> shapes("PxShape*");
|
||||
shapes.resize(numShapes);
|
||||
|
||||
actor.getShapes(shapes.begin(), shapes.size());
|
||||
|
||||
PxU32 numSqShapes = 0;
|
||||
for(PxU32 i=0; i<numShapes; i++)
|
||||
{
|
||||
if(shapes[i]->getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE)
|
||||
numSqShapes++;
|
||||
}
|
||||
|
||||
PxBounds3* bounds = PX_ALLOCATE(PxBounds3, numSqShapes, "PxBounds3");
|
||||
|
||||
numSqShapes = 0;
|
||||
{
|
||||
PX_SIMD_GUARD // PT: external guard because we use PxGeometryQueryFlag::Enum(0) below
|
||||
for(PxU32 i=0; i<numShapes; i++)
|
||||
{
|
||||
if(shapes[i]->getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE)
|
||||
PxGeometryQuery::computeGeomBounds(bounds[numSqShapes++], shapes[i]->getGeometry(), shapes[i]->getLocalPose(), 0.0f, 1.0f, PxGeometryQueryFlag::Enum(0));
|
||||
}
|
||||
}
|
||||
|
||||
numBounds = numSqShapes;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
PxBVH* PxRigidActorExt::createBVHFromActor(PxPhysics& physics, const PxRigidActor& actor)
|
||||
{
|
||||
PxU32 nbBounds = 0;
|
||||
PxBounds3* bounds = PxRigidActorExt::getRigidActorShapeLocalBoundsList(actor, nbBounds);
|
||||
|
||||
PxBVHDesc bvhDesc;
|
||||
bvhDesc.bounds.count = nbBounds;
|
||||
bvhDesc.bounds.data = bounds;
|
||||
bvhDesc.bounds.stride = sizeof(PxBounds3);
|
||||
|
||||
PxBVH* bvh = PxCreateBVH(bvhDesc, physics.getPhysicsInsertionCallback());
|
||||
|
||||
PX_FREE(bounds);
|
||||
return bvh;
|
||||
}
|
||||
|
||||
639
engine/third_party/physx/source/physxextensions/src/ExtRigidBodyExt.cpp
vendored
Normal file
639
engine/third_party/physx/source/physxextensions/src/ExtRigidBodyExt.cpp
vendored
Normal file
@@ -0,0 +1,639 @@
|
||||
// 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 "geometry/PxBoxGeometry.h"
|
||||
#include "geometry/PxSphereGeometry.h"
|
||||
#include "geometry/PxCapsuleGeometry.h"
|
||||
#include "geometry/PxPlaneGeometry.h"
|
||||
#include "geometry/PxConvexMeshGeometry.h"
|
||||
#include "geometry/PxTriangleMeshGeometry.h"
|
||||
#include "geometry/PxHeightFieldGeometry.h"
|
||||
#include "geometry/PxGeometryHelpers.h"
|
||||
#include "geometry/PxConvexMesh.h"
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
#include "extensions/PxRigidBodyExt.h"
|
||||
#include "extensions/PxShapeExt.h"
|
||||
#include "extensions/PxMassProperties.h"
|
||||
#include "PxShape.h"
|
||||
#include "PxScene.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
#include "PxRigidStatic.h"
|
||||
|
||||
#include "ExtInertiaTensor.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxSIMDHelpers.h"
|
||||
|
||||
#include "CmUtils.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Cm;
|
||||
|
||||
static bool computeMassAndDiagInertia(Ext::InertiaTensorComputer& inertiaComp,
|
||||
PxVec3& diagTensor, PxQuat& orient, PxReal& massOut, PxVec3& coM, bool lockCOM, const PxRigidBody& body, const char* errorStr)
|
||||
{
|
||||
// The inertia tensor and center of mass is relative to the actor at this point. Transform to the
|
||||
// body frame directly if CoM is specified, else use computed center of mass
|
||||
if (lockCOM)
|
||||
{
|
||||
inertiaComp.translate(-coM); // base the tensor on user's desired center of mass.
|
||||
}
|
||||
else
|
||||
{
|
||||
//get center of mass - has to be done BEFORE centering.
|
||||
coM = inertiaComp.getCenterOfMass();
|
||||
|
||||
//the computed result now needs to be centered around the computed center of mass:
|
||||
inertiaComp.center();
|
||||
}
|
||||
// The inertia matrix is now based on the body's center of mass desc.massLocalPose.p
|
||||
|
||||
massOut = inertiaComp.getMass();
|
||||
diagTensor = PxDiagonalize(inertiaComp.getInertia(), orient);
|
||||
|
||||
if ((diagTensor.x > 0.0f) && (diagTensor.y > 0.0f) && (diagTensor.z > 0.0f))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_WARNING, PX_FL,
|
||||
"%s: inertia tensor has negative components (ill-conditioned input expected). Approximation for inertia tensor will be used instead.", errorStr);
|
||||
|
||||
// keep center of mass but use the AABB as a crude approximation for the inertia tensor
|
||||
PxBounds3 bounds = body.getWorldBounds();
|
||||
const PxTransform pose = body.getGlobalPose();
|
||||
bounds = PxBounds3::transformFast(pose.getInverse(), bounds);
|
||||
Ext::InertiaTensorComputer it(false);
|
||||
it.setBox(bounds.getExtents());
|
||||
it.scaleDensity(massOut / it.getMass());
|
||||
const PxMat33 inertia = it.getInertia();
|
||||
diagTensor = PxVec3(inertia.column0.x, inertia.column1.y, inertia.column2.z);
|
||||
orient = PxQuat(PxIdentity);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool computeMassAndInertia(Ext::InertiaTensorComputer& inertiaComp, bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, const PxReal* masses, PxU32 densityOrMassCount, bool includeNonSimShapes)
|
||||
{
|
||||
PX_ASSERT(!densities || !masses);
|
||||
PX_ASSERT((densities || masses) && (densityOrMassCount > 0));
|
||||
|
||||
PxInlineArray<PxShape*, 16> shapes("PxShape*"); shapes.resize(body.getNbShapes());
|
||||
|
||||
body.getShapes(shapes.begin(), shapes.size());
|
||||
|
||||
PxU32 validShapeIndex = 0;
|
||||
PxReal currentMassOrDensity;
|
||||
const PxReal* massOrDensityArray;
|
||||
if (densities)
|
||||
{
|
||||
massOrDensityArray = densities;
|
||||
currentMassOrDensity = densities[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
massOrDensityArray = masses;
|
||||
currentMassOrDensity = masses[0];
|
||||
}
|
||||
if (!PxIsFinite(currentMassOrDensity))
|
||||
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "computeMassAndInertia: Provided mass or density has no valid value");
|
||||
|
||||
for(PxU32 i=0; i < shapes.size(); i++)
|
||||
{
|
||||
if ((!(shapes[i]->getFlags() & PxShapeFlag::eSIMULATION_SHAPE)) && (!includeNonSimShapes))
|
||||
continue;
|
||||
|
||||
if (multipleMassOrDensity)
|
||||
{
|
||||
if (validShapeIndex < densityOrMassCount)
|
||||
{
|
||||
currentMassOrDensity = massOrDensityArray[validShapeIndex];
|
||||
|
||||
if (!PxIsFinite(currentMassOrDensity))
|
||||
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "computeMassAndInertia: Provided mass or density has no valid value");
|
||||
}
|
||||
else
|
||||
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "computeMassAndInertia: Not enough mass/density values provided for all (simulation) shapes");
|
||||
}
|
||||
|
||||
Ext::InertiaTensorComputer it(false);
|
||||
|
||||
const PxGeometry& geom = shapes[i]->getGeometry();
|
||||
switch(geom.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE :
|
||||
{
|
||||
const PxSphereGeometry& g = static_cast<const PxSphereGeometry&>(geom);
|
||||
PxTransform temp(shapes[i]->getLocalPose());
|
||||
|
||||
it.setSphere(g.radius, &temp);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eBOX :
|
||||
{
|
||||
const PxBoxGeometry& g = static_cast<const PxBoxGeometry&>(geom);
|
||||
PxTransform temp(shapes[i]->getLocalPose());
|
||||
|
||||
it.setBox(g.halfExtents, &temp);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCAPSULE :
|
||||
{
|
||||
const PxCapsuleGeometry& g = static_cast<const PxCapsuleGeometry&>(geom);
|
||||
PxTransform temp(shapes[i]->getLocalPose());
|
||||
|
||||
it.setCapsule(0, g.radius, g.halfHeight, &temp);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCONVEXCORE:
|
||||
{
|
||||
PxMassProperties mp(shapes[i]->getGeometry());
|
||||
it = Ext::InertiaTensorComputer(mp.inertiaTensor, mp.centerOfMass, mp.mass);
|
||||
it.transform(shapes[i]->getLocalPose());
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCONVEXMESH :
|
||||
{
|
||||
const PxConvexMeshGeometry& g = static_cast<const PxConvexMeshGeometry&>(geom);
|
||||
PxConvexMesh& convMesh = *g.convexMesh;
|
||||
|
||||
PxReal convMass;
|
||||
PxMat33 convInertia;
|
||||
PxVec3 convCoM;
|
||||
convMesh.getMassInformation(convMass, convInertia, convCoM);
|
||||
|
||||
if (!g.scale.isIdentity())
|
||||
{
|
||||
//scale the mass properties
|
||||
convMass *= (g.scale.scale.x * g.scale.scale.y * g.scale.scale.z);
|
||||
convCoM = g.scale.transform(convCoM);
|
||||
convInertia = PxMassProperties::scaleInertia(convInertia, g.scale.rotation, g.scale.scale);
|
||||
}
|
||||
|
||||
it = Ext::InertiaTensorComputer(convInertia, convCoM, convMass);
|
||||
it.transform(shapes[i]->getLocalPose());
|
||||
}
|
||||
break;
|
||||
case PxGeometryType::eCUSTOM:
|
||||
{
|
||||
PxMassProperties mp(shapes[i]->getGeometry());
|
||||
it = Ext::InertiaTensorComputer(mp.inertiaTensor, mp.centerOfMass, mp.mass);
|
||||
it.transform(shapes[i]->getLocalPose());
|
||||
}
|
||||
break;
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
{
|
||||
const PxTriangleMeshGeometry& g = static_cast<const PxTriangleMeshGeometry&>(geom);
|
||||
|
||||
PxReal mass;
|
||||
PxMat33 inertia;
|
||||
PxVec3 centerOfMass;
|
||||
g.triangleMesh->getMassInformation(mass, inertia, centerOfMass);
|
||||
|
||||
if (!g.scale.isIdentity())
|
||||
{
|
||||
//scale the mass properties
|
||||
mass *= (g.scale.scale.x * g.scale.scale.y * g.scale.scale.z);
|
||||
centerOfMass = g.scale.transform(centerOfMass);
|
||||
inertia = PxMassProperties::scaleInertia(inertia, g.scale.rotation, g.scale.scale);
|
||||
}
|
||||
|
||||
it = Ext::InertiaTensorComputer(inertia, centerOfMass, mass);
|
||||
|
||||
it.transform(shapes[i]->getLocalPose());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
return PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "computeMassAndInertia: Dynamic actor with illegal collision shapes");
|
||||
}
|
||||
}
|
||||
|
||||
if (densities)
|
||||
it.scaleDensity(currentMassOrDensity);
|
||||
else if (multipleMassOrDensity) // mass per shape -> need to scale density per shape
|
||||
it.scaleDensity(currentMassOrDensity / it.getMass());
|
||||
|
||||
inertiaComp.add(it);
|
||||
|
||||
validShapeIndex++;
|
||||
}
|
||||
|
||||
if (validShapeIndex && masses && (!multipleMassOrDensity)) // at least one simulation shape and single mass for all shapes -> scale density at the end
|
||||
inertiaComp.scaleDensity(currentMassOrDensity / inertiaComp.getMass());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool updateMassAndInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
bool success;
|
||||
|
||||
// default values in case there were no shapes
|
||||
PxReal massOut = 1.0f;
|
||||
PxVec3 diagTensor(1.0f);
|
||||
PxQuat orient(PxIdentity);
|
||||
bool lockCom = massLocalPose != NULL;
|
||||
PxVec3 com = lockCom ? *massLocalPose : PxVec3(0);
|
||||
const char* errorStr = "PxRigidBodyExt::updateMassAndInertia";
|
||||
|
||||
if (densities && densityCount)
|
||||
{
|
||||
Ext::InertiaTensorComputer inertiaComp(true);
|
||||
if(computeMassAndInertia(inertiaComp, multipleMassOrDensity, body, densities, NULL, densityCount, includeNonSimShapes))
|
||||
{
|
||||
if(inertiaComp.getMass()!=0 && computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr))
|
||||
success = true;
|
||||
else
|
||||
success = false; // body with no shapes provided or computeMassAndDiagInertia() failed
|
||||
}
|
||||
else
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr);
|
||||
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"%s: No density specified, setting mass to 1 and inertia to (1,1,1)", errorStr);
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
PX_ASSERT(orient.isFinite());
|
||||
PX_ASSERT(diagTensor.isFinite());
|
||||
PX_ASSERT(PxIsFinite(massOut));
|
||||
|
||||
body.setMass(massOut);
|
||||
body.setMassSpaceInertiaTensor(diagTensor);
|
||||
body.setCMassLocalPose(PxTransform(com, orient));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
return ::updateMassAndInertia(true, body, densities, densityCount, massLocalPose, includeNonSimShapes);
|
||||
}
|
||||
|
||||
bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, PxReal density, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
return ::updateMassAndInertia(false, body, &density, 1, massLocalPose, includeNonSimShapes);
|
||||
}
|
||||
|
||||
static bool setMassAndUpdateInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
bool success;
|
||||
|
||||
// default values in case there were no shapes
|
||||
PxReal massOut = 1.0f;
|
||||
PxVec3 diagTensor(1.0f);
|
||||
PxQuat orient(PxIdentity);
|
||||
bool lockCom = massLocalPose != NULL;
|
||||
PxVec3 com = lockCom ? *massLocalPose : PxVec3(0);
|
||||
const char* errorStr = "PxRigidBodyExt::setMassAndUpdateInertia";
|
||||
|
||||
if(masses && massCount)
|
||||
{
|
||||
Ext::InertiaTensorComputer inertiaComp(true);
|
||||
if(computeMassAndInertia(inertiaComp, multipleMassOrDensity, body, NULL, masses, massCount, includeNonSimShapes))
|
||||
{
|
||||
success = true;
|
||||
|
||||
if (inertiaComp.getMass()!=0 && !computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr))
|
||||
success = false; // computeMassAndDiagInertia() failed (mass zero?)
|
||||
|
||||
if (massCount == 1)
|
||||
massOut = masses[0]; // to cover special case where body has no simulation shape
|
||||
}
|
||||
else
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr);
|
||||
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"%s: No mass specified, setting mass to 1 and inertia to (1,1,1)", errorStr);
|
||||
success = false;
|
||||
}
|
||||
|
||||
PX_ASSERT(orient.isFinite());
|
||||
PX_ASSERT(diagTensor.isFinite());
|
||||
|
||||
body.setMass(massOut);
|
||||
body.setMassSpaceInertiaTensor(diagTensor);
|
||||
body.setCMassLocalPose(PxTransform(com, orient));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
return ::setMassAndUpdateInertia(true, body, masses, massCount, massLocalPose, includeNonSimShapes);
|
||||
}
|
||||
|
||||
bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, PxReal mass, const PxVec3* massLocalPose, bool includeNonSimShapes)
|
||||
{
|
||||
return ::setMassAndUpdateInertia(false, body, &mass, 1, massLocalPose, includeNonSimShapes);
|
||||
}
|
||||
|
||||
PxMassProperties PxRigidBodyExt::computeMassPropertiesFromShapes(const PxShape* const* shapes, PxU32 shapeCount)
|
||||
{
|
||||
PxInlineArray<PxMassProperties, 16> massProps;
|
||||
massProps.reserve(shapeCount);
|
||||
PxInlineArray<PxTransform, 16> localTransforms;
|
||||
localTransforms.reserve(shapeCount);
|
||||
|
||||
for(PxU32 shapeIdx=0; shapeIdx < shapeCount; shapeIdx++)
|
||||
{
|
||||
const PxShape* shape = shapes[shapeIdx];
|
||||
PxMassProperties mp(shape->getGeometry());
|
||||
massProps.pushBack(mp);
|
||||
localTransforms.pushBack(shape->getLocalPose());
|
||||
}
|
||||
|
||||
return PxMassProperties::sum(massProps.begin(), localTransforms.begin(), shapeCount);
|
||||
}
|
||||
|
||||
PX_INLINE void addForceAtPosInternal(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
|
||||
{
|
||||
if(mode == PxForceMode::eACCELERATION || mode == PxForceMode::eVELOCITY_CHANGE)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL,
|
||||
"PxRigidBodyExt::addForce methods do not support eACCELERATION or eVELOCITY_CHANGE modes");
|
||||
return;
|
||||
}
|
||||
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
|
||||
|
||||
const PxVec3 torque = (pos - centerOfMass).cross(force);
|
||||
body.addForce(force, mode, wakeup);
|
||||
body.addTorque(torque, mode, wakeup);
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::addForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
|
||||
{
|
||||
addForceAtPosInternal(body, force, pos, mode, wakeup);
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::addForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
|
||||
{
|
||||
//transform pos to world space
|
||||
const PxVec3 globalForcePos = body.getGlobalPose().transform(pos);
|
||||
|
||||
addForceAtPosInternal(body, force, globalForcePos, mode, wakeup);
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::addLocalForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
|
||||
{
|
||||
const PxVec3 globalForce = body.getGlobalPose().rotate(force);
|
||||
|
||||
addForceAtPosInternal(body, globalForce, pos, mode, wakeup);
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::addLocalForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
|
||||
{
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxVec3 globalForcePos = globalPose.transform(pos);
|
||||
const PxVec3 globalForce = globalPose.rotate(force);
|
||||
|
||||
addForceAtPosInternal(body, globalForce, globalForcePos, mode, wakeup);
|
||||
}
|
||||
|
||||
PX_INLINE PxVec3 getVelocityAtPosInternal(const PxRigidBody& body, const PxVec3& point)
|
||||
{
|
||||
PxVec3 velocity = body.getLinearVelocity();
|
||||
velocity += body.getAngularVelocity().cross(point);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
|
||||
PxVec3 PxRigidBodyExt::getVelocityAtPos(const PxRigidBody& body, const PxVec3& point)
|
||||
{
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
|
||||
const PxVec3 rpoint = point - centerOfMass;
|
||||
|
||||
return getVelocityAtPosInternal(body, rpoint);
|
||||
}
|
||||
|
||||
PxVec3 PxRigidBodyExt::getLocalVelocityAtLocalPos(const PxRigidBody& body, const PxVec3& point)
|
||||
{
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
|
||||
const PxVec3 rpoint = globalPose.transform(point) - centerOfMass;
|
||||
|
||||
return getVelocityAtPosInternal(body, rpoint);
|
||||
}
|
||||
|
||||
PxVec3 PxRigidBodyExt::getVelocityAtOffset(const PxRigidBody& body, const PxVec3& point)
|
||||
{
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxVec3 centerOfMass = globalPose.rotate(body.getCMassLocalPose().p);
|
||||
const PxVec3 rpoint = point - centerOfMass;
|
||||
|
||||
return getVelocityAtPosInternal(body, rpoint);
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale,
|
||||
const PxReal invInertiaScale, PxVec3& linearVelocityChange, PxVec3& angularVelocityChange)
|
||||
{
|
||||
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
|
||||
const PxReal invMass = body.getInvMass() * invMassScale;
|
||||
const PxVec3 invInertiaMS = body.getMassSpaceInvInertiaTensor() * invInertiaScale;
|
||||
|
||||
PxMat33 invInertia;
|
||||
transformInertiaTensor(invInertiaMS, PxMat33Padded(globalPose.q), invInertia);
|
||||
linearVelocityChange = impulse * invMass;
|
||||
const PxVec3 rXI = (point - centerOfMass).cross(impulse);
|
||||
angularVelocityChange = invInertia * rXI;
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::computeLinearAngularImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale,
|
||||
const PxReal invInertiaScale, PxVec3& linearImpulse, PxVec3& angularImpulse)
|
||||
{
|
||||
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
|
||||
linearImpulse = impulse * invMassScale;
|
||||
angularImpulse = (point - centerOfMass).cross(impulse) * invInertiaScale;
|
||||
}
|
||||
|
||||
void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxVec3& impulsiveForce, const PxVec3& impulsiveTorque, PxVec3& deltaLinearVelocity, PxVec3& deltaAngularVelocity)
|
||||
{
|
||||
{
|
||||
const PxF32 recipMass = body.getInvMass();
|
||||
deltaLinearVelocity = impulsiveForce*recipMass;
|
||||
}
|
||||
|
||||
{
|
||||
const PxTransform globalPose = body.getGlobalPose();
|
||||
const PxTransform cmLocalPose = body.getCMassLocalPose();
|
||||
// PT:: tag: scalar transform*transform
|
||||
const PxTransform body2World = globalPose*cmLocalPose;
|
||||
const PxMat33Padded M(body2World.q);
|
||||
|
||||
const PxVec3 recipInertiaBodySpace = body.getMassSpaceInvInertiaTensor();
|
||||
|
||||
PxMat33 recipInertiaWorldSpace;
|
||||
const float axx = recipInertiaBodySpace.x*M(0,0), axy = recipInertiaBodySpace.x*M(1,0), axz = recipInertiaBodySpace.x*M(2,0);
|
||||
const float byx = recipInertiaBodySpace.y*M(0,1), byy = recipInertiaBodySpace.y*M(1,1), byz = recipInertiaBodySpace.y*M(2,1);
|
||||
const float czx = recipInertiaBodySpace.z*M(0,2), czy = recipInertiaBodySpace.z*M(1,2), czz = recipInertiaBodySpace.z*M(2,2);
|
||||
recipInertiaWorldSpace(0,0) = axx*M(0,0) + byx*M(0,1) + czx*M(0,2);
|
||||
recipInertiaWorldSpace(1,1) = axy*M(1,0) + byy*M(1,1) + czy*M(1,2);
|
||||
recipInertiaWorldSpace(2,2) = axz*M(2,0) + byz*M(2,1) + czz*M(2,2);
|
||||
recipInertiaWorldSpace(0,1) = recipInertiaWorldSpace(1,0) = axx*M(1,0) + byx*M(1,1) + czx*M(1,2);
|
||||
recipInertiaWorldSpace(0,2) = recipInertiaWorldSpace(2,0) = axx*M(2,0) + byx*M(2,1) + czx*M(2,2);
|
||||
recipInertiaWorldSpace(1,2) = recipInertiaWorldSpace(2,1) = axy*M(2,0) + byy*M(2,1) + czy*M(2,2);
|
||||
|
||||
deltaAngularVelocity = recipInertiaWorldSpace*(impulsiveTorque);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// Single closest hit compound sweep
|
||||
bool PxRigidBodyExt::linearSweepSingle(
|
||||
PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance,
|
||||
PxHitFlags outputFlags, PxSweepHit& closestHit, PxU32& shapeIndex,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation)
|
||||
{
|
||||
shapeIndex = 0xFFFFffff;
|
||||
PxReal closestDist = distance;
|
||||
PxU32 nbShapes = body.getNbShapes();
|
||||
for(PxU32 i=0; i < nbShapes; i++)
|
||||
{
|
||||
PxShape* shape = NULL;
|
||||
body.getShapes(&shape, 1, i);
|
||||
PX_ASSERT(shape != NULL);
|
||||
PxTransform pose = PxShapeExt::getGlobalPose(*shape, body);
|
||||
PxQueryFilterData fd;
|
||||
fd.flags = filterData.flags;
|
||||
PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3);
|
||||
fd.data = or4 ? filterData.data : shape->getQueryFilterData();
|
||||
|
||||
PxSweepBuffer subHit; // touching hits are not allowed to be returned from the filters
|
||||
scene.sweep(shape->getGeometry(), pose, unitDir, distance, subHit, outputFlags, fd, filterCall, cache, inflation);
|
||||
if (subHit.hasBlock && subHit.block.distance < closestDist)
|
||||
{
|
||||
closestDist = subHit.block.distance;
|
||||
closestHit = subHit.block;
|
||||
shapeIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return (shapeIndex != 0xFFFFffff);
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
// Multiple hits compound sweep
|
||||
// AP: we might be able to improve the return results API but no time for it in 3.3
|
||||
PxU32 PxRigidBodyExt::linearSweepMultiple(
|
||||
PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags,
|
||||
PxSweepHit* hitBuffer, PxU32* hitShapeIndices, PxU32 hitBufferSize, PxSweepHit& block, PxI32& blockingHitShapeIndex,
|
||||
bool& overflow, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation)
|
||||
{
|
||||
overflow = false;
|
||||
blockingHitShapeIndex = -1;
|
||||
|
||||
for (PxU32 i = 0; i < hitBufferSize; i++)
|
||||
hitShapeIndices[i] = 0xFFFFffff;
|
||||
|
||||
PxI32 sumNbResults = 0;
|
||||
|
||||
PxU32 nbShapes = body.getNbShapes();
|
||||
PxF32 shrunkMaxDistance = distance;
|
||||
for(PxU32 i=0; i < nbShapes; i++)
|
||||
{
|
||||
PxShape* shape = NULL;
|
||||
body.getShapes(&shape, 1, i);
|
||||
PX_ASSERT(shape != NULL);
|
||||
PxTransform pose = PxShapeExt::getGlobalPose(*shape, body);
|
||||
PxQueryFilterData fd;
|
||||
fd.flags = filterData.flags;
|
||||
PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3);
|
||||
fd.data = or4 ? filterData.data : shape->getQueryFilterData();
|
||||
|
||||
PxU32 bufSizeLeft = hitBufferSize-sumNbResults;
|
||||
PxSweepHit extraHit;
|
||||
PxSweepBuffer buffer(bufSizeLeft == 0 ? &extraHit : hitBuffer+sumNbResults, bufSizeLeft == 0 ? 1 : hitBufferSize-sumNbResults);
|
||||
scene.sweep(shape->getGeometry(), pose, unitDir, shrunkMaxDistance, buffer, outputFlags, fd, filterCall, cache, inflation);
|
||||
|
||||
// Check and abort on overflow. Assume overflow if result count is bufSize.
|
||||
PxU32 nbNewResults = buffer.getNbTouches();
|
||||
overflow |= (nbNewResults >= bufSizeLeft);
|
||||
if (bufSizeLeft == 0) // this is for when we used the extraHit buffer
|
||||
nbNewResults = 0;
|
||||
|
||||
// set hitShapeIndices for each new non-blocking hit
|
||||
for (PxU32 j = 0; j < nbNewResults; j++)
|
||||
if (sumNbResults + PxU32(j) < hitBufferSize)
|
||||
hitShapeIndices[sumNbResults+j] = i;
|
||||
|
||||
if (buffer.hasBlock) // there's a blocking hit in the most recent sweepMultiple results
|
||||
{
|
||||
// overwrite the return result blocking hit with the new blocking hit if under
|
||||
if (blockingHitShapeIndex == -1 || buffer.block.distance < block.distance)
|
||||
{
|
||||
blockingHitShapeIndex = PxI32(i);
|
||||
block = buffer.block;
|
||||
}
|
||||
|
||||
// Remove all the old touching hits below the new maxDist
|
||||
// sumNbResults is not updated yet at this point
|
||||
// and represents the count accumulated so far excluding the very last query
|
||||
PxI32 nbNewResultsSigned = PxI32(nbNewResults); // need a signed version, see nbNewResultsSigned-- below
|
||||
for (PxI32 j = sumNbResults-1; j >= 0; j--) // iterate over "old" hits (up to shapeIndex-1)
|
||||
if (buffer.block.distance < hitBuffer[j].distance)
|
||||
{
|
||||
// overwrite with last "new" hit
|
||||
PxI32 sourceIndex = PxI32(sumNbResults)+nbNewResultsSigned-1; PX_ASSERT(sourceIndex >= j);
|
||||
hitBuffer[j] = hitBuffer[sourceIndex];
|
||||
hitShapeIndices[j] = hitShapeIndices[sourceIndex];
|
||||
nbNewResultsSigned--; // can get negative, that means we are shifting the last results array
|
||||
}
|
||||
|
||||
sumNbResults += nbNewResultsSigned;
|
||||
} else // if there was no new blocking hit we don't need to do anything special, simply append all results to touch array
|
||||
sumNbResults += nbNewResults;
|
||||
|
||||
PX_ASSERT(sumNbResults >= 0 && sumNbResults <= PxI32(hitBufferSize));
|
||||
}
|
||||
|
||||
return PxU32(sumNbResults);
|
||||
}
|
||||
1482
engine/third_party/physx/source/physxextensions/src/ExtSampling.cpp
vendored
Normal file
1482
engine/third_party/physx/source/physxextensions/src/ExtSampling.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
696
engine/third_party/physx/source/physxextensions/src/ExtSceneQueryExt.cpp
vendored
Normal file
696
engine/third_party/physx/source/physxextensions/src/ExtSceneQueryExt.cpp
vendored
Normal file
@@ -0,0 +1,696 @@
|
||||
// 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/PxSceneQueryExt.h"
|
||||
#include "geometry/PxGeometryHelpers.h"
|
||||
#include "foundation/PxAllocatorCallback.h"
|
||||
#include "CmUtils.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
bool PxSceneQueryExt::raycastAny( const PxScene& scene,
|
||||
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryHit& hit, const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
||||
{
|
||||
PxSceneQueryFilterData fdAny = filterData;
|
||||
fdAny.flags |= PxQueryFlag::eANY_HIT;
|
||||
PxRaycastBuffer buf;
|
||||
scene.raycast(origin, unitDir, distance, buf, PxHitFlag::eANY_HIT, fdAny, filterCall, cache);
|
||||
hit = buf.block;
|
||||
return buf.hasBlock;
|
||||
}
|
||||
|
||||
bool PxSceneQueryExt::raycastSingle(const PxScene& scene,
|
||||
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryFlags outputFlags, PxRaycastHit& hit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
||||
{
|
||||
PxRaycastBuffer buf;
|
||||
PxQueryFilterData fd1 = filterData;
|
||||
scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
|
||||
hit = buf.block;
|
||||
return buf.hasBlock;
|
||||
}
|
||||
|
||||
PxI32 PxSceneQueryExt::raycastMultiple( const PxScene& scene,
|
||||
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryFlags outputFlags,
|
||||
PxRaycastHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache)
|
||||
{
|
||||
PxRaycastBuffer buf(hitBuffer, hitBufferSize);
|
||||
PxQueryFilterData fd1 = filterData;
|
||||
scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
|
||||
blockingHit = buf.hasBlock;
|
||||
if(blockingHit)
|
||||
{
|
||||
if(buf.nbTouches < hitBufferSize)
|
||||
{
|
||||
hitBuffer[buf.nbTouches] = buf.block;
|
||||
return PxI32(buf.nbTouches+1);
|
||||
}
|
||||
else // overflow, drop the last touch
|
||||
{
|
||||
hitBuffer[hitBufferSize-1] = buf.block;
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
// no block
|
||||
return PxI32(buf.nbTouches);
|
||||
}
|
||||
|
||||
bool PxSceneQueryExt::sweepAny( const PxScene& scene,
|
||||
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryFlags queryFlags,
|
||||
PxSceneQueryHit& hit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall,
|
||||
const PxSceneQueryCache* cache,
|
||||
PxReal inflation)
|
||||
{
|
||||
PxSceneQueryFilterData fdAny = filterData;
|
||||
fdAny.flags |= PxQueryFlag::eANY_HIT;
|
||||
PxSweepBuffer buf;
|
||||
scene.sweep(geometry, pose, unitDir, distance, buf, queryFlags|PxHitFlag::eANY_HIT, fdAny, filterCall, cache, inflation);
|
||||
hit = buf.block;
|
||||
return buf.hasBlock;
|
||||
}
|
||||
|
||||
bool PxSceneQueryExt::sweepSingle( const PxScene& scene,
|
||||
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryFlags outputFlags,
|
||||
PxSweepHit& hit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall,
|
||||
const PxSceneQueryCache* cache,
|
||||
PxReal inflation)
|
||||
{
|
||||
PxSweepBuffer buf;
|
||||
PxQueryFilterData fd1 = filterData;
|
||||
scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
|
||||
hit = buf.block;
|
||||
return buf.hasBlock;
|
||||
}
|
||||
|
||||
PxI32 PxSceneQueryExt::sweepMultiple( const PxScene& scene,
|
||||
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
||||
PxSceneQueryFlags outputFlags, PxSweepHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
|
||||
PxReal inflation)
|
||||
{
|
||||
PxQueryFilterData fd1 = filterData;
|
||||
PxSweepBuffer buf(hitBuffer, hitBufferSize);
|
||||
scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
|
||||
blockingHit = buf.hasBlock;
|
||||
if(blockingHit)
|
||||
{
|
||||
if(buf.nbTouches < hitBufferSize)
|
||||
{
|
||||
hitBuffer[buf.nbTouches] = buf.block;
|
||||
return PxI32(buf.nbTouches+1);
|
||||
}
|
||||
else // overflow, drop the last touch
|
||||
{
|
||||
hitBuffer[hitBufferSize-1] = buf.block;
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
// no block
|
||||
return PxI32(buf.nbTouches);
|
||||
}
|
||||
|
||||
PxI32 PxSceneQueryExt::overlapMultiple( const PxScene& scene,
|
||||
const PxGeometry& geometry, const PxTransform& pose,
|
||||
PxOverlapHit* hitBuffer, PxU32 hitBufferSize,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall)
|
||||
{
|
||||
PxQueryFilterData fd1 = filterData;
|
||||
fd1.flags |= PxQueryFlag::eNO_BLOCK;
|
||||
PxOverlapBuffer buf(hitBuffer, hitBufferSize);
|
||||
scene.overlap(geometry, pose, buf, fd1, filterCall);
|
||||
if(buf.hasBlock)
|
||||
{
|
||||
if(buf.nbTouches < hitBufferSize)
|
||||
{
|
||||
hitBuffer[buf.nbTouches] = buf.block;
|
||||
return PxI32(buf.nbTouches+1);
|
||||
}
|
||||
else // overflow, drop the last touch
|
||||
{
|
||||
hitBuffer[hitBufferSize-1] = buf.block;
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
// no block
|
||||
return PxI32(buf.nbTouches);
|
||||
}
|
||||
|
||||
bool PxSceneQueryExt::overlapAny( const PxScene& scene,
|
||||
const PxGeometry& geometry, const PxTransform& pose,
|
||||
PxOverlapHit& hit,
|
||||
const PxSceneQueryFilterData& filterData,
|
||||
PxSceneQueryFilterCallback* filterCall)
|
||||
{
|
||||
PxSceneQueryFilterData fdAny = filterData;
|
||||
fdAny.flags |= (PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK);
|
||||
PxOverlapBuffer buf;
|
||||
scene.overlap(geometry, pose, buf, fdAny, filterCall);
|
||||
hit = buf.block;
|
||||
return buf.hasBlock;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Raycast
|
||||
{
|
||||
PxVec3 origin;
|
||||
PxVec3 unitDir;
|
||||
PxReal distance;
|
||||
PxHitFlags hitFlags;
|
||||
PxQueryFilterData filterData;
|
||||
const PxQueryCache* cache;
|
||||
};
|
||||
struct Sweep
|
||||
{
|
||||
PxGeometryHolder geometry;
|
||||
PxTransform pose;
|
||||
PxVec3 unitDir;
|
||||
PxReal distance;
|
||||
PxHitFlags hitFlags;
|
||||
PxQueryFilterData filterData;
|
||||
const PxQueryCache* cache;
|
||||
PxReal inflation;
|
||||
};
|
||||
struct Overlap
|
||||
{
|
||||
PxGeometryHolder geometry;
|
||||
PxTransform pose;
|
||||
PxQueryFilterData filterData;
|
||||
const PxQueryCache* cache;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename HitType>
|
||||
struct NpOverflowBuffer : PxHitBuffer<HitType>
|
||||
{
|
||||
bool overflow;
|
||||
bool processCalled;
|
||||
PxU32 saveNbTouches;
|
||||
NpOverflowBuffer(HitType* hits, PxU32 count) : PxHitBuffer<HitType>(hits, count), overflow(false), processCalled(false), saveNbTouches(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual PxAgain processTouches(const HitType* /*hits*/, PxU32 /*count*/)
|
||||
{
|
||||
if (processCalled)
|
||||
return false;
|
||||
saveNbTouches = this->nbTouches;
|
||||
processCalled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void finalizeQuery()
|
||||
{
|
||||
if (processCalled)
|
||||
{
|
||||
overflow = (this->nbTouches > 0);
|
||||
this->nbTouches = saveNbTouches;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ExtBatchQuery : public PxBatchQueryExt
|
||||
{
|
||||
PX_NOCOPY(ExtBatchQuery)
|
||||
public:
|
||||
|
||||
ExtBatchQuery(
|
||||
const PxScene& scene,
|
||||
PxQueryFilterCallback* queryFilterCallback,
|
||||
PxRaycastBuffer* raycastBuffers, Raycast* raycastQueries, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
||||
PxSweepBuffer* sweepBuffers, Sweep* sweepQueries, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
||||
PxOverlapBuffer* overlapBuffers, Overlap* overlapQueries, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches);
|
||||
|
||||
~ExtBatchQuery() {}
|
||||
|
||||
virtual void release();
|
||||
|
||||
virtual PxRaycastBuffer* raycast(
|
||||
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, const PxU16 maxNbTouches,
|
||||
PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT),
|
||||
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
||||
const PxQueryCache* cache = NULL);
|
||||
|
||||
virtual PxSweepBuffer* sweep(
|
||||
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, const PxU16 maxNbTouches,
|
||||
PxHitFlags hitFlags = PxHitFlags(PxHitFlag::eDEFAULT),
|
||||
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
||||
const PxQueryCache* cache = NULL,
|
||||
const PxReal inflation = 0.f);
|
||||
|
||||
virtual PxOverlapBuffer* overlap(
|
||||
const PxGeometry& geometry, const PxTransform& pose, PxU16 maxNbTouches = 0,
|
||||
const PxQueryFilterData& filterData = PxQueryFilterData(),
|
||||
const PxQueryCache* cache = NULL);
|
||||
|
||||
virtual void execute();
|
||||
|
||||
private:
|
||||
|
||||
template<typename HitType, typename QueryType> struct Query
|
||||
{
|
||||
PxHitBuffer<HitType>* mBuffers;
|
||||
QueryType* mQueries;
|
||||
PxU32 mMaxNbBuffers;
|
||||
HitType* mTouches;
|
||||
PxU32 mMaxNbTouches;
|
||||
|
||||
PxU32 mBufferTide;
|
||||
|
||||
Query()
|
||||
: mBuffers(NULL),
|
||||
mQueries(NULL),
|
||||
mMaxNbBuffers(0),
|
||||
mTouches(NULL),
|
||||
mMaxNbTouches(0),
|
||||
mBufferTide(0)
|
||||
{
|
||||
}
|
||||
|
||||
Query(PxHitBuffer<HitType>* buffers, QueryType* queries, const PxU32 maxNbBuffers, HitType* touches, const PxU32 maxNbTouches)
|
||||
: mBuffers(buffers),
|
||||
mQueries(queries),
|
||||
mMaxNbBuffers(maxNbBuffers),
|
||||
mTouches(touches),
|
||||
mMaxNbTouches(maxNbTouches),
|
||||
mBufferTide(0)
|
||||
{
|
||||
for (PxU32 i = 0; i < mMaxNbBuffers; i++)
|
||||
{
|
||||
mBuffers[i].hasBlock = false;
|
||||
mBuffers[i].nbTouches = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PxHitBuffer<HitType>* addQuery(const QueryType& query, const PxU32 maxNbTouches)
|
||||
{
|
||||
if ((mBufferTide + 1) > mMaxNbBuffers)
|
||||
{
|
||||
//Ran out of queries.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PxHitBuffer<HitType>* buffer = mBuffers + mBufferTide;
|
||||
buffer->touches = NULL;
|
||||
buffer->maxNbTouches = maxNbTouches;
|
||||
buffer->hasBlock = false;
|
||||
buffer->nbTouches = 0xffffffff;
|
||||
|
||||
mQueries[mBufferTide] = query;
|
||||
|
||||
mBufferTide++;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void performQuery(const PxScene& scene, const Raycast& query, NpOverflowBuffer<PxRaycastHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
||||
{
|
||||
scene.raycast(
|
||||
query.origin, query.unitDir, query.distance,
|
||||
hitBuffer,
|
||||
query.hitFlags,
|
||||
query.filterData, qfcb,
|
||||
query.cache);
|
||||
}
|
||||
|
||||
static void performQuery(const PxScene& scene, const Sweep& query, NpOverflowBuffer<PxSweepHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
||||
{
|
||||
scene.sweep(
|
||||
query.geometry.any(), query.pose, query.unitDir, query.distance,
|
||||
hitBuffer,
|
||||
query.hitFlags,
|
||||
query.filterData, qfcb,
|
||||
query.cache,
|
||||
query.inflation);
|
||||
}
|
||||
|
||||
static void performQuery(const PxScene& scene, const Overlap& query, NpOverflowBuffer<PxOverlapHit>& hitBuffer, PxQueryFilterCallback* qfcb)
|
||||
{
|
||||
scene.overlap(
|
||||
query.geometry.any(), query.pose,
|
||||
hitBuffer,
|
||||
query.filterData, qfcb,
|
||||
query.cache);
|
||||
}
|
||||
|
||||
void execute(const PxScene& scene, PxQueryFilterCallback* qfcb)
|
||||
{
|
||||
PxU32 touchesTide = 0;
|
||||
for (PxU32 i = 0; i < mBufferTide; i++)
|
||||
{
|
||||
PX_ASSERT(0xffffffff == mBuffers[i].nbTouches);
|
||||
PX_ASSERT(0xffffffff != mBuffers[i].maxNbTouches);
|
||||
PX_ASSERT(!mBuffers[i].touches);
|
||||
|
||||
bool noTouchesRemaining = false;
|
||||
if (mBuffers[i].maxNbTouches > 0)
|
||||
{
|
||||
if (touchesTide >= mMaxNbTouches)
|
||||
{
|
||||
//No resources left.
|
||||
mBuffers[i].maxNbTouches = 0;
|
||||
mBuffers[i].touches = NULL;
|
||||
noTouchesRemaining = true;
|
||||
}
|
||||
else if ((touchesTide + mBuffers[i].maxNbTouches) > mMaxNbTouches)
|
||||
{
|
||||
//Some resources left but not enough to match requested number.
|
||||
//This might be enough but it depends on the number of hits generated by the query.
|
||||
mBuffers[i].maxNbTouches = mMaxNbTouches - touchesTide;
|
||||
mBuffers[i].touches = mTouches + touchesTide;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Enough resources left to match request.
|
||||
mBuffers[i].touches = mTouches + touchesTide;
|
||||
}
|
||||
}
|
||||
|
||||
bool overflow = false;
|
||||
{
|
||||
PX_ALIGN(16, NpOverflowBuffer<HitType> overflowBuffer)(mBuffers[i].touches, mBuffers[i].maxNbTouches);
|
||||
performQuery(scene, mQueries[i], overflowBuffer, qfcb);
|
||||
overflow = overflowBuffer.overflow || noTouchesRemaining;
|
||||
mBuffers[i].hasBlock = overflowBuffer.hasBlock;
|
||||
mBuffers[i].block = overflowBuffer.block;
|
||||
mBuffers[i].nbTouches = overflowBuffer.nbTouches;
|
||||
}
|
||||
|
||||
if(overflow)
|
||||
{
|
||||
mBuffers[i].maxNbTouches = 0xffffffff;
|
||||
}
|
||||
touchesTide += mBuffers[i].nbTouches;
|
||||
}
|
||||
|
||||
mBufferTide = 0;
|
||||
}
|
||||
};
|
||||
|
||||
const PxScene& mScene;
|
||||
PxQueryFilterCallback* mQueryFilterCallback;
|
||||
|
||||
Query<PxRaycastHit, Raycast> mRaycasts;
|
||||
Query<PxSweepHit, Sweep> mSweeps;
|
||||
Query<PxOverlapHit, Overlap> mOverlaps;
|
||||
};
|
||||
|
||||
template<typename HitType>
|
||||
class ExtBatchQueryDesc
|
||||
{
|
||||
public:
|
||||
ExtBatchQueryDesc(const PxU32 maxNbResults, const PxU32 maxNbTouches)
|
||||
: mResults(NULL),
|
||||
mMaxNbResults(maxNbResults),
|
||||
mTouches(NULL),
|
||||
mMaxNbTouches(maxNbTouches)
|
||||
{
|
||||
}
|
||||
ExtBatchQueryDesc(PxHitBuffer<HitType>* results, const PxU32 maxNbResults, HitType* touches, PxU32 maxNbTouches)
|
||||
: mResults(results),
|
||||
mMaxNbResults(maxNbResults),
|
||||
mTouches(touches),
|
||||
mMaxNbTouches(maxNbTouches)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxHitBuffer<HitType>* getResults() const { return mResults; }
|
||||
PX_FORCE_INLINE PxU32 getNbResults() const { return mMaxNbResults; }
|
||||
PX_FORCE_INLINE HitType* getTouches() const { return mTouches; }
|
||||
PX_FORCE_INLINE PxU32 getNbTouches() const { return mMaxNbTouches; }
|
||||
|
||||
private:
|
||||
PxHitBuffer<HitType>* mResults;
|
||||
PxU32 mMaxNbResults;
|
||||
HitType* mTouches;
|
||||
PxU32 mMaxNbTouches;
|
||||
};
|
||||
|
||||
template <typename HitType, typename QueryType>
|
||||
PxU32 computeByteSize(const ExtBatchQueryDesc<HitType>& queryDesc)
|
||||
{
|
||||
PxU32 byteSize = 0;
|
||||
if (queryDesc.getNbResults() > 0)
|
||||
{
|
||||
byteSize += sizeof(QueryType)*queryDesc.getNbResults();
|
||||
if (!queryDesc.getResults())
|
||||
{
|
||||
byteSize += sizeof(PxHitBuffer<HitType>)*queryDesc.getNbResults() + sizeof(HitType)*queryDesc.getNbTouches();
|
||||
}
|
||||
}
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
template <typename HitType, typename QueryType> PxU8* parseDesc
|
||||
(PxU8* bufIn, const ExtBatchQueryDesc<HitType>& queryDesc,
|
||||
PxHitBuffer<HitType>*& results,
|
||||
QueryType*& queries,
|
||||
PxU32& maxBufferSize,
|
||||
HitType*& touches,
|
||||
PxU32& maxNbTouches)
|
||||
{
|
||||
PxU8* bufOut = bufIn;
|
||||
|
||||
results = queryDesc.getResults();
|
||||
queries = NULL;
|
||||
maxBufferSize = queryDesc.getNbResults();
|
||||
touches = queryDesc.getTouches();
|
||||
maxNbTouches = queryDesc.getNbTouches();
|
||||
|
||||
if (maxBufferSize > 0)
|
||||
{
|
||||
queries = reinterpret_cast<QueryType*>(bufOut);
|
||||
bufOut += sizeof(QueryType)*maxBufferSize;
|
||||
|
||||
if (!results)
|
||||
{
|
||||
results = reinterpret_cast<PxHitBuffer<HitType>*>(bufOut);
|
||||
for (PxU32 i = 0; i < maxBufferSize; i++)
|
||||
{
|
||||
PX_PLACEMENT_NEW(results + i, PxHitBuffer<HitType>);
|
||||
}
|
||||
bufOut += sizeof(PxHitBuffer<HitType>)*maxBufferSize;
|
||||
|
||||
if (maxNbTouches > 0)
|
||||
{
|
||||
touches = reinterpret_cast<HitType*>(bufOut);
|
||||
bufOut += sizeof(HitType)*maxNbTouches;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bufOut;
|
||||
}
|
||||
|
||||
PxBatchQueryExt* create
|
||||
(const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
||||
const ExtBatchQueryDesc<PxRaycastHit>& raycastDesc, const ExtBatchQueryDesc<PxSweepHit>& sweepDesc, const ExtBatchQueryDesc<PxOverlapHit>& overlapDesc)
|
||||
{
|
||||
const PxU32 byteSize =
|
||||
sizeof(ExtBatchQuery) +
|
||||
computeByteSize<PxRaycastHit, Raycast>(raycastDesc) +
|
||||
computeByteSize<PxSweepHit, Sweep>(sweepDesc) +
|
||||
computeByteSize<PxOverlapHit, Overlap>(overlapDesc);
|
||||
|
||||
PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
|
||||
|
||||
PxU8* buf = reinterpret_cast<PxU8*>(allocator.allocate(byteSize, "NpBatchQueryExt", PX_FL));
|
||||
PX_CHECK_AND_RETURN_NULL(buf, "PxCreateBatchQueryExt - alllocation failed");
|
||||
ExtBatchQuery* bq = reinterpret_cast<ExtBatchQuery*>(buf);
|
||||
buf += sizeof(ExtBatchQuery);
|
||||
|
||||
PxHitBuffer<PxRaycastHit>* raycastBuffers = NULL;
|
||||
Raycast* raycastQueries = NULL;
|
||||
PxU32 maxNbRaycasts = 0;
|
||||
PxRaycastHit* raycastTouches = NULL;
|
||||
PxU32 maxNbRaycastTouches = 0;
|
||||
buf = parseDesc<PxRaycastHit, Raycast>(buf, raycastDesc, raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches);
|
||||
|
||||
PxHitBuffer<PxSweepHit>* sweepBuffers = NULL;
|
||||
Sweep* sweepQueries = NULL;
|
||||
PxU32 maxNbSweeps = 0;
|
||||
PxSweepHit* sweepTouches = NULL;
|
||||
PxU32 maxNbSweepTouches = 0;
|
||||
buf = parseDesc<PxSweepHit, Sweep>(buf, sweepDesc, sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches);
|
||||
|
||||
PxHitBuffer<PxOverlapHit>* overlapBuffers = NULL;
|
||||
Overlap* overlapQueries = NULL;
|
||||
PxU32 maxNbOverlaps = 0;
|
||||
PxOverlapHit* overlapTouches = NULL;
|
||||
PxU32 maxNbOverlapTouches = 0;
|
||||
buf = parseDesc<PxOverlapHit, Overlap>(buf, overlapDesc, overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
||||
|
||||
PX_ASSERT((reinterpret_cast<PxU8*>(bq) + byteSize) == buf);
|
||||
|
||||
PX_PLACEMENT_NEW(bq, ExtBatchQuery)(
|
||||
scene, queryFilterCallback,
|
||||
raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches,
|
||||
sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches,
|
||||
overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
||||
|
||||
return bq;
|
||||
}
|
||||
|
||||
PxBatchQueryExt* physx::PxCreateBatchQueryExt(
|
||||
const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
||||
const PxU32 maxNbRaycasts, const PxU32 maxNbRaycastTouches,
|
||||
const PxU32 maxNbSweeps, const PxU32 maxNbSweepTouches,
|
||||
const PxU32 maxNbOverlaps, const PxU32 maxNbOverlapTouches)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbRaycastTouches) && (0 == maxNbRaycasts)),
|
||||
"PxCreateBatchQueryExt - maxNbRaycastTouches is non-zero but maxNbRaycasts is zero");
|
||||
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbSweepTouches) && (0 == maxNbSweeps)),
|
||||
"PxCreateBatchQueryExt - maxNbSweepTouches is non-zero but maxNbSweeps is zero");
|
||||
PX_CHECK_AND_RETURN_NULL(!((0 != maxNbOverlapTouches) && (0 == maxNbOverlaps)),
|
||||
"PxCreateBatchQueryExt - maxNbOverlaps is non-zero but maxNbOverlaps is zero");
|
||||
|
||||
return create(scene, queryFilterCallback,
|
||||
ExtBatchQueryDesc<PxRaycastHit>(maxNbRaycasts, maxNbRaycastTouches),
|
||||
ExtBatchQueryDesc<PxSweepHit>(maxNbSweeps, maxNbSweepTouches),
|
||||
ExtBatchQueryDesc<PxOverlapHit>(maxNbOverlaps, maxNbOverlapTouches));
|
||||
}
|
||||
|
||||
PxBatchQueryExt* physx::PxCreateBatchQueryExt(
|
||||
const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
||||
PxRaycastBuffer* raycastBuffers, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
||||
PxSweepBuffer* sweepBuffers, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
||||
PxOverlapBuffer* overlapBuffers, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(!(!raycastTouches && (maxNbRaycastTouches != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbRaycastTouches > 0 but raycastTouches is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!raycastBuffers && (maxNbRaycasts != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbRaycasts > 0 but raycastBuffers is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!raycastBuffers && raycastTouches),
|
||||
"PxCreateBatchQueryExt - raycastBuffers is NULL but raycastTouches is non-NULL");
|
||||
|
||||
PX_CHECK_AND_RETURN_NULL(!(!sweepTouches && (maxNbSweepTouches != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbSweepTouches > 0 but sweepTouches is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!sweepBuffers && (maxNbSweeps != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbSweeps > 0 but sweepBuffers is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!sweepBuffers && sweepTouches),
|
||||
"PxCreateBatchQueryExt - sweepBuffers is NULL but sweepTouches is non-NULL");
|
||||
|
||||
PX_CHECK_AND_RETURN_NULL(!(!overlapTouches && (maxNbOverlapTouches != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbOverlapTouches > 0 but overlapTouches is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!overlapBuffers && (maxNbOverlaps != 0)),
|
||||
"PxCreateBatchQueryExt - maxNbOverlaps > 0 but overlapBuffers is NULL");
|
||||
PX_CHECK_AND_RETURN_NULL(!(!overlapBuffers && overlapTouches),
|
||||
"PxCreateBatchQueryExt - overlapBuffers is NULL but overlapTouches is non-NULL");
|
||||
|
||||
return create(scene, queryFilterCallback,
|
||||
ExtBatchQueryDesc<PxRaycastHit>(raycastBuffers, maxNbRaycasts, raycastTouches, maxNbRaycastTouches),
|
||||
ExtBatchQueryDesc<PxSweepHit>(sweepBuffers, maxNbSweeps, sweepTouches, maxNbSweepTouches),
|
||||
ExtBatchQueryDesc<PxOverlapHit>(overlapBuffers, maxNbOverlaps, overlapTouches, maxNbOverlapTouches));
|
||||
}
|
||||
|
||||
|
||||
ExtBatchQuery::ExtBatchQuery
|
||||
(const PxScene& scene, PxQueryFilterCallback* queryFilterCallback,
|
||||
PxRaycastBuffer* raycastBuffers, Raycast* raycastQueries, const PxU32 maxNbRaycasts, PxRaycastHit* raycastTouches, const PxU32 maxNbRaycastTouches,
|
||||
PxSweepBuffer* sweepBuffers, Sweep* sweepQueries, const PxU32 maxNbSweeps, PxSweepHit* sweepTouches, const PxU32 maxNbSweepTouches,
|
||||
PxOverlapBuffer* overlapBuffers, Overlap* overlapQueries, const PxU32 maxNbOverlaps, PxOverlapHit* overlapTouches, const PxU32 maxNbOverlapTouches)
|
||||
: mScene(scene),
|
||||
mQueryFilterCallback(queryFilterCallback)
|
||||
{
|
||||
typedef Query<PxRaycastHit, Raycast> QueryRaycast;
|
||||
typedef Query<PxSweepHit, Sweep> QuerySweep;
|
||||
typedef Query<PxOverlapHit, Overlap> QueryOverlap;
|
||||
PX_PLACEMENT_NEW(&mRaycasts, QueryRaycast)(raycastBuffers, raycastQueries, maxNbRaycasts, raycastTouches, maxNbRaycastTouches);
|
||||
PX_PLACEMENT_NEW(&mSweeps, QuerySweep)(sweepBuffers, sweepQueries, maxNbSweeps, sweepTouches, maxNbSweepTouches);
|
||||
PX_PLACEMENT_NEW(&mOverlaps, QueryOverlap)(overlapBuffers, overlapQueries, maxNbOverlaps, overlapTouches, maxNbOverlapTouches);
|
||||
}
|
||||
|
||||
void ExtBatchQuery::release()
|
||||
{
|
||||
PxGetAllocatorCallback()->deallocate(this);
|
||||
}
|
||||
|
||||
PxRaycastBuffer* ExtBatchQuery::raycast
|
||||
(const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
const PxU16 maxNbTouches,
|
||||
PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData,
|
||||
const PxQueryCache* cache)
|
||||
{
|
||||
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
||||
const Raycast raycast = { origin, unitDir, distance, hitFlags, qfd, cache };
|
||||
PxRaycastBuffer* buffer = mRaycasts.addQuery(raycast, maxNbTouches);
|
||||
PX_CHECK_MSG(buffer, "PxBatchQueryExt::raycast - number of raycast() calls exceeds maxNbRaycasts. query discarded");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PxSweepBuffer* ExtBatchQuery::sweep
|
||||
(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
|
||||
const PxU16 maxNbTouches,
|
||||
PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData,
|
||||
const PxQueryCache* cache,
|
||||
const PxReal inflation)
|
||||
{
|
||||
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
||||
const Sweep sweep = { geometry, pose, unitDir, distance, hitFlags, qfd, cache, inflation};
|
||||
PxSweepBuffer* buffer = mSweeps.addQuery(sweep, maxNbTouches);
|
||||
PX_CHECK_MSG(buffer, "PxBatchQueryExt::sweep - number of sweep() calls exceeds maxNbSweeps. query discarded");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PxOverlapBuffer* ExtBatchQuery::overlap
|
||||
(const PxGeometry& geometry, const PxTransform& pose, PxU16 maxNbTouches,
|
||||
const PxQueryFilterData& filterData,
|
||||
const PxQueryCache* cache)
|
||||
{
|
||||
const PxQueryFilterData qfd(filterData.data, filterData.flags | PxQueryFlag::eBATCH_QUERY_LEGACY_BEHAVIOUR);
|
||||
const Overlap overlap = { geometry, pose, qfd, cache};
|
||||
PxOverlapBuffer* buffer = mOverlaps.addQuery(overlap, maxNbTouches);
|
||||
PX_CHECK_MSG(buffer, "PxBatchQueryExt::overlap - number of overlap() calls exceeds maxNbOverlaps. query discarded");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void ExtBatchQuery::execute()
|
||||
{
|
||||
mRaycasts.execute(mScene, mQueryFilterCallback);
|
||||
mSweeps.execute(mScene, mQueryFilterCallback);
|
||||
mOverlaps.execute(mScene, mQueryFilterCallback);
|
||||
}
|
||||
469
engine/third_party/physx/source/physxextensions/src/ExtSceneQuerySystem.cpp
vendored
Normal file
469
engine/third_party/physx/source/physxextensions/src/ExtSceneQuerySystem.cpp
vendored
Normal file
@@ -0,0 +1,469 @@
|
||||
// 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/PxSceneQuerySystemExt.h"
|
||||
#include "extensions/PxShapeExt.h"
|
||||
#include "foundation/PxAlloca.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "geometry/PxBVH.h"
|
||||
#include "GuActorShapeMap.h"
|
||||
#include "SqQuery.h"
|
||||
#include "SqFactory.h"
|
||||
#include "PxRigidActor.h"
|
||||
#include "PxPruningStructure.h"
|
||||
#include "PxSceneDesc.h" // PT: for PxSceneLimits TODO: remove
|
||||
|
||||
// PT: this file re-implements a scene-queries system for PxScene inside PxExtensions. All SQ-related calls from the PxScene API
|
||||
// will be re-routed to this class. This version re-uses the same internal code as PhysX (most notably from SqQuery.h) so there is
|
||||
// little differences between the internal PhysX version and this one except minor implementation details like what we store in the
|
||||
// PrunerPayload. The whole API is available, it uses the same number of "pruners" for the queries, etc. This is a good working
|
||||
// starting point for users who want to start tinkering with the system without starting from scratch.
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sq;
|
||||
using namespace Gu;
|
||||
|
||||
#define EXT_PRUNER_EPSILON 0.005f
|
||||
|
||||
// PT: in this external implementation we'll use Px pointers instead of Np pointers in the payload.
|
||||
static PX_FORCE_INLINE void setPayload(PrunerPayload& pp, const PxShape* shape, const PxRigidActor* actor)
|
||||
{
|
||||
pp.data[0] = size_t(shape);
|
||||
pp.data[1] = size_t(actor);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxShape* getShapeFromPayload(const PrunerPayload& payload)
|
||||
{
|
||||
return reinterpret_cast<PxShape*>(payload.data[0]);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxRigidActor* getActorFromPayload(const PrunerPayload& payload)
|
||||
{
|
||||
return reinterpret_cast<PxRigidActor*>(payload.data[1]);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool isDynamicActor(const PxRigidActor& actor)
|
||||
{
|
||||
const PxType actorType = actor.getConcreteType();
|
||||
return actorType != PxConcreteType::eRIGID_STATIC;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PX_FORCE_INLINE ActorShapeData createActorShapeData(PrunerData data, PrunerCompoundId id) { return (ActorShapeData(id) << 32) | ActorShapeData(data); }
|
||||
static PX_FORCE_INLINE PrunerData getPrunerData(ActorShapeData data) { return PrunerData(data); }
|
||||
static PX_FORCE_INLINE PrunerCompoundId getCompoundID(ActorShapeData data) { return PrunerCompoundId(data >> 32); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
class ExtSqAdapter : public QueryAdapter
|
||||
{
|
||||
public:
|
||||
ExtSqAdapter() {}
|
||||
virtual ~ExtSqAdapter() {}
|
||||
|
||||
// Adapter
|
||||
virtual const PxGeometry& getGeometry(const PrunerPayload& payload) const;
|
||||
//~Adapter
|
||||
|
||||
// QueryAdapter
|
||||
virtual PrunerHandle findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const;
|
||||
virtual void getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const;
|
||||
virtual void getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const;
|
||||
//~QueryAdapter
|
||||
|
||||
ActorShapeMap mDatabase;
|
||||
};
|
||||
}
|
||||
|
||||
const PxGeometry& ExtSqAdapter::getGeometry(const PrunerPayload& payload) const
|
||||
{
|
||||
PxShape* shape = getShapeFromPayload(payload);
|
||||
return shape->getGeometry();
|
||||
}
|
||||
|
||||
PrunerHandle ExtSqAdapter::findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const
|
||||
{
|
||||
const PxU32 actorIndex = cache.actor->getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mDatabase.find(actorIndex, cache.actor, cache.shape);
|
||||
|
||||
const PrunerData prunerData = getPrunerData(actorShapeData);
|
||||
compoundId = getCompoundID(actorShapeData);
|
||||
|
||||
prunerIndex = getPrunerIndex(prunerData);
|
||||
return getPrunerHandle(prunerData);
|
||||
}
|
||||
|
||||
void ExtSqAdapter::getFilterData(const PrunerPayload& payload, PxFilterData& filterData) const
|
||||
{
|
||||
PxShape* shape = getShapeFromPayload(payload);
|
||||
filterData = shape->getQueryFilterData();
|
||||
}
|
||||
|
||||
void ExtSqAdapter::getActorShape(const PrunerPayload& payload, PxActorShape& actorShape) const
|
||||
{
|
||||
actorShape.actor = getActorFromPayload(payload);
|
||||
actorShape.shape = getShapeFromPayload(payload);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
class ExternalPxSQ : public PxSceneQuerySystem, public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
ExternalPxSQ(PVDCapture* pvd, PxU64 contextID, Pruner* staticPruner, Pruner* dynamicPruner,
|
||||
PxU32 dynamicTreeRebuildRateHint, PxSceneQueryUpdateMode::Enum mode, const PxSceneLimits& limits) :
|
||||
mQueries (pvd, contextID, staticPruner, dynamicPruner, dynamicTreeRebuildRateHint, EXT_PRUNER_EPSILON, limits, mExtAdapter),
|
||||
mUpdateMode (mode),
|
||||
mRefCount (1)
|
||||
{}
|
||||
virtual ~ExternalPxSQ() {}
|
||||
|
||||
virtual void release();
|
||||
virtual void acquireReference();
|
||||
virtual void preallocate(PxU32 prunerIndex, PxU32 nbShapes) { SQ().preallocate(prunerIndex, nbShapes); }
|
||||
virtual void addSQShape( const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds,
|
||||
const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure);
|
||||
virtual void removeSQShape(const PxRigidActor& actor, const PxShape& shape);
|
||||
virtual void updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform);
|
||||
virtual PxSQCompoundHandle addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& pxbvh, const PxTransform* transforms);
|
||||
virtual void removeSQCompound(PxSQCompoundHandle compoundHandle);
|
||||
virtual void updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform);
|
||||
virtual void flushUpdates() { SQ().flushUpdates(); }
|
||||
virtual void flushMemory() { SQ().flushMemory(); }
|
||||
virtual void visualize(PxU32 prunerIndex, PxRenderOutput& out) const { SQ().visualize(prunerIndex, out); }
|
||||
virtual void shiftOrigin(const PxVec3& shift) { SQ().shiftOrigin(shift); }
|
||||
virtual PxSQBuildStepHandle prepareSceneQueryBuildStep(PxU32 prunerIndex);
|
||||
virtual void sceneQueryBuildStep(PxSQBuildStepHandle handle);
|
||||
virtual void finalizeUpdates();
|
||||
virtual void setDynamicTreeRebuildRateHint(PxU32 dynTreeRebuildRateHint) { SQ().setDynamicTreeRebuildRateHint(dynTreeRebuildRateHint); }
|
||||
virtual PxU32 getDynamicTreeRebuildRateHint() const { return SQ().getDynamicTreeRebuildRateHint(); }
|
||||
virtual void forceRebuildDynamicTree(PxU32 prunerIndex) { SQ().forceRebuildDynamicTree(prunerIndex); }
|
||||
virtual PxSceneQueryUpdateMode::Enum getUpdateMode() const { return mUpdateMode; }
|
||||
virtual void setUpdateMode(PxSceneQueryUpdateMode::Enum mode) { mUpdateMode = mode; }
|
||||
virtual PxU32 getStaticTimestamp() const { return SQ().getStaticTimestamp(); }
|
||||
virtual void merge(const PxPruningStructure& pxps);
|
||||
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
virtual bool sweep( const PxGeometry& geometry, const PxTransform& pose,
|
||||
const PxVec3& unitDir, const PxReal distance,
|
||||
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const;
|
||||
virtual bool overlap(const PxGeometry& geometry, const PxTransform& transform,
|
||||
PxOverlapCallback& hitCall,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
virtual PxSQPrunerHandle getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const;
|
||||
virtual void sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
||||
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices);
|
||||
|
||||
PX_FORCE_INLINE PrunerManager& SQ() { return mQueries.mSQManager; }
|
||||
PX_FORCE_INLINE const PrunerManager& SQ() const { return mQueries.mSQManager; }
|
||||
|
||||
ExtSqAdapter mExtAdapter;
|
||||
SceneQueries mQueries;
|
||||
PxSceneQueryUpdateMode::Enum mUpdateMode;
|
||||
PxU32 mRefCount;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void addExternalSQ(PxSceneQuerySystem* added);
|
||||
void removeExternalSQ(PxSceneQuerySystem* removed);
|
||||
|
||||
void ExternalPxSQ::release()
|
||||
{
|
||||
mRefCount--;
|
||||
if(!mRefCount)
|
||||
{
|
||||
removeExternalSQ(this);
|
||||
PX_DELETE_THIS;
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalPxSQ::acquireReference()
|
||||
{
|
||||
mRefCount++;
|
||||
}
|
||||
|
||||
void ExternalPxSQ::addSQShape(const PxRigidActor& actor, const PxShape& shape, const PxBounds3& bounds, const PxTransform& transform, const PxSQCompoundHandle* compoundHandle, bool hasPruningStructure)
|
||||
{
|
||||
PrunerPayload payload;
|
||||
setPayload(payload, &shape, &actor);
|
||||
|
||||
const PrunerCompoundId cid = compoundHandle ? PrunerCompoundId(*compoundHandle) : INVALID_COMPOUND_ID;
|
||||
const PrunerData prunerData = SQ().addPrunerShape(payload, isDynamicActor(actor), cid, bounds, transform, hasPruningStructure);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
mExtAdapter.mDatabase.add(actorIndex, &actor, &shape, createActorShapeData(prunerData, cid));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct DatabaseCleaner : PrunerPayloadRemovalCallback
|
||||
{
|
||||
DatabaseCleaner(ExtSqAdapter& adapter) : mAdapter(adapter){}
|
||||
|
||||
virtual void invoke(PxU32 nbRemoved, const PrunerPayload* removed) PX_OVERRIDE PX_FINAL
|
||||
{
|
||||
PxU32 actorIndex = 0xffffffff;
|
||||
const PxRigidActor* cachedActor = NULL;
|
||||
|
||||
while(nbRemoved--)
|
||||
{
|
||||
const PrunerPayload& payload = *removed++;
|
||||
|
||||
const PxRigidActor* actor = getActorFromPayload(payload);
|
||||
|
||||
if(actor!=cachedActor)
|
||||
{
|
||||
actorIndex = actor->getInternalActorIndex();
|
||||
cachedActor = actor;
|
||||
}
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
bool status = mAdapter.mDatabase.remove(actorIndex, actor, getShapeFromPayload(payload), NULL);
|
||||
PX_ASSERT(status);
|
||||
PX_UNUSED(status);
|
||||
}
|
||||
}
|
||||
ExtSqAdapter& mAdapter;
|
||||
|
||||
PX_NOCOPY(DatabaseCleaner)
|
||||
};
|
||||
}
|
||||
|
||||
void ExternalPxSQ::removeSQShape(const PxRigidActor& actor, const PxShape& shape)
|
||||
{
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
ActorShapeData actorShapeData;
|
||||
mExtAdapter.mDatabase.remove(actorIndex, &actor, &shape, &actorShapeData);
|
||||
|
||||
const PrunerData data = getPrunerData(actorShapeData);
|
||||
const PrunerCompoundId compoundId = getCompoundID(actorShapeData);
|
||||
|
||||
SQ().removePrunerShape(compoundId, data, NULL);
|
||||
}
|
||||
|
||||
void ExternalPxSQ::updateSQShape(const PxRigidActor& actor, const PxShape& shape, const PxTransform& transform)
|
||||
{
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
||||
|
||||
const PrunerData shapeHandle = getPrunerData(actorShapeData);
|
||||
const PrunerCompoundId cid = getCompoundID(actorShapeData);
|
||||
|
||||
SQ().markForUpdate(cid, shapeHandle, transform);
|
||||
}
|
||||
|
||||
PxSQCompoundHandle ExternalPxSQ::addSQCompound(const PxRigidActor& actor, const PxShape** shapes, const PxBVH& bvh, const PxTransform* transforms)
|
||||
{
|
||||
const PxU32 numSqShapes = bvh.getNbBounds();
|
||||
|
||||
PX_ALLOCA(payloads, PrunerPayload, numSqShapes);
|
||||
for(PxU32 i=0; i<numSqShapes; i++)
|
||||
setPayload(payloads[i], shapes[i], &actor);
|
||||
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
PX_ALLOCA(shapeHandles, PrunerData, numSqShapes);
|
||||
SQ().addCompoundShape(bvh, actorIndex, actor.getGlobalPose(), shapeHandles, payloads, transforms, isDynamicActor(actor));
|
||||
|
||||
for(PxU32 i=0; i<numSqShapes; i++)
|
||||
{
|
||||
// PT: TODO: actorIndex is now redundant!
|
||||
mExtAdapter.mDatabase.add(actorIndex, &actor, shapes[i], createActorShapeData(shapeHandles[i], actorIndex));
|
||||
}
|
||||
|
||||
return PxSQCompoundHandle(actorIndex);
|
||||
}
|
||||
|
||||
void ExternalPxSQ::removeSQCompound(PxSQCompoundHandle compoundHandle)
|
||||
{
|
||||
DatabaseCleaner cleaner(mExtAdapter);
|
||||
SQ().removeCompoundActor(PrunerCompoundId(compoundHandle), &cleaner);
|
||||
}
|
||||
|
||||
void ExternalPxSQ::updateSQCompound(PxSQCompoundHandle compoundHandle, const PxTransform& compoundTransform)
|
||||
{
|
||||
SQ().updateCompoundActor(PrunerCompoundId(compoundHandle), compoundTransform);
|
||||
}
|
||||
|
||||
PxSQBuildStepHandle ExternalPxSQ::prepareSceneQueryBuildStep(PxU32 prunerIndex)
|
||||
{
|
||||
return SQ().prepareSceneQueriesUpdate(PruningIndex::Enum(prunerIndex));
|
||||
}
|
||||
|
||||
void ExternalPxSQ::sceneQueryBuildStep(PxSQBuildStepHandle handle)
|
||||
{
|
||||
SQ().sceneQueryBuildStep(handle);
|
||||
}
|
||||
|
||||
void ExternalPxSQ::finalizeUpdates()
|
||||
{
|
||||
switch(mUpdateMode)
|
||||
{
|
||||
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_ENABLED: SQ().afterSync(true, true); break;
|
||||
case PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED: SQ().afterSync(true, false); break;
|
||||
case PxSceneQueryUpdateMode::eBUILD_DISABLED_COMMIT_DISABLED: SQ().afterSync(false, false); break;
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalPxSQ::merge(const PxPruningStructure& pxps)
|
||||
{
|
||||
Pruner* staticPruner = SQ().getPruner(PruningIndex::eSTATIC);
|
||||
if(staticPruner)
|
||||
staticPruner->merge(pxps.getStaticMergeData());
|
||||
|
||||
Pruner* dynamicPruner = SQ().getPruner(PruningIndex::eDYNAMIC);
|
||||
if(dynamicPruner)
|
||||
dynamicPruner->merge(pxps.getDynamicMergeData());
|
||||
}
|
||||
|
||||
bool ExternalPxSQ::raycast( const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
|
||||
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._raycast(origin, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, flags);
|
||||
}
|
||||
|
||||
bool ExternalPxSQ::sweep( const PxGeometry& geometry, const PxTransform& pose,
|
||||
const PxVec3& unitDir, const PxReal distance,
|
||||
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._sweep(geometry, pose, unitDir, distance, hitCall, hitFlags, filterData, filterCall, cache, inflation, flags);
|
||||
}
|
||||
|
||||
bool ExternalPxSQ::overlap( const PxGeometry& geometry, const PxTransform& transform,
|
||||
PxOverlapCallback& hitCall,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const
|
||||
{
|
||||
return mQueries._overlap( geometry, transform, hitCall, filterData, filterCall, cache, flags);
|
||||
}
|
||||
|
||||
PxSQPrunerHandle ExternalPxSQ::getHandle(const PxRigidActor& actor, const PxShape& shape, PxU32& prunerIndex) const
|
||||
{
|
||||
const PxU32 actorIndex = actor.getInternalActorIndex();
|
||||
PX_ASSERT(actorIndex!=0xffffffff);
|
||||
|
||||
const ActorShapeData actorShapeData = mExtAdapter.mDatabase.find(actorIndex, &actor, &shape);
|
||||
|
||||
const PrunerData prunerData = getPrunerData(actorShapeData);
|
||||
|
||||
prunerIndex = getPrunerIndex(prunerData);
|
||||
|
||||
return PxSQPrunerHandle(getPrunerHandle(prunerData));
|
||||
}
|
||||
|
||||
void ExternalPxSQ::sync(PxU32 prunerIndex, const PxSQPrunerHandle* handles, const PxU32* indices, const PxBounds3* bounds,
|
||||
const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices)
|
||||
{
|
||||
PX_ASSERT(prunerIndex==PruningIndex::eDYNAMIC);
|
||||
if(prunerIndex==PruningIndex::eDYNAMIC)
|
||||
SQ().sync(handles, indices, bounds, transforms, count, ignoredIndices);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static CompanionPrunerType getCompanionType(PxDynamicTreeSecondaryPruner::Enum type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case PxDynamicTreeSecondaryPruner::eNONE: return COMPANION_PRUNER_NONE;
|
||||
case PxDynamicTreeSecondaryPruner::eBUCKET: return COMPANION_PRUNER_BUCKET;
|
||||
case PxDynamicTreeSecondaryPruner::eINCREMENTAL: return COMPANION_PRUNER_INCREMENTAL;
|
||||
case PxDynamicTreeSecondaryPruner::eBVH: return COMPANION_PRUNER_AABB_TREE;
|
||||
case PxDynamicTreeSecondaryPruner::eLAST: return COMPANION_PRUNER_NONE;
|
||||
}
|
||||
return COMPANION_PRUNER_NONE;
|
||||
}
|
||||
|
||||
static BVHBuildStrategy getBuildStrategy(PxBVHBuildStrategy::Enum bs)
|
||||
{
|
||||
switch(bs)
|
||||
{
|
||||
case PxBVHBuildStrategy::eFAST: return BVH_SPLATTER_POINTS;
|
||||
case PxBVHBuildStrategy::eDEFAULT: return BVH_SPLATTER_POINTS_SPLIT_GEOM_CENTER;
|
||||
case PxBVHBuildStrategy::eSAH: return BVH_SAH;
|
||||
case PxBVHBuildStrategy::eLAST: return BVH_SPLATTER_POINTS;
|
||||
}
|
||||
return BVH_SPLATTER_POINTS;
|
||||
}
|
||||
|
||||
static Pruner* create(PxPruningStructureType::Enum type, PxU64 contextID, PxDynamicTreeSecondaryPruner::Enum secondaryType, PxBVHBuildStrategy::Enum buildStrategy, PxU32 nbObjectsPerNode)
|
||||
{
|
||||
// if(0)
|
||||
// return createIncrementalPruner(contextID);
|
||||
|
||||
const CompanionPrunerType cpType = getCompanionType(secondaryType);
|
||||
const BVHBuildStrategy bs = getBuildStrategy(buildStrategy);
|
||||
|
||||
Pruner* pruner = NULL;
|
||||
switch(type)
|
||||
{
|
||||
case PxPruningStructureType::eNONE: { pruner = createBucketPruner(contextID); break; }
|
||||
case PxPruningStructureType::eDYNAMIC_AABB_TREE: { pruner = createAABBPruner(contextID, true, cpType, bs, nbObjectsPerNode); break; }
|
||||
case PxPruningStructureType::eSTATIC_AABB_TREE: { pruner = createAABBPruner(contextID, false, cpType, bs, nbObjectsPerNode); break; }
|
||||
case PxPruningStructureType::eLAST: break;
|
||||
}
|
||||
return pruner;
|
||||
}
|
||||
|
||||
PxSceneQuerySystem* physx::PxCreateExternalSceneQuerySystem(const PxSceneQueryDesc& desc, PxU64 contextID)
|
||||
{
|
||||
PVDCapture* pvd = NULL;
|
||||
Pruner* staticPruner = create(desc.staticStructure, contextID, desc.dynamicTreeSecondaryPruner, desc.staticBVHBuildStrategy, desc.staticNbObjectsPerNode);
|
||||
Pruner* dynamicPruner = create(desc.dynamicStructure, contextID, desc.dynamicTreeSecondaryPruner, desc.dynamicBVHBuildStrategy, desc.dynamicNbObjectsPerNode);
|
||||
|
||||
ExternalPxSQ* pxsq = PX_NEW(ExternalPxSQ)(pvd, contextID, staticPruner, dynamicPruner, desc.dynamicTreeRebuildRateHint, desc.sceneQueryUpdateMode, PxSceneLimits());
|
||||
|
||||
addExternalSQ(pxsq);
|
||||
|
||||
return pxsq;
|
||||
}
|
||||
42
engine/third_party/physx/source/physxextensions/src/ExtSerialization.h
vendored
Normal file
42
engine/third_party/physx/source/physxextensions/src/ExtSerialization.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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 EXT_SERIALIZATION_H
|
||||
#define EXT_SERIALIZATION_H
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
void RegisterExtensionsSerializers(PxSerializationRegistry& sr);
|
||||
void UnregisterExtensionsSerializers(PxSerializationRegistry& sr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
151
engine/third_party/physx/source/physxextensions/src/ExtSharedQueueEntryPool.h
vendored
Normal file
151
engine/third_party/physx/source/physxextensions/src/ExtSharedQueueEntryPool.h
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
// 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 EXT_SHARED_QUEUE_ENTRY_POOL_H
|
||||
#define EXT_SHARED_QUEUE_ENTRY_POOL_H
|
||||
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxSList.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
class SharedQueueEntry : public PxSListEntry
|
||||
{
|
||||
public:
|
||||
SharedQueueEntry(void* objectRef) : mObjectRef(objectRef), mPooledEntry(false) {}
|
||||
SharedQueueEntry() : mObjectRef(NULL), mPooledEntry(true) {}
|
||||
|
||||
public:
|
||||
void* mObjectRef;
|
||||
bool mPooledEntry; // True if the entry was preallocated in a pool
|
||||
};
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value.
|
||||
#endif // Because of the SList member I assume*/
|
||||
|
||||
template<class Alloc = typename PxAllocatorTraits<SharedQueueEntry>::Type >
|
||||
class SharedQueueEntryPool : private Alloc
|
||||
{
|
||||
public:
|
||||
SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc = Alloc("SharedQueueEntryPool"));
|
||||
~SharedQueueEntryPool();
|
||||
|
||||
SharedQueueEntry* getEntry(void* objectRef);
|
||||
void putEntry(SharedQueueEntry& entry);
|
||||
|
||||
private:
|
||||
SharedQueueEntry* mTaskEntryPool;
|
||||
PxSList mTaskEntryPtrPool;
|
||||
};
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class Alloc>
|
||||
SharedQueueEntryPool<Alloc>::SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc)
|
||||
: Alloc(alloc)
|
||||
{
|
||||
PxAlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool");
|
||||
|
||||
mTaskEntryPool = poolSize ? reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry) * poolSize, PX_FL)) : NULL;
|
||||
|
||||
if (mTaskEntryPool)
|
||||
{
|
||||
for(PxU32 i=0; i < poolSize; i++)
|
||||
{
|
||||
PX_ASSERT((size_t(&mTaskEntryPool[i]) & (PX_SLIST_ALIGNMENT-1)) == 0); // The SList entry must be aligned according to PX_SLIST_ALIGNMENT
|
||||
|
||||
PX_PLACEMENT_NEW(&mTaskEntryPool[i], SharedQueueEntry)();
|
||||
PX_ASSERT(mTaskEntryPool[i].mPooledEntry == true);
|
||||
mTaskEntryPtrPool.push(mTaskEntryPool[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Alloc>
|
||||
SharedQueueEntryPool<Alloc>::~SharedQueueEntryPool()
|
||||
{
|
||||
if (mTaskEntryPool)
|
||||
{
|
||||
PxAlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool");
|
||||
alignedAlloc.deallocate(mTaskEntryPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Alloc>
|
||||
SharedQueueEntry* SharedQueueEntryPool<Alloc>::getEntry(void* objectRef)
|
||||
{
|
||||
SharedQueueEntry* e = static_cast<SharedQueueEntry*>(mTaskEntryPtrPool.pop());
|
||||
if (e)
|
||||
{
|
||||
PX_ASSERT(e->mPooledEntry == true);
|
||||
e->mObjectRef = objectRef;
|
||||
return e;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxAlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc;
|
||||
e = reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry), PX_FL));
|
||||
if (e)
|
||||
{
|
||||
PX_PLACEMENT_NEW(e, SharedQueueEntry)(objectRef);
|
||||
PX_ASSERT(e->mPooledEntry == false);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Alloc>
|
||||
void SharedQueueEntryPool<Alloc>::putEntry(SharedQueueEntry& entry)
|
||||
{
|
||||
if (entry.mPooledEntry)
|
||||
{
|
||||
entry.mObjectRef = NULL;
|
||||
mTaskEntryPtrPool.push(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
PxAlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc;
|
||||
alignedAlloc.deallocate(&entry);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ext
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
376
engine/third_party/physx/source/physxextensions/src/ExtSimpleFactory.cpp
vendored
Normal file
376
engine/third_party/physx/source/physxextensions/src/ExtSimpleFactory.cpp
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
// 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/PxMathUtils.h"
|
||||
#include "foundation/PxQuat.h"
|
||||
#include "geometry/PxSphereGeometry.h"
|
||||
#include "geometry/PxBoxGeometry.h"
|
||||
#include "geometry/PxCapsuleGeometry.h"
|
||||
#include "geometry/PxConvexMeshGeometry.h"
|
||||
#include "geometry/PxPlaneGeometry.h"
|
||||
#include "extensions/PxRigidBodyExt.h"
|
||||
#include "extensions/PxSimpleFactory.h"
|
||||
#include "PxPhysics.h"
|
||||
#include "PxScene.h"
|
||||
#include "PxRigidStatic.h"
|
||||
#include "PxRigidStatic.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
#include "PxShape.h"
|
||||
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "foundation/PxInlineArray.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static bool isDynamicGeometry(PxGeometryType::Enum type)
|
||||
{
|
||||
return type == PxGeometryType::eBOX
|
||||
|| type == PxGeometryType::eSPHERE
|
||||
|| type == PxGeometryType::eCAPSULE
|
||||
|| type == PxGeometryType::eCONVEXCORE
|
||||
|| type == PxGeometryType::eCUSTOM
|
||||
|| type == PxGeometryType::eCONVEXMESH;
|
||||
}
|
||||
|
||||
namespace physx
|
||||
{
|
||||
PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
PxShape& shape,
|
||||
PxReal density)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
|
||||
|
||||
PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
|
||||
if(actor)
|
||||
{
|
||||
if(!actor->attachShape(shape))
|
||||
{
|
||||
actor->release();
|
||||
return NULL;
|
||||
}
|
||||
if(!PxRigidBodyExt::updateMassAndInertia(*actor, density))
|
||||
{
|
||||
actor->release();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return actor;
|
||||
}
|
||||
|
||||
PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
const PxGeometry& geometry,
|
||||
PxMaterial& material,
|
||||
PxReal density,
|
||||
const PxTransform& shapeOffset)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
|
||||
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateDynamic: shapeOffset is not valid.");
|
||||
|
||||
if(!isDynamicGeometry(geometry.getType()) || density <= 0.0f)
|
||||
return NULL;
|
||||
|
||||
PxShape* shape = sdk.createShape(geometry, material, true);
|
||||
if(!shape)
|
||||
return NULL;
|
||||
|
||||
shape->setLocalPose(shapeOffset);
|
||||
|
||||
PxRigidDynamic* body = PxCreateDynamic(sdk, transform, *shape, density);
|
||||
shape->release();
|
||||
return body;
|
||||
}
|
||||
|
||||
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
PxShape& shape,
|
||||
PxReal density)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
|
||||
|
||||
bool isDynGeom = isDynamicGeometry(shape.getGeometry().getType());
|
||||
if(isDynGeom && density <= 0.0f)
|
||||
return NULL;
|
||||
|
||||
PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
|
||||
if(actor)
|
||||
{
|
||||
actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
|
||||
if(!isDynGeom)
|
||||
shape.setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
|
||||
|
||||
actor->attachShape(shape);
|
||||
|
||||
if(isDynGeom)
|
||||
PxRigidBodyExt::updateMassAndInertia(*actor, density);
|
||||
else
|
||||
{
|
||||
actor->setMass(1.f);
|
||||
actor->setMassSpaceInertiaTensor(PxVec3(1.f,1.f,1.f));
|
||||
}
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
const PxGeometry& geometry,
|
||||
PxMaterial& material,
|
||||
PxReal density,
|
||||
const PxTransform& shapeOffset)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
|
||||
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid.");
|
||||
|
||||
bool isDynGeom = isDynamicGeometry(geometry.getType());
|
||||
if(isDynGeom && density <= 0.0f)
|
||||
return NULL;
|
||||
|
||||
PxShape* shape = sdk.createShape(geometry, material, true);
|
||||
if(!shape)
|
||||
return NULL;
|
||||
|
||||
shape->setLocalPose(shapeOffset);
|
||||
|
||||
PxRigidDynamic* body = PxCreateKinematic(sdk, transform, *shape, density);
|
||||
shape->release();
|
||||
return body;
|
||||
}
|
||||
|
||||
PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
PxShape& shape)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
|
||||
|
||||
PxRigidStatic* s = sdk.createRigidStatic(transform);
|
||||
if(s)
|
||||
s->attachShape(shape);
|
||||
return s;
|
||||
}
|
||||
|
||||
PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
|
||||
const PxTransform& transform,
|
||||
const PxGeometry& geometry,
|
||||
PxMaterial& material,
|
||||
const PxTransform& shapeOffset)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
|
||||
PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateStatic: shapeOffset is not valid.");
|
||||
|
||||
PxShape* shape = sdk.createShape(geometry, material, true);
|
||||
if(!shape)
|
||||
return NULL;
|
||||
|
||||
shape->setLocalPose(shapeOffset);
|
||||
|
||||
PxRigidStatic* s = PxCreateStatic(sdk, transform, *shape);
|
||||
shape->release();
|
||||
return s;
|
||||
}
|
||||
|
||||
PxRigidStatic* PxCreatePlane(PxPhysics& sdk,
|
||||
const PxPlane& plane,
|
||||
PxMaterial& material)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(plane.n.isFinite(), "PxCreatePlane: plane normal is not valid.");
|
||||
|
||||
if (!plane.n.isNormalized())
|
||||
return NULL;
|
||||
|
||||
return PxCreateStatic(sdk, PxTransformFromPlaneEquation(plane), PxPlaneGeometry(), material);
|
||||
}
|
||||
|
||||
PxShape* PxCloneShape(PxPhysics& physics, const PxShape& from, bool isExclusive)
|
||||
{
|
||||
PxInlineArray<PxMaterial*, 64> materials;
|
||||
PxU16 materialCount = from.getNbMaterials();
|
||||
materials.resize(materialCount);
|
||||
from.getMaterials(materials.begin(), materialCount);
|
||||
|
||||
PxShape* to = physics.createShape(from.getGeometry(), materials.begin(), materialCount, isExclusive, from.getFlags());
|
||||
|
||||
to->setLocalPose(from.getLocalPose());
|
||||
to->setContactOffset(from.getContactOffset());
|
||||
to->setRestOffset(from.getRestOffset());
|
||||
to->setSimulationFilterData(from.getSimulationFilterData());
|
||||
to->setQueryFilterData(from.getQueryFilterData());
|
||||
to->setTorsionalPatchRadius(from.getTorsionalPatchRadius());
|
||||
to->setMinTorsionalPatchRadius(from.getMinTorsionalPatchRadius());
|
||||
return to;
|
||||
}
|
||||
|
||||
static void copyStaticProperties(PxPhysics& physics, PxRigidActor& to, const PxRigidActor& from)
|
||||
{
|
||||
PxInlineArray<PxShape*, 64> shapes;
|
||||
shapes.resize(from.getNbShapes());
|
||||
|
||||
PxU32 shapeCount = from.getNbShapes();
|
||||
from.getShapes(shapes.begin(), shapeCount);
|
||||
|
||||
for(PxU32 i = 0; i < shapeCount; i++)
|
||||
{
|
||||
PxShape* s = shapes[i];
|
||||
if(!s->isExclusive())
|
||||
to.attachShape(*s);
|
||||
else
|
||||
{
|
||||
PxShape* newShape = physx::PxCloneShape(physics, *s, true);
|
||||
to.attachShape(*newShape);
|
||||
newShape->release();
|
||||
}
|
||||
}
|
||||
|
||||
to.setActorFlags(from.getActorFlags());
|
||||
to.setOwnerClient(from.getOwnerClient());
|
||||
to.setDominanceGroup(from.getDominanceGroup());
|
||||
to.setEnvironmentID(from.getEnvironmentID());
|
||||
}
|
||||
|
||||
PxRigidStatic* PxCloneStatic(PxPhysics& physicsSDK,
|
||||
const PxTransform& transform,
|
||||
const PxRigidActor& from)
|
||||
{
|
||||
PxRigidStatic* to = physicsSDK.createRigidStatic(transform);
|
||||
if(!to)
|
||||
return NULL;
|
||||
|
||||
copyStaticProperties(physicsSDK, *to, from);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
PxRigidDynamic* PxCloneDynamic(PxPhysics& physicsSDK,
|
||||
const PxTransform& transform,
|
||||
const PxRigidDynamic& from)
|
||||
{
|
||||
PxRigidDynamic* to = physicsSDK.createRigidDynamic(transform);
|
||||
if(!to)
|
||||
return NULL;
|
||||
|
||||
copyStaticProperties(physicsSDK, *to, from);
|
||||
|
||||
to->setRigidBodyFlags(from.getRigidBodyFlags());
|
||||
|
||||
to->setMass(from.getMass());
|
||||
to->setMassSpaceInertiaTensor(from.getMassSpaceInertiaTensor());
|
||||
to->setCMassLocalPose(from.getCMassLocalPose());
|
||||
|
||||
to->setLinearVelocity(from.getLinearVelocity());
|
||||
to->setAngularVelocity(from.getAngularVelocity());
|
||||
|
||||
to->setLinearDamping(from.getLinearDamping());
|
||||
to->setAngularDamping(from.getAngularDamping());
|
||||
|
||||
PxU32 posIters, velIters;
|
||||
from.getSolverIterationCounts(posIters, velIters);
|
||||
to->setSolverIterationCounts(posIters, velIters);
|
||||
|
||||
to->setMaxLinearVelocity(from.getMaxLinearVelocity());
|
||||
to->setMaxAngularVelocity(from.getMaxAngularVelocity());
|
||||
to->setMaxDepenetrationVelocity(from.getMaxDepenetrationVelocity());
|
||||
to->setSleepThreshold(from.getSleepThreshold());
|
||||
to->setStabilizationThreshold(from.getStabilizationThreshold());
|
||||
to->setMinCCDAdvanceCoefficient(from.getMinCCDAdvanceCoefficient());
|
||||
to->setContactReportThreshold(from.getContactReportThreshold());
|
||||
to->setMaxContactImpulse(from.getMaxContactImpulse());
|
||||
|
||||
PxTransform target;
|
||||
if (from.getKinematicTarget(target))
|
||||
to->setKinematicTarget(target);
|
||||
|
||||
to->setRigidDynamicLockFlags(from.getRigidDynamicLockFlags());
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
static PxTransform scalePosition(const PxTransform& t, PxReal scale)
|
||||
{
|
||||
return PxTransform(t.p*scale, t.q);
|
||||
}
|
||||
|
||||
void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(scale > 0,
|
||||
"PxScaleRigidActor requires that the scale parameter is greater than zero");
|
||||
|
||||
PxInlineArray<PxShape*, 64> shapes;
|
||||
shapes.resize(actor.getNbShapes());
|
||||
actor.getShapes(shapes.begin(), shapes.size());
|
||||
|
||||
for(PxU32 i=0;i<shapes.size();i++)
|
||||
{
|
||||
shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale));
|
||||
PxGeometryHolder h(shapes[i]->getGeometry());
|
||||
|
||||
switch(h.getType())
|
||||
{
|
||||
case PxGeometryType::eSPHERE:
|
||||
h.sphere().radius *= scale;
|
||||
break;
|
||||
case PxGeometryType::ePLANE:
|
||||
break;
|
||||
case PxGeometryType::eCAPSULE:
|
||||
h.capsule().halfHeight *= scale;
|
||||
h.capsule().radius *= scale;
|
||||
break;
|
||||
case PxGeometryType::eBOX:
|
||||
h.box().halfExtents *= scale;
|
||||
break;
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
h.convexMesh().scale.scale *= scale;
|
||||
break;
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
h.triangleMesh().scale.scale *= scale;
|
||||
break;
|
||||
case PxGeometryType::eHEIGHTFIELD:
|
||||
h.heightField().heightScale *= scale;
|
||||
h.heightField().rowScale *= scale;
|
||||
h.heightField().columnScale *= scale;
|
||||
break;
|
||||
default:
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
shapes[i]->setGeometry(h.any());
|
||||
}
|
||||
|
||||
if(!scaleMassProps)
|
||||
return;
|
||||
|
||||
PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>();
|
||||
if(!dynamic)
|
||||
return;
|
||||
|
||||
PxReal scale3 = scale*scale*scale;
|
||||
dynamic->setMass(dynamic->getMass()*scale3);
|
||||
dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale);
|
||||
dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale));
|
||||
}
|
||||
}
|
||||
143
engine/third_party/physx/source/physxextensions/src/ExtSmoothNormals.cpp
vendored
Normal file
143
engine/third_party/physx/source/physxextensions/src/ExtSmoothNormals.cpp
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// 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 "extensions/PxSmoothNormals.h"
|
||||
|
||||
#include "foundation/PxMathUtils.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static PxReal computeAngle(const PxVec3* verts, const PxU32* refs, PxU32 vref)
|
||||
{
|
||||
PxU32 e0=0,e2=0;
|
||||
if(vref==refs[0])
|
||||
{
|
||||
e0 = 2;
|
||||
e2 = 1;
|
||||
}
|
||||
else if(vref==refs[1])
|
||||
{
|
||||
e0 = 2;
|
||||
e2 = 0;
|
||||
}
|
||||
else if(vref==refs[2])
|
||||
{
|
||||
e0 = 0;
|
||||
e2 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
const PxVec3 edge0 = verts[refs[e0]] - verts[vref];
|
||||
const PxVec3 edge1 = verts[refs[e2]] - verts[vref];
|
||||
|
||||
return PxComputeAngle(edge0, edge1);
|
||||
}
|
||||
|
||||
bool PxBuildSmoothNormals(PxU32 nbTris, PxU32 nbVerts, const PxVec3* verts, const PxU32* dFaces, const PxU16* wFaces, PxVec3* normals, bool flip)
|
||||
{
|
||||
if(!verts || !normals || !nbTris || !nbVerts)
|
||||
return false;
|
||||
|
||||
// Get correct destination buffers
|
||||
// - if available, write directly to user-provided buffers
|
||||
// - else get some ram and keep track of it
|
||||
PxVec3* FNormals = PX_ALLOCATE(PxVec3, nbTris, "PxVec3");
|
||||
if(!FNormals) return false;
|
||||
|
||||
// Compute face normals
|
||||
const PxU32 c = PxU32(flip!=0);
|
||||
for(PxU32 i=0; i<nbTris; i++)
|
||||
{
|
||||
// compute indices outside of array index to workaround
|
||||
// SNC bug which was generating incorrect addresses
|
||||
const PxU32 i0 = i*3+0;
|
||||
const PxU32 i1 = i*3+1+c;
|
||||
const PxU32 i2 = i*3+2-c;
|
||||
|
||||
const PxU32 Ref0 = dFaces ? dFaces[i0] : wFaces ? wFaces[i0] : 0;
|
||||
const PxU32 Ref1 = dFaces ? dFaces[i1] : wFaces ? wFaces[i1] : 1;
|
||||
const PxU32 Ref2 = dFaces ? dFaces[i2] : wFaces ? wFaces[i2] : 2;
|
||||
|
||||
FNormals[i] = (verts[Ref2]-verts[Ref0]).cross(verts[Ref1] - verts[Ref0]);
|
||||
PX_ASSERT(!FNormals[i].isZero());
|
||||
FNormals[i].normalize();
|
||||
}
|
||||
|
||||
// Compute vertex normals
|
||||
PxMemSet(normals, 0, nbVerts*sizeof(PxVec3));
|
||||
|
||||
// TTP 3751
|
||||
PxVec3* TmpNormals = PX_ALLOCATE(PxVec3, nbVerts, "PxVec3");
|
||||
PxMemSet(TmpNormals, 0, nbVerts*sizeof(PxVec3));
|
||||
for(PxU32 i=0;i<nbTris;i++)
|
||||
{
|
||||
PxU32 Ref[3];
|
||||
Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0;
|
||||
Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1;
|
||||
Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2;
|
||||
|
||||
for(PxU32 j=0;j<3;j++)
|
||||
{
|
||||
if(TmpNormals[Ref[j]].isZero())
|
||||
TmpNormals[Ref[j]] = FNormals[i];
|
||||
}
|
||||
}
|
||||
//~TTP 3751
|
||||
|
||||
for(PxU32 i=0;i<nbTris;i++)
|
||||
{
|
||||
PxU32 Ref[3];
|
||||
Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0;
|
||||
Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1;
|
||||
Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2;
|
||||
|
||||
normals[Ref[0]] += FNormals[i] * computeAngle(verts, Ref, Ref[0]);
|
||||
normals[Ref[1]] += FNormals[i] * computeAngle(verts, Ref, Ref[1]);
|
||||
normals[Ref[2]] += FNormals[i] * computeAngle(verts, Ref, Ref[2]);
|
||||
}
|
||||
|
||||
// Normalize vertex normals
|
||||
for(PxU32 i=0;i<nbVerts;i++)
|
||||
{
|
||||
if(normals[i].isZero())
|
||||
normals[i] = TmpNormals[i];
|
||||
// PX_ASSERT(!normals[i].isZero());
|
||||
normals[i].normalize();
|
||||
}
|
||||
|
||||
PX_FREE(TmpNormals); // TTP 3751
|
||||
PX_FREE(FNormals);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
225
engine/third_party/physx/source/physxextensions/src/ExtSphericalJoint.cpp
vendored
Normal file
225
engine/third_party/physx/source/physxextensions/src/ExtSphericalJoint.cpp
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
// 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 "ExtSphericalJoint.h"
|
||||
#include "ExtConstraintHelper.h"
|
||||
#include "CmConeLimitHelper.h"
|
||||
#include "omnipvd/ExtOmniPvdSetData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Ext;
|
||||
|
||||
SphericalJoint::SphericalJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1) :
|
||||
SphericalJointT(PxJointConcreteType::eSPHERICAL, actor0, localFrame0, actor1, localFrame1, "SphericalJointData")
|
||||
{
|
||||
SphericalJointData* data = static_cast<SphericalJointData*>(mData);
|
||||
|
||||
data->limit = PxJointLimitCone(PxPi/2, PxPi/2);
|
||||
data->jointFlags = PxSphericalJointFlags();
|
||||
}
|
||||
|
||||
void SphericalJoint::setLimitCone(const PxJointLimitCone &limit)
|
||||
{
|
||||
PX_CHECK_AND_RETURN(limit.isValid(), "PxSphericalJoint::setLimit: invalid parameter");
|
||||
data().limit = limit;
|
||||
markDirty();
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxSphericalJoint& j = static_cast<PxSphericalJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitYAngle, j, limit.yAngle)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitZAngle, j, limit.zAngle)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
#endif
|
||||
}
|
||||
|
||||
PxJointLimitCone SphericalJoint::getLimitCone() const
|
||||
{
|
||||
return data().limit;
|
||||
}
|
||||
|
||||
PxSphericalJointFlags SphericalJoint::getSphericalJointFlags() const
|
||||
{
|
||||
return data().jointFlags;
|
||||
}
|
||||
|
||||
void SphericalJoint::setSphericalJointFlags(PxSphericalJointFlags flags)
|
||||
{
|
||||
data().jointFlags = flags;
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, jointFlags, static_cast<PxSphericalJoint&>(*this), flags)
|
||||
}
|
||||
|
||||
void SphericalJoint::setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value)
|
||||
{
|
||||
if(value)
|
||||
data().jointFlags |= flag;
|
||||
else
|
||||
data().jointFlags &= ~flag;
|
||||
markDirty();
|
||||
|
||||
OMNI_PVD_SET(OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, jointFlags, static_cast<PxSphericalJoint&>(*this), getSphericalJointFlags())
|
||||
}
|
||||
|
||||
PxReal SphericalJoint::getSwingYAngle() const
|
||||
{
|
||||
return getSwingYAngle_Internal();
|
||||
}
|
||||
|
||||
PxReal SphericalJoint::getSwingZAngle() const
|
||||
{
|
||||
return getSwingZAngle_Internal();
|
||||
}
|
||||
|
||||
static void SphericalJointVisualize(PxConstraintVisualizer& viz, const void* constantBlock, const PxTransform& body0Transform, const PxTransform& body1Transform, PxU32 flags)
|
||||
{
|
||||
const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::computeJointFrames(cA2w, cB2w, data, body0Transform, body1Transform);
|
||||
if(flags & PxConstraintVisualizationFlag::eLOCAL_FRAMES)
|
||||
viz.visualizeJointFrames(cA2w, cB2w);
|
||||
|
||||
if((flags & PxConstraintVisualizationFlag::eLIMITS) && (data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED))
|
||||
{
|
||||
joint::applyNeighborhoodOperator(cA2w, cB2w);
|
||||
|
||||
const PxTransform cB2cA = cA2w.transformInv(cB2w);
|
||||
PxQuat swing, twist;
|
||||
PxSeparateSwingTwist(cB2cA.q, swing, twist);
|
||||
|
||||
viz.visualizeLimitCone(cA2w, PxTan(data.limit.zAngle/4), PxTan(data.limit.yAngle/4));
|
||||
}
|
||||
}
|
||||
|
||||
//TAG:solverprepshader
|
||||
static PxU32 SphericalJointSolverPrep(Px1DConstraint* constraints,
|
||||
PxVec3p& body0WorldOffset,
|
||||
PxU32 /*maxConstraints*/,
|
||||
PxConstraintInvMassScale& invMassScale,
|
||||
const void* constantBlock,
|
||||
const PxTransform& bA2w,
|
||||
const PxTransform& bB2w,
|
||||
bool /*useExtendedLimits*/,
|
||||
PxVec3p& cA2wOut, PxVec3p& cB2wOut)
|
||||
{
|
||||
const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock);
|
||||
|
||||
PxTransform32 cA2w, cB2w;
|
||||
joint::ConstraintHelper ch(constraints, invMassScale, cA2w, cB2w, body0WorldOffset, data, bA2w, bB2w);
|
||||
|
||||
joint::applyNeighborhoodOperator(cA2w, cB2w);
|
||||
|
||||
if(data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED)
|
||||
{
|
||||
PxQuat swing, twist;
|
||||
PxSeparateSwingTwist(cA2w.q.getConjugate() * cB2w.q, swing, twist);
|
||||
PX_ASSERT(PxAbs(swing.x)<1e-6f);
|
||||
|
||||
PxVec3 axis;
|
||||
PxReal error;
|
||||
const Cm::ConeLimitHelperTanLess coneHelper(data.limit.yAngle, data.limit.zAngle);
|
||||
coneHelper.getLimit(swing, axis, error);
|
||||
ch.angularLimit(cA2w.rotate(axis), error, data.limit);
|
||||
}
|
||||
|
||||
PxVec3 ra, rb;
|
||||
ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, 0, ra, rb);
|
||||
cA2wOut = ra + bA2w.p;
|
||||
cB2wOut = rb + bB2w.p;
|
||||
|
||||
return ch.getCount();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxConstraintShaderTable gSphericalJointShaders = { SphericalJointSolverPrep, SphericalJointVisualize, PxConstraintFlag::Enum(0) };
|
||||
|
||||
PxConstraintSolverPrep SphericalJoint::getPrep() const { return gSphericalJointShaders.solverPrep; }
|
||||
|
||||
PxSphericalJoint* physx::PxSphericalJointCreate(PxPhysics& physics, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1)
|
||||
{
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxSphericalJointCreate: local frame 0 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxSphericalJointCreate: local frame 1 is not a valid transform");
|
||||
PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxSphericalJointCreate: actors must be different");
|
||||
PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxSphericalJointCreate: at least one actor must be dynamic");
|
||||
|
||||
return createJointT<SphericalJoint, SphericalJointData>(physics, actor0, localFrame0, actor1, localFrame1, gSphericalJointShaders);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
void SphericalJoint::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
mPxConstraint = resolveConstraintPtr(context, mPxConstraint, this, gSphericalJointShaders);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
void SphericalJoint::updateOmniPvdProperties() const
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
const PxSphericalJoint& j = static_cast<const PxSphericalJoint&>(*this);
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, swingYAngle, j, getSwingYAngle())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, swingZAngle, j, getSwingZAngle())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
template<>
|
||||
void physx::Ext::omniPvdInitJoint<SphericalJoint>(SphericalJoint& joint)
|
||||
{
|
||||
OMNI_PVD_WRITE_SCOPE_BEGIN(pvdWriter, pvdRegData)
|
||||
|
||||
PxSphericalJoint& j = static_cast<PxSphericalJoint&>(joint);
|
||||
OMNI_PVD_CREATE_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, j);
|
||||
omniPvdSetBaseJointParams(static_cast<PxJoint&>(joint), PxJointConcreteType::eSPHERICAL);
|
||||
|
||||
PxJointLimitCone limit = joint.getLimitCone();
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitYAngle, j, limit.yAngle)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitZAngle, j, limit.zAngle)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitRestitution, j, limit.restitution)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitBounceThreshold, j, limit.bounceThreshold)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitStiffness, j, limit.stiffness)
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, limitDamping, j, limit.damping)
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, jointFlags, j, joint.getSphericalJointFlags())
|
||||
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, swingYAngle, j, joint.getSwingYAngle())
|
||||
OMNI_PVD_SET_EXPLICIT(pvdWriter, pvdRegData, OMNI_PVD_CONTEXT_HANDLE, PxSphericalJoint, swingZAngle, j, joint.getSwingZAngle())
|
||||
|
||||
OMNI_PVD_WRITE_SCOPE_END
|
||||
}
|
||||
|
||||
#endif
|
||||
84
engine/third_party/physx/source/physxextensions/src/ExtSphericalJoint.h
vendored
Normal file
84
engine/third_party/physx/source/physxextensions/src/ExtSphericalJoint.h
vendored
Normal 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 EXT_SPHERICAL_JOINT_H
|
||||
#define EXT_SPHERICAL_JOINT_H
|
||||
|
||||
#include "extensions/PxSphericalJoint.h"
|
||||
|
||||
#include "ExtJoint.h"
|
||||
#include "CmUtils.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxSphericalJointGeneratedValues;
|
||||
namespace Ext
|
||||
{
|
||||
struct SphericalJointData: public JointData
|
||||
{
|
||||
PxJointLimitCone limit;
|
||||
|
||||
PxSphericalJointFlags jointFlags;
|
||||
private:
|
||||
SphericalJointData(const PxJointLimitCone& cone) : limit(cone) {}
|
||||
};
|
||||
|
||||
typedef JointT<PxSphericalJoint, SphericalJointData, PxSphericalJointGeneratedValues> SphericalJointT;
|
||||
|
||||
class SphericalJoint : public SphericalJointT
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
SphericalJoint(PxBaseFlags baseFlags) : SphericalJointT(baseFlags) {}
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
static SphericalJoint* createObject(PxU8*& address, PxDeserializationContext& context) { return createJointObject<SphericalJoint>(address, context); }
|
||||
//~PX_SERIALIZATION
|
||||
SphericalJoint(const PxTolerancesScale& /*scale*/, PxRigidActor* actor0, const PxTransform& localFrame0, PxRigidActor* actor1, const PxTransform& localFrame1);
|
||||
// PxSphericalJoint
|
||||
virtual void setLimitCone(const PxJointLimitCone &limit) PX_OVERRIDE;
|
||||
virtual PxJointLimitCone getLimitCone() const PX_OVERRIDE;
|
||||
virtual void setSphericalJointFlags(PxSphericalJointFlags flags) PX_OVERRIDE;
|
||||
virtual void setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value) PX_OVERRIDE;
|
||||
virtual PxSphericalJointFlags getSphericalJointFlags() const PX_OVERRIDE;
|
||||
virtual PxReal getSwingYAngle() const PX_OVERRIDE;
|
||||
virtual PxReal getSwingZAngle() const PX_OVERRIDE;
|
||||
//~PxSphericalJoint
|
||||
|
||||
// PxConstraintConnector
|
||||
virtual PxConstraintSolverPrep getPrep() const PX_OVERRIDE;
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
virtual void updateOmniPvdProperties() const PX_OVERRIDE;
|
||||
#endif
|
||||
//~PxConstraintConnector
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
578
engine/third_party/physx/source/physxextensions/src/ExtSqManager.cpp
vendored
Normal file
578
engine/third_party/physx/source/physxextensions/src/ExtSqManager.cpp
vendored
Normal file
@@ -0,0 +1,578 @@
|
||||
// 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 "ExtSqManager.h"
|
||||
#define SQ_DEBUG_VIZ_STATIC_COLOR PxU32(PxDebugColor::eARGB_BLUE)
|
||||
#define SQ_DEBUG_VIZ_DYNAMIC_COLOR PxU32(PxDebugColor::eARGB_RED)
|
||||
#define SQ_DEBUG_VIZ_STATIC_COLOR2 PxU32(PxDebugColor::eARGB_DARKBLUE)
|
||||
#define SQ_DEBUG_VIZ_DYNAMIC_COLOR2 PxU32(PxDebugColor::eARGB_DARKRED)
|
||||
#define SQ_DEBUG_VIZ_COMPOUND_COLOR PxU32(PxDebugColor::eARGB_MAGENTA)
|
||||
#include "GuBounds.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sq;
|
||||
using namespace Gu;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SqFactory.h"
|
||||
#include "common/PxProfileZone.h"
|
||||
#include "common/PxRenderBuffer.h"
|
||||
#include "GuBVH.h"
|
||||
#include "foundation/PxAlloca.h"
|
||||
|
||||
// PT: this is a customized version of physx::Sq::PrunerManager that supports more than 2 hardcoded pruners.
|
||||
// It might not be possible to support the whole PxSceneQuerySystem API with an arbitrary number of pruners.
|
||||
|
||||
ExtPrunerManager::ExtPrunerManager(PxU64 contextID, float inflation, const Adapter& adapter, bool usesTreeOfPruners) :
|
||||
mAdapter (adapter),
|
||||
mTreeOfPruners (NULL),
|
||||
mContextID (contextID),
|
||||
mStaticTimestamp (0),
|
||||
mRebuildRateHint (100),
|
||||
mInflation (inflation),
|
||||
mPrunerNeedsUpdating (false),
|
||||
mTimestampNeedsUpdating (false),
|
||||
mUsesTreeOfPruners (usesTreeOfPruners)
|
||||
{
|
||||
mCompoundPrunerExt.mPruner = createCompoundPruner(contextID);
|
||||
}
|
||||
|
||||
ExtPrunerManager::~ExtPrunerManager()
|
||||
{
|
||||
PX_DELETE(mTreeOfPruners);
|
||||
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
PX_DELETE(pe);
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 ExtPrunerManager::addPruner(Pruner* pruner, PxU32 preallocated)
|
||||
{
|
||||
const PxU32 index = mPrunerExt.size();
|
||||
PrunerExt* pe = PX_NEW(PrunerExt);
|
||||
pe->init(pruner);
|
||||
if(preallocated)
|
||||
pe->preallocate(preallocated);
|
||||
mPrunerExt.pushBack(pe);
|
||||
return index;
|
||||
}
|
||||
|
||||
void ExtPrunerManager::preallocate(PxU32 prunerIndex, PxU32 nbShapes)
|
||||
{
|
||||
const bool preallocateCompoundPruner = prunerIndex==0xffffffff;
|
||||
if(preallocateCompoundPruner)
|
||||
{
|
||||
mCompoundPrunerExt.preallocate(nbShapes);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
mPrunerExt[prunerIndex]->preallocate(nbShapes);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::flushMemory()
|
||||
{
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
pe->flushMemory();
|
||||
}
|
||||
|
||||
mCompoundPrunerExt.flushMemory();
|
||||
}
|
||||
|
||||
PrunerHandle ExtPrunerManager::addPrunerShape(const PrunerPayload& payload, PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, const PxBounds3& bounds, const PxTransform& transform, bool hasPruningStructure)
|
||||
{
|
||||
if(compoundId==INVALID_COMPOUND_ID && prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return INVALID_PRUNERHANDLE;
|
||||
}
|
||||
|
||||
mPrunerNeedsUpdating = true;
|
||||
|
||||
if(!dynamic)
|
||||
invalidateStaticTimestamp();
|
||||
|
||||
PrunerHandle handle;
|
||||
if(compoundId == INVALID_COMPOUND_ID)
|
||||
{
|
||||
PX_ASSERT(prunerIndex<mPrunerExt.size());
|
||||
PX_ASSERT(mPrunerExt[prunerIndex]->pruner());
|
||||
mPrunerExt[prunerIndex]->pruner()->addObjects(&handle, &bounds, &payload, &transform, 1, hasPruningStructure);
|
||||
//mPrunerExt[prunerIndex].growDirtyList(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(mCompoundPrunerExt.pruner());
|
||||
mCompoundPrunerExt.pruner()->addObject(compoundId, handle, bounds, payload, transform);
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ExtPrunerManager::removePrunerShape(PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, PrunerHandle shapeHandle, PrunerPayloadRemovalCallback* removalCallback)
|
||||
{
|
||||
if(compoundId==INVALID_COMPOUND_ID && prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
mPrunerNeedsUpdating = true;
|
||||
|
||||
if(!dynamic)
|
||||
invalidateStaticTimestamp();
|
||||
|
||||
if(compoundId == INVALID_COMPOUND_ID)
|
||||
{
|
||||
PX_ASSERT(prunerIndex<mPrunerExt.size());
|
||||
PX_ASSERT(mPrunerExt[prunerIndex]->pruner());
|
||||
|
||||
mPrunerExt[prunerIndex]->removeFromDirtyList(shapeHandle);
|
||||
mPrunerExt[prunerIndex]->pruner()->removeObjects(&shapeHandle, 1, removalCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCompoundPrunerExt.removeFromDirtyList(compoundId, shapeHandle);
|
||||
mCompoundPrunerExt.pruner()->removeObject(compoundId, shapeHandle, removalCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::markForUpdate(PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, PrunerHandle shapeHandle, const PxTransform& transform)
|
||||
{
|
||||
if(compoundId==INVALID_COMPOUND_ID && prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
mPrunerNeedsUpdating = true;
|
||||
|
||||
if(!dynamic)
|
||||
invalidateStaticTimestamp();
|
||||
|
||||
if(compoundId == INVALID_COMPOUND_ID)
|
||||
{
|
||||
PX_ASSERT(prunerIndex<mPrunerExt.size());
|
||||
PX_ASSERT(mPrunerExt[prunerIndex]->pruner());
|
||||
|
||||
// PT: TODO: at this point do we still need a dirty list? we could just update the bounds directly?
|
||||
mPrunerExt[prunerIndex]->addToDirtyList(shapeHandle, dynamic, transform);
|
||||
}
|
||||
else
|
||||
mCompoundPrunerExt.addToDirtyList(compoundId, shapeHandle, transform);
|
||||
}
|
||||
|
||||
void ExtPrunerManager::setDynamicTreeRebuildRateHint(PxU32 rebuildRateHint)
|
||||
{
|
||||
mRebuildRateHint = rebuildRateHint;
|
||||
|
||||
// PT: we are still using the same rebuild hint for all pruners here, which may or may
|
||||
// not make sense. We could also have a different build rate for each pruner.
|
||||
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
Pruner* pruner = pe->pruner();
|
||||
if(pruner && pruner->isDynamic())
|
||||
static_cast<DynamicPruner*>(pruner)->setRebuildRateHint(rebuildRateHint);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::afterSync(bool buildStep, bool commit)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.sceneQueryBuildStep", mContextID);
|
||||
|
||||
if(!buildStep && !commit)
|
||||
{
|
||||
mPrunerNeedsUpdating = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// flush user modified objects
|
||||
flushShapes();
|
||||
|
||||
// PT: TODO: with N pruners this part would be worth multi-threading
|
||||
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
Pruner* pruner = pe->pruner();
|
||||
if(pruner)
|
||||
{
|
||||
if(pruner->isDynamic())
|
||||
static_cast<DynamicPruner*>(pruner)->buildStep(true);
|
||||
|
||||
if(commit)
|
||||
pruner->commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(commit)
|
||||
{
|
||||
if(mUsesTreeOfPruners)
|
||||
createTreeOfPruners();
|
||||
}
|
||||
|
||||
mPrunerNeedsUpdating = !commit;
|
||||
}
|
||||
|
||||
void ExtPrunerManager::flushShapes()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.flushShapes", mContextID);
|
||||
|
||||
// must already have acquired writer lock here
|
||||
|
||||
const float inflation = 1.0f + mInflation;
|
||||
|
||||
bool mustInvalidateStaticTimestamp = false;
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
if(pe->processDirtyList(i, mAdapter, inflation))
|
||||
mustInvalidateStaticTimestamp = true;
|
||||
}
|
||||
|
||||
if(mustInvalidateStaticTimestamp)
|
||||
invalidateStaticTimestamp();
|
||||
|
||||
mCompoundPrunerExt.flushShapes(mAdapter, inflation);
|
||||
}
|
||||
|
||||
void ExtPrunerManager::flushUpdates()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.flushUpdates", mContextID);
|
||||
|
||||
if(mPrunerNeedsUpdating)
|
||||
{
|
||||
// no need to take lock if manual sq update is enabled
|
||||
// as flushUpdates will only be called from NpScene::flushQueryUpdates()
|
||||
mSQLock.lock();
|
||||
|
||||
if(mPrunerNeedsUpdating)
|
||||
{
|
||||
flushShapes();
|
||||
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
if(pe->pruner())
|
||||
pe->pruner()->commit();
|
||||
}
|
||||
|
||||
if(mUsesTreeOfPruners)
|
||||
createTreeOfPruners();
|
||||
|
||||
PxMemoryBarrier();
|
||||
mPrunerNeedsUpdating = false;
|
||||
}
|
||||
mSQLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::forceRebuildDynamicTree(PxU32 prunerIndex)
|
||||
{
|
||||
// PT: beware here when called from the PxScene, the prunerIndex may not match
|
||||
|
||||
PX_PROFILE_ZONE("SceneQuery.forceDynamicTreeRebuild", mContextID);
|
||||
|
||||
if(prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
PxMutex::ScopedLock lock(mSQLock);
|
||||
|
||||
PrunerExt* pe = mPrunerExt[prunerIndex];
|
||||
Pruner* pruner = pe->pruner();
|
||||
|
||||
if(pruner && pruner->isDynamic())
|
||||
{
|
||||
static_cast<DynamicPruner*>(pruner)->purge();
|
||||
static_cast<DynamicPruner*>(pruner)->commit();
|
||||
}
|
||||
}
|
||||
|
||||
void* ExtPrunerManager::prepareSceneQueriesUpdate(PxU32 prunerIndex)
|
||||
{
|
||||
// PT: beware here when called from the PxScene, the prunerIndex may not match
|
||||
|
||||
if(prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PX_ASSERT(mPrunerExt[prunerIndex]->pruner());
|
||||
|
||||
bool retVal = false;
|
||||
Pruner* pruner = mPrunerExt[prunerIndex]->pruner();
|
||||
if(pruner && pruner->isDynamic())
|
||||
retVal = static_cast<DynamicPruner*>(pruner)->prepareBuild();
|
||||
|
||||
return retVal ? pruner : NULL;
|
||||
}
|
||||
|
||||
void ExtPrunerManager::sceneQueryBuildStep(void* handle)
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.sceneQueryBuildStep", mContextID);
|
||||
|
||||
Pruner* pruner = reinterpret_cast<Pruner*>(handle);
|
||||
|
||||
if(pruner && pruner->isDynamic())
|
||||
{
|
||||
const bool buildFinished = static_cast<DynamicPruner*>(pruner)->buildStep(false);
|
||||
if(buildFinished)
|
||||
mPrunerNeedsUpdating = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::visualize(PxU32 prunerIndex, PxRenderOutput& out) const
|
||||
{
|
||||
// PT: beware here when called from the PxScene, the prunerIndex may not match
|
||||
// This is quite awkward and should be improved.
|
||||
|
||||
// PT: problem here is that this function will be called by the regular PhysX scene when plugged to its PxSceneDesc,
|
||||
// and the calling code only understands the regular PhysX pruners.
|
||||
|
||||
const bool visualizeCompoundPruner = prunerIndex==0xffffffff;
|
||||
if(visualizeCompoundPruner)
|
||||
{
|
||||
const CompoundPruner* cp = mCompoundPrunerExt.pruner();
|
||||
if(cp)
|
||||
cp->visualizeEx(out, SQ_DEBUG_VIZ_COMPOUND_COLOR, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
PrunerExt* pe = mPrunerExt[prunerIndex];
|
||||
Pruner* pruner = pe->pruner();
|
||||
if(pruner)
|
||||
{
|
||||
// PT: TODO: this doesn't really work: the static color was for static shapes but they
|
||||
// could still be stored in a dynamic pruner. So this code doesn't use a color scheme
|
||||
// consistent with what we use in the default code.
|
||||
if(pruner->isDynamic())
|
||||
{
|
||||
//if(visDynamic)
|
||||
pruner->visualize(out, SQ_DEBUG_VIZ_DYNAMIC_COLOR, SQ_DEBUG_VIZ_DYNAMIC_COLOR2);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if(visStatic)
|
||||
pruner->visualize(out, SQ_DEBUG_VIZ_STATIC_COLOR, SQ_DEBUG_VIZ_STATIC_COLOR2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::shiftOrigin(const PxVec3& shift)
|
||||
{
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
Pruner* pruner = pe->pruner();
|
||||
if(pruner)
|
||||
pruner->shiftOrigin(shift);
|
||||
}
|
||||
|
||||
mCompoundPrunerExt.pruner()->shiftOrigin(shift);
|
||||
}
|
||||
|
||||
void ExtPrunerManager::addCompoundShape(const PxBVH& pxbvh, PrunerCompoundId compoundId, const PxTransform& compoundTransform, PrunerHandle* prunerHandle, const PrunerPayload* payloads, const PxTransform* transforms, bool isDynamic)
|
||||
{
|
||||
const Gu::BVH& bvh = static_cast<const Gu::BVH&>(pxbvh);
|
||||
|
||||
PX_ASSERT(mCompoundPrunerExt.mPruner);
|
||||
mCompoundPrunerExt.mPruner->addCompound(prunerHandle, bvh, compoundId, compoundTransform, isDynamic, payloads, transforms);
|
||||
if(!isDynamic)
|
||||
invalidateStaticTimestamp();
|
||||
}
|
||||
|
||||
void ExtPrunerManager::updateCompoundActor(PrunerCompoundId compoundId, const PxTransform& compoundTransform)
|
||||
{
|
||||
PX_ASSERT(mCompoundPrunerExt.mPruner);
|
||||
const bool isDynamic = mCompoundPrunerExt.mPruner->updateCompound(compoundId, compoundTransform);
|
||||
if(!isDynamic)
|
||||
invalidateStaticTimestamp();
|
||||
}
|
||||
|
||||
void ExtPrunerManager::removeCompoundActor(PrunerCompoundId compoundId, PrunerPayloadRemovalCallback* removalCallback)
|
||||
{
|
||||
PX_ASSERT(mCompoundPrunerExt.mPruner);
|
||||
const bool isDynamic = mCompoundPrunerExt.mPruner->removeCompound(compoundId, removalCallback);
|
||||
if(!isDynamic)
|
||||
invalidateStaticTimestamp();
|
||||
}
|
||||
|
||||
void ExtPrunerManager::sync(PxU32 prunerIndex, const PrunerHandle* handles, const PxU32* boundsIndices, const PxBounds3* bounds, const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices)
|
||||
{
|
||||
if(!count)
|
||||
return;
|
||||
|
||||
if(prunerIndex>=mPrunerExt.size())
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Invalid pruner index");
|
||||
return;
|
||||
}
|
||||
|
||||
Pruner* pruner = getPruner(prunerIndex);
|
||||
if(!pruner)
|
||||
return;
|
||||
|
||||
PxU32 startIndex = 0;
|
||||
PxU32 numIndices = count;
|
||||
|
||||
// if shape sim map is not empty, parse the indices and skip update for the dirty one
|
||||
if(ignoredIndices.count())
|
||||
{
|
||||
// PT: I think this codepath was used with SCB / buffered changes, but it's not needed anymore
|
||||
numIndices = 0;
|
||||
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
// if(ignoredIndices.test(boundsIndices[i]))
|
||||
if(ignoredIndices.boundedTest(boundsIndices[i]))
|
||||
{
|
||||
pruner->updateObjects(handles + startIndex, numIndices, mInflation, boundsIndices + startIndex, bounds, transforms);
|
||||
numIndices = 0;
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else
|
||||
numIndices++;
|
||||
}
|
||||
// PT: we fallback to the next line on purpose - no "else"
|
||||
}
|
||||
|
||||
pruner->updateObjects(handles + startIndex, numIndices, mInflation, boundsIndices + startIndex, bounds, transforms);
|
||||
}
|
||||
|
||||
PxU32 ExtPrunerManager::startCustomBuildstep()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.startCustomBuildstep", mContextID);
|
||||
|
||||
// flush user modified objects
|
||||
//flushShapes();
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.flushShapes", mContextID);
|
||||
// PT: only flush the compound pruner synchronously
|
||||
// must already have acquired writer lock here
|
||||
const float inflation = 1.0f + mInflation;
|
||||
mCompoundPrunerExt.flushShapes(mAdapter, inflation);
|
||||
}
|
||||
|
||||
mTimestampNeedsUpdating = false;
|
||||
|
||||
return mPrunerExt.size();
|
||||
}
|
||||
|
||||
void ExtPrunerManager::customBuildstep(PxU32 index)
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.customBuildstep", mContextID);
|
||||
|
||||
PX_ASSERT(index<mPrunerExt.size());
|
||||
|
||||
PrunerExt* pe = mPrunerExt[index];
|
||||
Pruner* pruner = pe->pruner();
|
||||
|
||||
//void ExtPrunerManager::flushShapes()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.flushShapes", mContextID);
|
||||
// must already have acquired writer lock here
|
||||
const float inflation = 1.0f + mInflation;
|
||||
if(pe->processDirtyList(index, mAdapter, inflation))
|
||||
mTimestampNeedsUpdating = true;
|
||||
}
|
||||
|
||||
if(pruner)
|
||||
{
|
||||
if(pruner->isDynamic())
|
||||
static_cast<DynamicPruner*>(pruner)->buildStep(true); // PT: "true" because that parameter was made for PxSceneQuerySystem::sceneQueryBuildStep(), not us
|
||||
|
||||
pruner->commit();
|
||||
}
|
||||
}
|
||||
|
||||
void ExtPrunerManager::finishCustomBuildstep()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.finishCustomBuildstep", mContextID);
|
||||
|
||||
if(mUsesTreeOfPruners)
|
||||
createTreeOfPruners();
|
||||
|
||||
mPrunerNeedsUpdating = false;
|
||||
if(mTimestampNeedsUpdating)
|
||||
invalidateStaticTimestamp();
|
||||
}
|
||||
|
||||
void ExtPrunerManager::createTreeOfPruners()
|
||||
{
|
||||
PX_PROFILE_ZONE("SceneQuery.createTreeOfPruners", mContextID);
|
||||
|
||||
PX_DELETE(mTreeOfPruners);
|
||||
|
||||
mTreeOfPruners = PX_NEW(BVH)(NULL);
|
||||
|
||||
const PxU32 nb = mPrunerExt.size();
|
||||
|
||||
PxBounds3* prunerBounds = reinterpret_cast<PxBounds3*>(PxAlloca(sizeof(PxBounds3)*(nb+1)));
|
||||
|
||||
PxU32 nbBounds = 0;
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerExt* pe = mPrunerExt[i];
|
||||
Pruner* pruner = pe->pruner();
|
||||
if(pruner)
|
||||
pruner->getGlobalBounds(prunerBounds[nbBounds++]);
|
||||
}
|
||||
|
||||
mTreeOfPruners->init(nbBounds, NULL, prunerBounds, sizeof(PxBounds3), BVH_SPLATTER_POINTS, 1, 0.01f);
|
||||
}
|
||||
139
engine/third_party/physx/source/physxextensions/src/ExtSqManager.h
vendored
Normal file
139
engine/third_party/physx/source/physxextensions/src/ExtSqManager.h
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
// 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 EXT_SQ_MANAGER_H
|
||||
#define EXT_SQ_MANAGER_H
|
||||
|
||||
#include "common/PxPhysXCommonConfig.h"
|
||||
|
||||
#include "foundation/PxBitMap.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "SqPruner.h"
|
||||
#include "SqManager.h"
|
||||
|
||||
#include "foundation/PxHashSet.h"
|
||||
namespace physx
|
||||
{
|
||||
namespace Sq
|
||||
{
|
||||
class CompoundPruner;
|
||||
}
|
||||
}
|
||||
|
||||
#include "foundation/PxMutex.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxRenderOutput;
|
||||
class PxBVH;
|
||||
class PxSceneLimits;
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
class BVH;
|
||||
}
|
||||
|
||||
namespace Sq
|
||||
{
|
||||
// PT: this is a customized version of physx::Sq::PrunerManager that supports more than 2 hardcoded pruners.
|
||||
// It might not be possible to support the whole PxSceneQuerySystem API with an arbitrary number of pruners.
|
||||
class ExtPrunerManager : public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
ExtPrunerManager(PxU64 contextID, float inflation, const Adapter& adapter, bool usesTreeOfPruners);
|
||||
~ExtPrunerManager();
|
||||
|
||||
PxU32 addPruner(Gu::Pruner* pruner, PxU32 preallocated);
|
||||
|
||||
Gu::PrunerHandle addPrunerShape(const Gu::PrunerPayload& payload, PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, const PxBounds3& bounds, const PxTransform& transform, bool hasPruningStructure=false);
|
||||
void addCompoundShape(const PxBVH& bvh, PrunerCompoundId compoundId, const PxTransform& compoundTransform, Gu::PrunerHandle* prunerHandle, const Gu::PrunerPayload* payloads, const PxTransform* transforms, bool isDynamic);
|
||||
void markForUpdate(PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, Gu::PrunerHandle shapeHandle, const PxTransform& transform);
|
||||
void removePrunerShape(PxU32 prunerIndex, bool dynamic, PrunerCompoundId compoundId, Gu::PrunerHandle shapeHandle, Gu::PrunerPayloadRemovalCallback* removalCallback);
|
||||
|
||||
PX_FORCE_INLINE PxU32 getNbPruners() const { return mPrunerExt.size(); }
|
||||
PX_FORCE_INLINE const Gu::Pruner* getPruner(PxU32 index) const { return mPrunerExt[index]->mPruner; }
|
||||
PX_FORCE_INLINE Gu::Pruner* getPruner(PxU32 index) { return mPrunerExt[index]->mPruner; }
|
||||
PX_FORCE_INLINE const CompoundPruner* getCompoundPruner() const { return mCompoundPrunerExt.mPruner; }
|
||||
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
|
||||
|
||||
void preallocate(PxU32 prunerIndex, PxU32 nbShapes);
|
||||
|
||||
void setDynamicTreeRebuildRateHint(PxU32 dynTreeRebuildRateHint);
|
||||
PX_FORCE_INLINE PxU32 getDynamicTreeRebuildRateHint() const { return mRebuildRateHint; }
|
||||
|
||||
void flushUpdates();
|
||||
void forceRebuildDynamicTree(PxU32 prunerIndex);
|
||||
|
||||
void updateCompoundActor(PrunerCompoundId compoundId, const PxTransform& compoundTransform);
|
||||
void removeCompoundActor(PrunerCompoundId compoundId, Gu::PrunerPayloadRemovalCallback* removalCallback);
|
||||
|
||||
void* prepareSceneQueriesUpdate(PxU32 prunerIndex);
|
||||
void sceneQueryBuildStep(void* handle);
|
||||
|
||||
void sync(PxU32 prunerIndex, const Gu::PrunerHandle* handles, const PxU32* boundsIndices, const PxBounds3* bounds, const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices);
|
||||
void afterSync(bool buildStep, bool commit);
|
||||
void shiftOrigin(const PxVec3& shift);
|
||||
void visualize(PxU32 prunerIndex, PxRenderOutput& out) const;
|
||||
|
||||
void flushMemory();
|
||||
PX_FORCE_INLINE PxU32 getStaticTimestamp() const { return mStaticTimestamp; }
|
||||
PX_FORCE_INLINE const Adapter& getAdapter() const { return mAdapter; }
|
||||
PX_FORCE_INLINE const Gu::BVH* getTreeOfPruners() const { return mTreeOfPruners; }
|
||||
|
||||
PxU32 startCustomBuildstep();
|
||||
void customBuildstep(PxU32 index);
|
||||
void finishCustomBuildstep();
|
||||
|
||||
void createTreeOfPruners();
|
||||
private:
|
||||
const Adapter& mAdapter;
|
||||
PxArray<PrunerExt*> mPrunerExt;
|
||||
CompoundPrunerExt mCompoundPrunerExt;
|
||||
|
||||
Gu::BVH* mTreeOfPruners;
|
||||
|
||||
const PxU64 mContextID;
|
||||
PxU32 mStaticTimestamp;
|
||||
PxU32 mRebuildRateHint;
|
||||
const float mInflation; // SQ_PRUNER_EPSILON
|
||||
|
||||
PxMutex mSQLock; // to make sure only one query updates the dirty pruner structure if multiple queries run in parallel
|
||||
|
||||
volatile bool mPrunerNeedsUpdating;
|
||||
volatile bool mTimestampNeedsUpdating;
|
||||
const bool mUsesTreeOfPruners;
|
||||
|
||||
void flushShapes();
|
||||
PX_FORCE_INLINE void invalidateStaticTimestamp() { mStaticTimestamp++; }
|
||||
|
||||
PX_NOCOPY(ExtPrunerManager)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
1236
engine/third_party/physx/source/physxextensions/src/ExtSqQuery.cpp
vendored
Normal file
1236
engine/third_party/physx/source/physxextensions/src/ExtSqQuery.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
142
engine/third_party/physx/source/physxextensions/src/ExtSqQuery.h
vendored
Normal file
142
engine/third_party/physx/source/physxextensions/src/ExtSqQuery.h
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// 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 EXT_SQ_QUERY_H
|
||||
#define EXT_SQ_QUERY_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#include "geometry/PxGeometryQueryFlags.h"
|
||||
|
||||
#include "ExtSqManager.h"
|
||||
#include "PxQueryReport.h"
|
||||
#include "GuCachedFuncs.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxGeometry;
|
||||
struct PxQueryFilterData;
|
||||
struct PxFilterData;
|
||||
class PxQueryFilterCallback;
|
||||
|
||||
namespace Sq
|
||||
{
|
||||
struct ExtMultiQueryInput;
|
||||
|
||||
class ExtPVDCapture
|
||||
{
|
||||
public:
|
||||
ExtPVDCapture() {}
|
||||
virtual ~ExtPVDCapture() {}
|
||||
|
||||
virtual bool transmitSceneQueries() = 0;
|
||||
|
||||
virtual void raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal distance, const PxRaycastHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData, bool multipleHits) = 0;
|
||||
virtual void sweep(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, PxReal distance, const PxSweepHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData, bool multipleHits) = 0;
|
||||
virtual void overlap(const PxGeometry& geometry, const PxTransform& pose, const PxOverlapHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData) = 0;
|
||||
};
|
||||
|
||||
// SceneQueries-level adapter. Augments the PrunerManager-level adapter with functions needed to perform queries.
|
||||
class ExtQueryAdapter : public Adapter
|
||||
{
|
||||
public:
|
||||
ExtQueryAdapter() {}
|
||||
virtual ~ExtQueryAdapter() {}
|
||||
|
||||
// PT: TODO: decouple from PxQueryCache?
|
||||
virtual Gu::PrunerHandle findPrunerHandle(const PxQueryCache& cache, PrunerCompoundId& compoundId, PxU32& prunerIndex) const = 0;
|
||||
|
||||
// PT: TODO: return reference? but this version is at least consistent with getActorShape
|
||||
virtual void getFilterData(const Gu::PrunerPayload& payload, PxFilterData& filterData) const = 0;
|
||||
virtual void getActorShape(const Gu::PrunerPayload& payload, PxActorShape& actorShape) const = 0;
|
||||
|
||||
// PT: new for this customized version: a function to perform per-pruner filtering
|
||||
virtual bool processPruner(PxU32 prunerIndex, const PxQueryThreadContext* context, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
// PT: this is a customized version of physx::Sq::SceneQueries that supports more than 2 hardcoded pruners.
|
||||
// It might not be possible to support the whole PxSceneQuerySystem API with an arbitrary number of pruners.
|
||||
class ExtSceneQueries
|
||||
{
|
||||
PX_NOCOPY(ExtSceneQueries)
|
||||
public:
|
||||
ExtSceneQueries(Sq::ExtPVDCapture* pvd, PxU64 contextID,
|
||||
float inflation, const Sq::ExtQueryAdapter& adapter, bool usesTreeOfPruners);
|
||||
~ExtSceneQueries();
|
||||
|
||||
PX_FORCE_INLINE Sq::ExtPrunerManager& getPrunerManagerFast() { return mSQManager; }
|
||||
PX_FORCE_INLINE const Sq::ExtPrunerManager& getPrunerManagerFast() const { return mSQManager; }
|
||||
|
||||
template<typename QueryHit>
|
||||
bool multiQuery(
|
||||
const Sq::ExtMultiQueryInput& in,
|
||||
PxHitCallback<QueryHit>& hits, PxHitFlags hitFlags, const PxQueryCache*,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const;
|
||||
|
||||
bool _raycast(
|
||||
const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, // Ray data
|
||||
PxRaycastCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
|
||||
bool _sweep(
|
||||
const PxGeometry& geometry, const PxTransform& pose, // GeomObject data
|
||||
const PxVec3& unitDir, const PxReal distance, // Ray data
|
||||
PxSweepCallback& hitCall, PxHitFlags hitFlags,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, const PxReal inflation, PxGeometryQueryFlags flags) const;
|
||||
|
||||
bool _overlap(
|
||||
const PxGeometry& geometry, const PxTransform& transform, // GeomObject data
|
||||
PxOverlapCallback& hitCall,
|
||||
const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
|
||||
const PxQueryCache* cache, PxGeometryQueryFlags flags) const;
|
||||
|
||||
PX_FORCE_INLINE PxU64 getContextId() const { return mSQManager.getContextId(); }
|
||||
Sq::ExtPrunerManager mSQManager;
|
||||
public:
|
||||
Gu::CachedFuncs mCachedFuncs;
|
||||
|
||||
Sq::ExtPVDCapture* mPVD;
|
||||
};
|
||||
|
||||
#if PX_SUPPORT_EXTERN_TEMPLATE
|
||||
//explicit template instantiation declaration
|
||||
extern template
|
||||
bool ExtSceneQueries::multiQuery<PxRaycastHit>(const Sq::ExtMultiQueryInput&, PxHitCallback<PxRaycastHit>&, PxHitFlags, const PxQueryCache*, const PxQueryFilterData&, PxQueryFilterCallback*) const;
|
||||
|
||||
extern template
|
||||
bool ExtSceneQueries::multiQuery<PxOverlapHit>(const Sq::ExtMultiQueryInput&, PxHitCallback<PxOverlapHit>&, PxHitFlags, const PxQueryCache*, const PxQueryFilterData&, PxQueryFilterCallback*) const;
|
||||
|
||||
extern template
|
||||
bool ExtSceneQueries::multiQuery<PxSweepHit>(const Sq::ExtMultiQueryInput&, PxHitCallback<PxSweepHit>&, PxHitFlags, const PxQueryCache*, const PxQueryFilterData&, PxQueryFilterCallback*) const;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
102
engine/third_party/physx/source/physxextensions/src/ExtTaskQueueHelper.h
vendored
Normal file
102
engine/third_party/physx/source/physxextensions/src/ExtTaskQueueHelper.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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 EXT_TASK_QUEUE_HELPER_H
|
||||
#define EXT_TASK_QUEUE_HELPER_H
|
||||
|
||||
#include "task/PxTask.h"
|
||||
#include "ExtSharedQueueEntryPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
#define EXT_TASK_QUEUE_ENTRY_POOL_SIZE 128
|
||||
#define EXT_TASK_QUEUE_ENTRY_HIGH_PRIORITY_POOL_SIZE 32
|
||||
|
||||
namespace Ext
|
||||
{
|
||||
class TaskQueueHelper
|
||||
{
|
||||
SharedQueueEntryPool<> mQueueEntryPool;
|
||||
PxSList mJobList;
|
||||
|
||||
SharedQueueEntryPool<> mHighPriorityQueueEntryPool;
|
||||
PxSList mHighPriorityJobList;
|
||||
|
||||
public:
|
||||
|
||||
TaskQueueHelper() : mQueueEntryPool(EXT_TASK_QUEUE_ENTRY_POOL_SIZE, "QueueEntryPool"),
|
||||
mHighPriorityQueueEntryPool(EXT_TASK_QUEUE_ENTRY_HIGH_PRIORITY_POOL_SIZE, "HighPriorityQueueEntryPool")
|
||||
{}
|
||||
|
||||
PX_FORCE_INLINE bool tryAcceptJobToQueue(PxBaseTask& task)
|
||||
{
|
||||
if(task.isHighPriority())
|
||||
{
|
||||
SharedQueueEntry* entry = mHighPriorityQueueEntryPool.getEntry(&task);
|
||||
if(entry)
|
||||
{
|
||||
mHighPriorityJobList.push(*entry);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task);
|
||||
if(entry)
|
||||
{
|
||||
mJobList.push(*entry);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // PT: we never actually reach this
|
||||
}
|
||||
}
|
||||
|
||||
template<const bool highPriorityT>
|
||||
PxBaseTask* fetchTask()
|
||||
{
|
||||
SharedQueueEntry* entry = highPriorityT ? static_cast<SharedQueueEntry*>(mHighPriorityJobList.pop()) : static_cast<SharedQueueEntry*>(mJobList.pop());
|
||||
if(entry)
|
||||
{
|
||||
PxBaseTask* task = reinterpret_cast<PxBaseTask*>(entry->mObjectRef);
|
||||
if(highPriorityT)
|
||||
mHighPriorityQueueEntryPool.putEntry(*entry);
|
||||
else
|
||||
mQueueEntryPool.putEntry(*entry);
|
||||
return task;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Ext
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
383
engine/third_party/physx/source/physxextensions/src/ExtTetMakerExt.cpp
vendored
Normal file
383
engine/third_party/physx/source/physxextensions/src/ExtTetMakerExt.cpp
vendored
Normal file
@@ -0,0 +1,383 @@
|
||||
// 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 "tet/ExtDelaunayBoundaryInserter.h"
|
||||
#include "extensions/PxTetMakerExt.h"
|
||||
#include "cooking/PxTetrahedronMeshDesc.h"
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
#include "tet/ExtMeshSimplificator.h"
|
||||
#include "tet/ExtRemesher.h"
|
||||
#include "tet/ExtOctreeTetrahedralizer.h"
|
||||
#include "tet/ExtVoxelTetrahedralizer.h"
|
||||
#include "foundation/PxMat33.h"
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static PX_FORCE_INLINE PxReal computeTetrahedronVolume(const PxVec3& x0, const PxVec3& x1, const PxVec3& x2, const PxVec3& x3)
|
||||
{
|
||||
const PxVec3 u1 = x1 - x0;
|
||||
const PxVec3 u2 = x2 - x0;
|
||||
const PxVec3 u3 = x3 - x0;
|
||||
|
||||
PxMat33 edgeMatrix = PxMat33(u1, u2, u3);
|
||||
|
||||
const PxReal det = edgeMatrix.getDeterminant();
|
||||
|
||||
const PxReal volume = det / 6.0f;
|
||||
return volume;
|
||||
}
|
||||
|
||||
//Remove tets with small volume
|
||||
static void removeSmallVolumeTetrahedra(PxArray<::physx::PxVec3>& vertices, PxArray<PxU32>& indices, PxReal volumeThreshold = 1e-8f)
|
||||
{
|
||||
uint32_t indexer = 0;
|
||||
|
||||
for (uint32_t i = 0; i < indices.size(); i += 4)
|
||||
{
|
||||
for (uint32_t j = 0; j < 4; ++j)
|
||||
{
|
||||
indices[indexer + j] = indices[i + j];
|
||||
}
|
||||
|
||||
if (computeTetrahedronVolume(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], vertices[indices[i + 3]]) >= volumeThreshold)
|
||||
{
|
||||
indexer += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexer < indices.size())
|
||||
{
|
||||
indices.removeRange(indexer, indices.size() - indexer);
|
||||
}
|
||||
}
|
||||
|
||||
//Removes vertices not referenced by any tetrahedron and maps the tet's indices to match the compacted vertex list
|
||||
static void removeUnusedVertices(PxArray<::physx::PxVec3>& vertices, PxArray<PxU32>& tets, PxU32 numPointsToKeepAtBeginning = 0)
|
||||
{
|
||||
PxArray<PxI32> compressorMap;
|
||||
compressorMap.resize(vertices.size());
|
||||
|
||||
for (PxU32 i = 0; i < numPointsToKeepAtBeginning; ++i)
|
||||
compressorMap[i] = 0;
|
||||
for (PxU32 i = numPointsToKeepAtBeginning; i < compressorMap.size(); ++i)
|
||||
compressorMap[i] = -1;
|
||||
|
||||
for (PxU32 i = 0; i < tets.size(); i += 4)
|
||||
{
|
||||
const PxU32* tet = &tets[i];
|
||||
if (tet[0] == 0xFFFFFFFFu)
|
||||
continue;
|
||||
compressorMap[tet[0]] = 0;
|
||||
compressorMap[tet[1]] = 0;
|
||||
compressorMap[tet[2]] = 0;
|
||||
compressorMap[tet[3]] = 0;
|
||||
}
|
||||
|
||||
PxU32 indexer = 0;
|
||||
for (PxU32 i = 0; i < compressorMap.size(); ++i)
|
||||
{
|
||||
if (compressorMap[i] >= 0)
|
||||
{
|
||||
compressorMap[i] = indexer;
|
||||
vertices[indexer] = vertices[i];
|
||||
indexer++;
|
||||
}
|
||||
}
|
||||
|
||||
for (PxU32 i = 0; i < tets.size(); i += 4)
|
||||
{
|
||||
PxU32* tet = &tets[i];
|
||||
if (tet[0] == 0xFFFFFFFFu)
|
||||
continue;
|
||||
tet[0] = compressorMap[tet[0]];
|
||||
tet[1] = compressorMap[tet[1]];
|
||||
tet[2] = compressorMap[tet[2]];
|
||||
tet[3] = compressorMap[tet[3]];
|
||||
}
|
||||
|
||||
if (indexer < vertices.size())
|
||||
vertices.removeRange(indexer, vertices.size() - indexer);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU64 buildKey(PxI32 a, PxI32 b)
|
||||
{
|
||||
if (a < b)
|
||||
return ((PxU64(a)) << 32) | (PxU64(b));
|
||||
else
|
||||
return ((PxU64(b)) << 32) | (PxU64(a));
|
||||
}
|
||||
|
||||
static const PxI32 neighborEdgeList[3][2] = { { 0, 1 }, { 0, 2 }, { 1, 2 } };
|
||||
|
||||
static void buildTriangleNeighborhood(const PxI32* tris, PxU32 numTris, PxArray<PxI32>& result)
|
||||
{
|
||||
PxU32 l = 4 * numTris; //Waste one element in neighborhood info but allow bit shift access instead
|
||||
result.clear();
|
||||
result.resize(l, -1);
|
||||
|
||||
PxHashMap<PxU64, PxI32> faces;
|
||||
for (PxU32 i = 0; i < numTris; ++i)
|
||||
{
|
||||
const PxI32* tri = &tris[3 * i];
|
||||
if (tris[0] < 0)
|
||||
continue;
|
||||
|
||||
for (PxI32 j = 0; j < 3; ++j)
|
||||
{
|
||||
PxU64 key = buildKey(tri[neighborEdgeList[j][0]], tri[neighborEdgeList[j][1]]);
|
||||
if (const PxPair<const PxU64, PxI32>* ptr = faces.find(key))
|
||||
{
|
||||
if (ptr->second < 0)
|
||||
{
|
||||
//PX_ASSERT(false); //Invalid tetmesh since a face is shared by more than 2 tetrahedra
|
||||
continue;
|
||||
}
|
||||
|
||||
result[4 * i + j] = ptr->second;
|
||||
result[ptr->second] = 4 * i + j;
|
||||
|
||||
faces[key] = -1;
|
||||
}
|
||||
else
|
||||
faces.insert(key, 4 * i + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxTetMaker::detectTriangleIslands(const PxI32* triangles, PxU32 numTriangles, PxArray<PxU32>& islandIndexPerTriangle)
|
||||
{
|
||||
//Detect islands
|
||||
PxArray<PxI32> neighborhood;
|
||||
buildTriangleNeighborhood(triangles, numTriangles, neighborhood);
|
||||
const PxU32 noIslandAssignedMarker = 0xFFFFFFFF;
|
||||
islandIndexPerTriangle.resize(numTriangles, noIslandAssignedMarker);
|
||||
PxU32 start = 0;
|
||||
PxI32 color = -1;
|
||||
PxArray<PxI32> stack;
|
||||
while (true)
|
||||
{
|
||||
stack.clear();
|
||||
while (start < islandIndexPerTriangle.size())
|
||||
{
|
||||
if (islandIndexPerTriangle[start] == noIslandAssignedMarker)
|
||||
{
|
||||
stack.pushBack(start);
|
||||
++color;
|
||||
islandIndexPerTriangle[start] = color;
|
||||
break;
|
||||
}
|
||||
++start;
|
||||
}
|
||||
|
||||
if (start == islandIndexPerTriangle.size())
|
||||
break;
|
||||
|
||||
while (stack.size() > 0)
|
||||
{
|
||||
PxI32 id = stack.popBack();
|
||||
for (PxI32 i = 0; i < 3; ++i)
|
||||
{
|
||||
PxI32 a = neighborhood[4 * id + i];
|
||||
PxI32 tetId = a >> 2;
|
||||
if (tetId >= 0 && islandIndexPerTriangle[tetId] == noIslandAssignedMarker)
|
||||
{
|
||||
stack.pushBack(tetId);
|
||||
islandIndexPerTriangle[tetId] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 PxTetMaker::findLargestIslandId(const PxU32* islandIndexPerTriangle, PxU32 numTriangles)
|
||||
{
|
||||
PxU32 numIslands = 0;
|
||||
for (PxU32 i = 0; i < numTriangles; ++i)
|
||||
numIslands = PxMax(numIslands, islandIndexPerTriangle[i]);
|
||||
++numIslands;
|
||||
|
||||
PxArray<PxU32> numEntriesPerColor;
|
||||
numEntriesPerColor.resize(numIslands, 0);
|
||||
for (PxU32 i = 0; i < numTriangles; ++i)
|
||||
numEntriesPerColor[islandIndexPerTriangle[i]] += 1;
|
||||
|
||||
PxU32 colorWithHighestTetCount = 0;
|
||||
for (PxU32 i = 1; i < numEntriesPerColor.size(); ++i)
|
||||
if (numEntriesPerColor[i] > numEntriesPerColor[colorWithHighestTetCount])
|
||||
colorWithHighestTetCount = i;
|
||||
|
||||
return colorWithHighestTetCount;
|
||||
}
|
||||
|
||||
bool PxTetMaker::createConformingTetrahedronMesh(const PxSimpleTriangleMesh& triangleMesh,
|
||||
physx::PxArray<physx::PxVec3>& outVertices, physx::PxArray<physx::PxU32>& outTetIndices, const bool validate, PxReal volumeThreshold)
|
||||
{
|
||||
if (validate)
|
||||
{
|
||||
PxTriangleMeshAnalysisResults result = PxTetMaker::validateTriangleMesh(triangleMesh);
|
||||
if (result & PxTriangleMeshAnalysisResult::eMESH_IS_INVALID)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_INFO, PX_FL, "createConformingTetrahedronMesh(): Input triangle mesh is not suited to create a tetmesh due to deficiencies. Please call PxTetMaker::validateTriangleMesh(triangleMesh) for more details.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Ext::generateTetmesh(triangleMesh.points, triangleMesh.triangles, triangleMesh.flags & PxMeshFlag::e16_BIT_INDICES, outVertices, outTetIndices);
|
||||
|
||||
if (volumeThreshold > 0.0f)
|
||||
removeSmallVolumeTetrahedra(outVertices, outTetIndices, volumeThreshold);
|
||||
|
||||
PxU32 numRemoveAtEnd = Ext::removeDisconnectedIslands(reinterpret_cast<PxI32*>(outTetIndices.begin()), outTetIndices.size() / 4);
|
||||
if (numRemoveAtEnd > 0)
|
||||
outTetIndices.removeRange(outTetIndices.size() - 4 * numRemoveAtEnd, 4 * numRemoveAtEnd);
|
||||
|
||||
removeUnusedVertices(outVertices, outTetIndices, triangleMesh.points.count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxTetMaker::createVoxelTetrahedronMesh(const PxTetrahedronMeshDesc& tetMesh,
|
||||
const PxU32 numVoxelsAlongLongestBoundingBoxAxis, physx::PxArray<physx::PxVec3>& outVertices, physx::PxArray<physx::PxU32>& outTetIndices,
|
||||
PxI32* intputPointToOutputTetIndex, const PxU32* anchorNodeIndices, PxU32 numTetsPerVoxel)
|
||||
{
|
||||
//numTetsPerVoxel has only two valid values.
|
||||
if (numTetsPerVoxel != 5 && numTetsPerVoxel != 6)
|
||||
numTetsPerVoxel = 5;
|
||||
Ext::generateVoxelTetmesh(tetMesh.points, tetMesh.tetrahedrons, numVoxelsAlongLongestBoundingBoxAxis, outVertices, outTetIndices, intputPointToOutputTetIndex, anchorNodeIndices, numTetsPerVoxel);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxTetMaker::createVoxelTetrahedronMeshFromEdgeLength(const PxTetrahedronMeshDesc& tetMesh,
|
||||
const PxReal voxelEdgeLength, physx::PxArray<physx::PxVec3>& outVertices, physx::PxArray<physx::PxU32>& outTetIndices,
|
||||
PxI32* intputPointToOutputTetIndex, const PxU32* anchorNodeIndices, PxU32 numTetsPerVoxel)
|
||||
{
|
||||
//numTetsPerVoxel has only two valid values.
|
||||
if (numTetsPerVoxel != 5 && numTetsPerVoxel != 6)
|
||||
numTetsPerVoxel = 5;
|
||||
Ext::generateVoxelTetmesh(tetMesh.points, tetMesh.tetrahedrons, voxelEdgeLength, outVertices, outTetIndices, intputPointToOutputTetIndex, anchorNodeIndices, numTetsPerVoxel);
|
||||
return true;
|
||||
}
|
||||
|
||||
PxTriangleMeshAnalysisResults PxTetMaker::validateTriangleMesh(const PxSimpleTriangleMesh& triangleMesh, const PxReal minVolumeThreshold, const PxReal minTriangleAngleRadians)
|
||||
{
|
||||
return Ext::validateTriangleMesh(triangleMesh.points, triangleMesh.triangles, triangleMesh.flags & PxMeshFlag::e16_BIT_INDICES, minVolumeThreshold, minTriangleAngleRadians);
|
||||
}
|
||||
|
||||
PxTetrahedronMeshAnalysisResults PxTetMaker::validateTetrahedronMesh(const PxBoundedData& points, const PxBoundedData& tetrahedra, const PxReal minTetVolumeThreshold)
|
||||
{
|
||||
return Ext::validateTetrahedronMesh(points, tetrahedra, false, minTetVolumeThreshold);
|
||||
}
|
||||
|
||||
void PxTetMaker::simplifyTriangleMesh(const PxArray<PxVec3>& inputVertices, const PxArray<PxU32>&inputIndices, int targetTriangleCount, PxF32 maximalEdgeLength,
|
||||
PxArray<PxVec3>& outputVertices, PxArray<PxU32>& outputIndices,
|
||||
PxArray<PxU32> *vertexMap, PxReal edgeLengthCostWeight, PxReal flatnessDetectionThreshold,
|
||||
bool projectSimplifiedPointsOnInputMeshSurface, PxArray<PxU32>* outputVertexToInputTriangle, bool removeDisconnectedPatches)
|
||||
{
|
||||
Ext::MeshSimplificator ms;
|
||||
|
||||
PxArray<PxU32> indexMapToFullTriangleSet;
|
||||
if (removeDisconnectedPatches)
|
||||
{
|
||||
PxU32 numTriangles = inputIndices.size() / 3;
|
||||
PxArray<PxU32> islandIndexPerTriangle;
|
||||
PxTetMaker::detectTriangleIslands(reinterpret_cast<const PxI32*>(inputIndices.begin()), numTriangles, islandIndexPerTriangle);
|
||||
|
||||
PxU32 biggestIslandIndex = PxTetMaker::findLargestIslandId(islandIndexPerTriangle.begin(), islandIndexPerTriangle.size());
|
||||
|
||||
PxArray<PxU32> connectedTriangleSet;
|
||||
for (PxU32 i = 0; i < numTriangles; ++i)
|
||||
{
|
||||
if (islandIndexPerTriangle[i] == biggestIslandIndex)
|
||||
{
|
||||
for (PxU32 j = 0; j < 3; ++j)
|
||||
connectedTriangleSet.pushBack(inputIndices[3 * i + j]);
|
||||
indexMapToFullTriangleSet.pushBack(i);
|
||||
}
|
||||
}
|
||||
|
||||
ms.init(inputVertices, connectedTriangleSet, edgeLengthCostWeight, flatnessDetectionThreshold, projectSimplifiedPointsOnInputMeshSurface);
|
||||
ms.decimateBySize(targetTriangleCount, maximalEdgeLength);
|
||||
ms.readBack(outputVertices, outputIndices, vertexMap, outputVertexToInputTriangle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms.init(inputVertices, inputIndices, edgeLengthCostWeight, flatnessDetectionThreshold, projectSimplifiedPointsOnInputMeshSurface);
|
||||
ms.decimateBySize(targetTriangleCount, maximalEdgeLength);
|
||||
ms.readBack(outputVertices, outputIndices, vertexMap, outputVertexToInputTriangle);
|
||||
}
|
||||
|
||||
if (removeDisconnectedPatches && projectSimplifiedPointsOnInputMeshSurface && outputVertexToInputTriangle)
|
||||
{
|
||||
for (PxU32 i = 0; i < outputVertexToInputTriangle->size(); ++i)
|
||||
(*outputVertexToInputTriangle)[i] = indexMapToFullTriangleSet[(*outputVertexToInputTriangle)[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void PxTetMaker::remeshTriangleMesh(const PxArray<PxVec3>& inputVertices, const PxArray<PxU32>&inputIndices, PxU32 gridResolution,
|
||||
PxArray<PxVec3>& outputVertices, PxArray<PxU32>& outputIndices, PxArray<PxU32> *vertexMap)
|
||||
{
|
||||
Ext::Remesher rm;
|
||||
rm.remesh(inputVertices, inputIndices, gridResolution, vertexMap);
|
||||
rm.readBack(outputVertices, outputIndices);
|
||||
}
|
||||
|
||||
void PxTetMaker::remeshTriangleMesh(const PxVec3* inputVertices, PxU32 nbVertices, const PxU32* inputIndices, PxU32 nbIndices, PxU32 gridResolution,
|
||||
PxArray<PxVec3>& outputVertices, PxArray<PxU32>& outputIndices, PxArray<PxU32> *vertexMap)
|
||||
{
|
||||
Ext::Remesher rm;
|
||||
rm.remesh(inputVertices, nbVertices, inputIndices, nbIndices, gridResolution, vertexMap);
|
||||
rm.readBack(outputVertices, outputIndices);
|
||||
}
|
||||
|
||||
void PxTetMaker::createTreeBasedTetrahedralMesh(const PxArray<PxVec3>& inputVertices, const PxArray<PxU32>&inputIndices,
|
||||
bool useTreeNodes, PxArray<PxVec3>& outputVertices, PxArray<PxU32>& outputIndices, PxReal volumeThreshold)
|
||||
{
|
||||
Ext::OctreeTetrahedralizer ot;
|
||||
ot.createTetMesh(inputVertices, inputIndices, useTreeNodes);
|
||||
ot.readBack(outputVertices, outputIndices);
|
||||
|
||||
if (volumeThreshold > 0.0f)
|
||||
removeSmallVolumeTetrahedra(outputVertices, outputIndices, volumeThreshold);
|
||||
|
||||
PxU32 numRemoveAtEnd = Ext::removeDisconnectedIslands(reinterpret_cast<PxI32*>(outputIndices.begin()), outputIndices.size() / 4);
|
||||
if (numRemoveAtEnd > 0)
|
||||
outputIndices.removeRange(outputIndices.size() - 4 * numRemoveAtEnd, 4 * numRemoveAtEnd);
|
||||
|
||||
removeUnusedVertices(outputVertices, outputIndices, inputVertices.size());
|
||||
}
|
||||
|
||||
void PxTetMaker::createRelaxedVoxelTetrahedralMesh(const PxArray<PxVec3>& inputVertices, const PxArray<PxU32>&inputIndices,
|
||||
PxArray<PxVec3>& outputVertices, PxArray<PxU32>& outputIndices,
|
||||
PxI32 resolution, PxI32 numRelaxationIters, PxF32 relMinTetVolume)
|
||||
{
|
||||
Ext::VoxelTetrahedralizer vt;
|
||||
vt.createTetMesh(inputVertices, inputIndices, resolution, numRelaxationIters, relMinTetVolume);
|
||||
vt.readBack(outputVertices, outputIndices);
|
||||
}
|
||||
|
||||
465
engine/third_party/physx/source/physxextensions/src/ExtTetrahedronMeshExt.cpp
vendored
Normal file
465
engine/third_party/physx/source/physxextensions/src/ExtTetrahedronMeshExt.cpp
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
// 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/PxTetrahedronMeshExt.h"
|
||||
#include "foundation/PxMathUtils.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
#include "GuTetrahedronMesh.h"
|
||||
#include "GuBox.h"
|
||||
#include "GuBV4.h"
|
||||
#include "GuBV4_Common.h"
|
||||
#include "GuDistancePointTetrahedron.h"
|
||||
|
||||
#include "GuAABBTreeNode.h"
|
||||
#include "GuAABBTree.h"
|
||||
#include "GuAABBTreeBounds.h"
|
||||
#include "GuAABBTreeQuery.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct TetrahedronFinderCallback
|
||||
{
|
||||
PxVec3 mQueryPoint;
|
||||
PxI32 mTetId;
|
||||
PxVec4 mBary;
|
||||
|
||||
const PxVec3* mVertices;
|
||||
const PxU32* mTets;
|
||||
|
||||
PxReal mTolerance = 1e-6f;
|
||||
|
||||
TetrahedronFinderCallback(const PxVec3& queryPoint, const PxVec3* vertices, const PxU32* tets, const PxReal tolerance = 1e-6f) :
|
||||
mQueryPoint(queryPoint), mTetId(-1), mVertices(vertices), mTets(tets), mTolerance(tolerance) {}
|
||||
|
||||
PX_FORCE_INLINE bool testPrimitive(const PxU32 primitiveStartId, const PxU32 numPrimitives)
|
||||
{
|
||||
for (PxU32 i = 0; i < numPrimitives; ++i)
|
||||
{
|
||||
const PxU32* tet = &mTets[4 * (primitiveStartId + i)];
|
||||
PxComputeBarycentric(mVertices[tet[0]], mVertices[tet[1]], mVertices[tet[2]], mVertices[tet[3]], mQueryPoint, mBary);
|
||||
|
||||
if (mBary.x >= -mTolerance && mBary.x <= 1 + mTolerance && mBary.y >= -mTolerance && mBary.y <= 1 + mTolerance &&
|
||||
mBary.z >= -mTolerance && mBary.z <= 1 + mTolerance && mBary.w >= -mTolerance && mBary.w <= 1 + mTolerance)
|
||||
{
|
||||
mTetId = PxI32(primitiveStartId + i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool testBox(const float boxMinX, const float boxMinY, const float boxMinZ, const float boxMaxX, const float boxMaxY, const float boxMaxZ)
|
||||
{
|
||||
return mQueryPoint.x >= boxMinX && mQueryPoint.y >= boxMinY && mQueryPoint.z >= boxMinZ &&
|
||||
mQueryPoint.x <= boxMaxX && mQueryPoint.y <= boxMaxY && mQueryPoint.z <= boxMaxZ;
|
||||
}
|
||||
};
|
||||
|
||||
struct ClosestTetrahedronFinderCallback
|
||||
{
|
||||
PxVec3 mQueryPoint;
|
||||
PxI32 mTetId;
|
||||
PxVec4 mBary;
|
||||
PxReal mDist = 1.84467e+19f; // sqrtf(FLT_MAX)
|
||||
|
||||
const PxVec3* mVertices;
|
||||
const PxU32* mTets;
|
||||
PxReal mTolerance = 1e-6f;
|
||||
|
||||
ClosestTetrahedronFinderCallback(const PxVec3& queryPoint, const PxVec3* vertices, const PxU32* tets) :
|
||||
mQueryPoint(queryPoint), mTetId(-1), mVertices(vertices), mTets(tets) {}
|
||||
|
||||
PX_FORCE_INLINE bool testPrimitive(const PxU32 primitiveStartId, const PxU32 numPrimitives)
|
||||
{
|
||||
for (PxU32 i = 0; i < numPrimitives; ++i)
|
||||
{
|
||||
PxVec4 bary;
|
||||
const PxU32* tet = &mTets[4 * (primitiveStartId + i)];
|
||||
PxComputeBarycentric(mVertices[tet[0]], mVertices[tet[1]], mVertices[tet[2]], mVertices[tet[3]], mQueryPoint, bary);
|
||||
|
||||
if (bary.x >= -mTolerance && bary.x <= 1 + mTolerance && bary.y >= -mTolerance && bary.y <= 1 + mTolerance &&
|
||||
bary.z >= -mTolerance && bary.z <= 1 + mTolerance && bary.w >= -mTolerance && bary.w <= 1 + mTolerance)
|
||||
{
|
||||
mTetId = PxI32(primitiveStartId + i);
|
||||
mBary = bary;
|
||||
mDist = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
PxVec3 closest = Gu::closestPtPointTetrahedron(mQueryPoint, mVertices[tet[0]], mVertices[tet[1]], mVertices[tet[2]], mVertices[tet[3]]);
|
||||
PxReal distSq = (closest - mQueryPoint).magnitudeSquared();
|
||||
if (distSq < mDist * mDist)
|
||||
{
|
||||
mTetId = PxI32(primitiveStartId + i);
|
||||
mBary = bary;
|
||||
mDist = PxSqrt(distSq);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool testBox(const float boxMinX, const float boxMinY, const float boxMinZ, const float boxMaxX, const float boxMaxY, const float boxMaxZ)
|
||||
{
|
||||
if (mQueryPoint.x >= boxMinX && mQueryPoint.y >= boxMinY && mQueryPoint.z >= boxMinZ &&
|
||||
mQueryPoint.x <= boxMaxX && mQueryPoint.y <= boxMaxY && mQueryPoint.z <= boxMaxZ)
|
||||
return true;
|
||||
PxVec3 closest = mQueryPoint;
|
||||
closest.x = PxClamp(closest.x, boxMinX, boxMaxX);
|
||||
closest.y = PxClamp(closest.y, boxMinY, boxMaxY);
|
||||
closest.z = PxClamp(closest.z, boxMinZ, boxMaxZ);
|
||||
PxReal distSq = (closest - mQueryPoint).magnitudeSquared();
|
||||
return distSq < mDist * mDist;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, PxU32 i>
|
||||
static int process(PxU32* stack, PxU32& stackSize, const Gu::BVDataSwizzledNQ* node, T& callback)
|
||||
{
|
||||
if (callback.testBox(node->mMinX[i], node->mMinY[i], node->mMinZ[i], node->mMaxX[i], node->mMaxY[i], node->mMaxZ[i]))
|
||||
{
|
||||
if (node->isLeaf(i))
|
||||
{
|
||||
PxU32 primitiveIndex = node->getPrimitive(i);
|
||||
const PxU32 numPrimitives = Gu::getNbPrimitives(primitiveIndex);
|
||||
if(callback.testPrimitive(primitiveIndex, numPrimitives)) //Returns true if the query should be terminated immediately
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
stack[stackSize++] = node->getChildData(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void traverseBVH(const Gu::BV4Tree& tree, T& callback)
|
||||
{
|
||||
const Gu::BVDataPackedNQ* root = static_cast<const Gu::BVDataPackedNQ*>(tree.mNodes);
|
||||
|
||||
PxU32 stack[GU_BV4_STACK_SIZE];
|
||||
PxU32 stackSize = 0;
|
||||
stack[stackSize++] = tree.mInitData;
|
||||
|
||||
while (stackSize > 0)
|
||||
{
|
||||
const PxU32 childData = stack[--stackSize];
|
||||
const Gu::BVDataSwizzledNQ* node = reinterpret_cast<const Gu::BVDataSwizzledNQ*>(root + Gu::getChildOffset(childData));
|
||||
|
||||
const PxU32 nodeType = Gu::getChildType(childData);
|
||||
|
||||
if (nodeType > 1)
|
||||
if (process<T, 3>(stack, stackSize, node, callback)) return;
|
||||
if (nodeType > 0)
|
||||
if (process<T, 2>(stack, stackSize, node, callback)) return;
|
||||
if (process<T, 1>(stack, stackSize, node, callback)) return;
|
||||
if (process<T, 0>(stack, stackSize, node, callback)) return;
|
||||
}
|
||||
}
|
||||
|
||||
PxI32 PxTetrahedronMeshExt::findTetrahedronContainingPoint(const PxTetrahedronMesh* mesh, const PxVec3& point, PxVec4& bary, PxReal tolerance)
|
||||
{
|
||||
TetrahedronFinderCallback callback(point, mesh->getVertices(), static_cast<const PxU32*>(mesh->getTetrahedrons()), tolerance);
|
||||
traverseBVH(static_cast<const Gu::BVTetrahedronMesh*>(mesh)->getBV4Tree(), callback);
|
||||
bary = callback.mBary;
|
||||
return callback.mTetId;
|
||||
}
|
||||
|
||||
PxI32 PxTetrahedronMeshExt::findTetrahedronClosestToPoint(const PxTetrahedronMesh* mesh, const PxVec3& point, PxVec4& bary)
|
||||
{
|
||||
ClosestTetrahedronFinderCallback callback(point, mesh->getVertices(), static_cast<const PxU32*>(mesh->getTetrahedrons()));
|
||||
const Gu::BV4Tree& tree = static_cast<const Gu::BVTetrahedronMesh*>(mesh)->getBV4Tree();
|
||||
if (tree.mNbNodes) traverseBVH(tree, callback);
|
||||
else callback.testPrimitive(0, mesh->getNbTetrahedrons());
|
||||
bary = callback.mBary;
|
||||
return callback.mTetId;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ClosestDistanceToTetmeshTraversalController
|
||||
{
|
||||
private:
|
||||
PxReal mClosestDistanceSquared;
|
||||
const PxU32* mTetrahedra;
|
||||
const PxVec3* mPoints;
|
||||
const Gu::BVHNode* mNodes;
|
||||
PxVec3 mQueryPoint;
|
||||
PxVec3 mClosestPoint;
|
||||
PxI32 mClosestTetId;
|
||||
|
||||
public:
|
||||
PX_FORCE_INLINE ClosestDistanceToTetmeshTraversalController() {}
|
||||
|
||||
PX_FORCE_INLINE ClosestDistanceToTetmeshTraversalController(const PxU32* tetrahedra, const PxVec3* points, Gu::BVHNode* nodes) :
|
||||
mTetrahedra(tetrahedra), mPoints(points), mNodes(nodes), mQueryPoint(0.0f), mClosestPoint(0.0f), mClosestTetId(-1)
|
||||
{
|
||||
initialize(tetrahedra, points, nodes);
|
||||
}
|
||||
|
||||
void initialize(const PxU32* tetrahedra, const PxVec3* points, Gu::BVHNode* nodes)
|
||||
{
|
||||
mTetrahedra = tetrahedra;
|
||||
mPoints = points;
|
||||
mNodes = nodes;
|
||||
mQueryPoint = PxVec3(0.0f);
|
||||
mClosestPoint = PxVec3(0.0f);
|
||||
mClosestTetId = -1;
|
||||
mClosestDistanceSquared = PX_MAX_F32;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setQueryPoint(const PxVec3& queryPoint)
|
||||
{
|
||||
this->mQueryPoint = queryPoint;
|
||||
mClosestDistanceSquared = FLT_MAX;
|
||||
mClosestPoint = PxVec3(0.0f);
|
||||
mClosestTetId = -1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getClosestPoint() const
|
||||
{
|
||||
return mClosestPoint;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxReal distancePointBoxSquared(const PxBounds3& box, const PxVec3& point)
|
||||
{
|
||||
PxVec3 closestPt = box.minimum.maximum(box.maximum.minimum(point));
|
||||
return (closestPt - point).magnitudeSquared();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Gu::TraversalControl::Enum analyze(const Gu::BVHNode& node, PxI32)
|
||||
{
|
||||
if (distancePointBoxSquared(node.mBV, mQueryPoint) >= mClosestDistanceSquared)
|
||||
return Gu::TraversalControl::eDontGoDeeper;
|
||||
|
||||
if (node.isLeaf())
|
||||
{
|
||||
const PxI32 j = node.getPrimitiveIndex();
|
||||
const PxU32* tet = &mTetrahedra[4 * j];
|
||||
|
||||
PxVec4 bary;
|
||||
PxComputeBarycentric(mPoints[tet[0]], mPoints[tet[1]], mPoints[tet[2]], mPoints[tet[3]], mQueryPoint, bary);
|
||||
|
||||
const PxReal tolerance = 0.0f;
|
||||
if (bary.x >= -tolerance && bary.x <= 1 + tolerance && bary.y >= -tolerance && bary.y <= 1 + tolerance &&
|
||||
bary.z >= -tolerance && bary.z <= 1 + tolerance && bary.w >= -tolerance && bary.w <= 1 + tolerance)
|
||||
{
|
||||
mClosestDistanceSquared = 0;
|
||||
mClosestTetId = j;
|
||||
mClosestPoint = mQueryPoint;
|
||||
return Gu::TraversalControl::eAbort;
|
||||
}
|
||||
|
||||
PxVec3 closest = Gu::closestPtPointTetrahedron(mQueryPoint, mPoints[tet[0]], mPoints[tet[1]], mPoints[tet[2]], mPoints[tet[3]]);
|
||||
PxReal d2 = (closest - mQueryPoint).magnitudeSquared();
|
||||
if (d2 < mClosestDistanceSquared)
|
||||
{
|
||||
mClosestDistanceSquared = d2;
|
||||
mClosestTetId = j;
|
||||
mClosestPoint = closest;
|
||||
}
|
||||
return Gu::TraversalControl::eDontGoDeeper;
|
||||
}
|
||||
|
||||
const Gu::BVHNode& nodePos = mNodes[node.getPosIndex()];
|
||||
const PxReal distSquaredPos = distancePointBoxSquared(nodePos.mBV, mQueryPoint);
|
||||
const Gu::BVHNode& nodeNeg = mNodes[node.getNegIndex()];
|
||||
const PxReal distSquaredNeg = distancePointBoxSquared(nodeNeg.mBV, mQueryPoint);
|
||||
|
||||
if (distSquaredPos < distSquaredNeg)
|
||||
{
|
||||
if (distSquaredPos < mClosestDistanceSquared)
|
||||
return Gu::TraversalControl::eGoDeeper;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (distSquaredNeg < mClosestDistanceSquared)
|
||||
return Gu::TraversalControl::eGoDeeperNegFirst;
|
||||
}
|
||||
return Gu::TraversalControl::eDontGoDeeper;
|
||||
}
|
||||
|
||||
PxI32 getClosestTetId() const { return mClosestTetId; }
|
||||
|
||||
void setClosestStart(const PxReal closestDistanceSquared, PxI32 closestTetrahedron, const PxVec3& closestPoint)
|
||||
{
|
||||
mClosestDistanceSquared = closestDistanceSquared;
|
||||
mClosestTetId = closestTetrahedron;
|
||||
mClosestPoint = closestPoint;
|
||||
}
|
||||
|
||||
private:
|
||||
PX_NOCOPY(ClosestDistanceToTetmeshTraversalController)
|
||||
};
|
||||
}
|
||||
|
||||
static void buildTree(const PxU32* tetrahedra, const PxU32 numTetrahedra, const PxVec3* points, PxArray<Gu::BVHNode>& tree, PxF32 enlargement = 1e-4f)
|
||||
{
|
||||
//Computes a bounding box for every triangle in triangles
|
||||
Gu::AABBTreeBounds boxes;
|
||||
boxes.init(numTetrahedra);
|
||||
for (PxU32 i = 0; i < numTetrahedra; ++i)
|
||||
{
|
||||
const PxU32* tri = &tetrahedra[4 * i];
|
||||
PxBounds3 box = PxBounds3::empty();
|
||||
box.include(points[tri[0]]);
|
||||
box.include(points[tri[1]]);
|
||||
box.include(points[tri[2]]);
|
||||
box.include(points[tri[3]]);
|
||||
box.fattenFast(enlargement);
|
||||
boxes.getBounds()[i] = box;
|
||||
}
|
||||
|
||||
Gu::buildAABBTree(numTetrahedra, boxes, tree);
|
||||
}
|
||||
|
||||
void PxTetrahedronMeshExt::createPointsToTetrahedronMap(const PxArray<PxVec3>& tetMeshVertices, const PxArray<PxU32>& tetMeshIndices,
|
||||
const PxArray<PxVec3>& pointsToEmbed, PxArray<PxVec4>& barycentricCoordinates, PxArray<PxU32>& tetLinks)
|
||||
{
|
||||
barycentricCoordinates.resize(0);
|
||||
tetLinks.resize(0);
|
||||
|
||||
if (tetMeshVertices.size() == 0 || tetMeshIndices.size() == 0)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINVALID_PARAMETER, PX_FL, "Point in Tetmesh embedding: Input mesh does not have any tetrahedra or points.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pointsToEmbed.size() == 0)
|
||||
return;
|
||||
|
||||
PxArray<Gu::BVHNode> tree;
|
||||
buildTree(tetMeshIndices.begin(), tetMeshIndices.size() / 4, tetMeshVertices.begin(), tree);
|
||||
|
||||
if (tree.size() == 0)
|
||||
return;
|
||||
|
||||
ClosestDistanceToTetmeshTraversalController cd(tetMeshIndices.begin(), tetMeshVertices.begin(), tree.begin());
|
||||
|
||||
barycentricCoordinates.resize(pointsToEmbed.size());
|
||||
tetLinks.resize(pointsToEmbed.size());
|
||||
for (PxU32 i = 0; i < pointsToEmbed.size(); ++i)
|
||||
{
|
||||
cd.setQueryPoint(pointsToEmbed[i]);
|
||||
Gu::traverseBVH(tree.begin(), cd);
|
||||
|
||||
const PxU32* tet = &tetMeshIndices[4 * cd.getClosestTetId()];
|
||||
PxVec4 bary;
|
||||
PxComputeBarycentric(tetMeshVertices[tet[0]], tetMeshVertices[tet[1]], tetMeshVertices[tet[2]], tetMeshVertices[tet[3]], cd.getClosestPoint(), bary);
|
||||
|
||||
barycentricCoordinates[i] = bary;
|
||||
tetLinks[i] = cd.getClosestTetId();
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct SortedTriangle
|
||||
{
|
||||
public:
|
||||
PxU32 A;
|
||||
PxU32 B;
|
||||
PxU32 C;
|
||||
PxI32 TetIndex;
|
||||
bool Flipped;
|
||||
|
||||
PX_FORCE_INLINE SortedTriangle(PxU32 a, PxU32 b, PxU32 c, PxI32 tetIndex = -1)
|
||||
{
|
||||
A = a; B = b; C = c; Flipped = false; TetIndex = tetIndex;
|
||||
if (A > B) { PxSwap(A, B); Flipped = !Flipped; }
|
||||
if (B > C) { PxSwap(B, C); Flipped = !Flipped; }
|
||||
if (A > B) { PxSwap(A, B); Flipped = !Flipped; }
|
||||
}
|
||||
};
|
||||
|
||||
struct TriangleHash
|
||||
{
|
||||
PX_FORCE_INLINE std::size_t operator()(const SortedTriangle& k) const
|
||||
{
|
||||
return k.A ^ k.B ^ k.C;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool equal(const SortedTriangle& first, const SortedTriangle& second) const
|
||||
{
|
||||
return first.A == second.A && first.B == second.B && first.C == second.C;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static const PxU32 tetFaces[4][3] = { {0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3} };
|
||||
|
||||
void PxTetrahedronMeshExt::extractTetMeshSurface(const void* tetrahedra, PxU32 numTetrahedra, bool sixteenBitIndices, PxArray<PxU32>& surfaceTriangles, PxArray<PxU32>* surfaceTriangleToTet, bool flipTriangleOrientation)
|
||||
{
|
||||
PxHashMap<SortedTriangle, PxU32, TriangleHash> tris;
|
||||
|
||||
const PxU32* tets32 = reinterpret_cast<const PxU32*>(tetrahedra);
|
||||
const PxU16* tets16 = reinterpret_cast<const PxU16*>(tetrahedra);
|
||||
|
||||
PxU32 l = 4 * numTetrahedra;
|
||||
for (PxU32 i = 0; i < l; i += 4)
|
||||
{
|
||||
for (PxU32 j = 0; j < 4; ++j)
|
||||
{
|
||||
SortedTriangle tri(sixteenBitIndices ? tets16[i + tetFaces[j][0]] : tets32[i + tetFaces[j][0]],
|
||||
sixteenBitIndices ? tets16[i + tetFaces[j][1]] : tets32[i + tetFaces[j][1]],
|
||||
sixteenBitIndices ? tets16[i + tetFaces[j][2]] : tets32[i + tetFaces[j][2]], i);
|
||||
if (const PxPair<const SortedTriangle, PxU32>* ptr = tris.find(tri))
|
||||
tris[tri] = ptr->second + 1;
|
||||
else
|
||||
tris.insert(tri, 1);
|
||||
}
|
||||
}
|
||||
|
||||
surfaceTriangles.clear();
|
||||
if (surfaceTriangleToTet)
|
||||
surfaceTriangleToTet->clear();
|
||||
for (PxHashMap<SortedTriangle, PxU32, TriangleHash>::Iterator iter = tris.getIterator(); !iter.done(); ++iter)
|
||||
{
|
||||
if (iter->second == 1) {
|
||||
surfaceTriangles.pushBack(iter->first.A);
|
||||
if (iter->first.Flipped != flipTriangleOrientation)
|
||||
{
|
||||
surfaceTriangles.pushBack(iter->first.C);
|
||||
surfaceTriangles.pushBack(iter->first.B);
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceTriangles.pushBack(iter->first.B);
|
||||
surfaceTriangles.pushBack(iter->first.C);
|
||||
}
|
||||
if (surfaceTriangleToTet)
|
||||
surfaceTriangleToTet->pushBack(iter->first.TetIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxTetrahedronMeshExt::extractTetMeshSurface(const PxTetrahedronMesh* mesh, PxArray<PxU32>& surfaceTriangles, PxArray<PxU32>* surfaceTriangleToTet, bool flipTriangleOrientation)
|
||||
{
|
||||
extractTetMeshSurface(mesh->getTetrahedrons(), mesh->getNbTetrahedrons(), mesh->getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES, surfaceTriangles, surfaceTriangleToTet, flipTriangleOrientation);
|
||||
}
|
||||
189
engine/third_party/physx/source/physxextensions/src/ExtTriangleMeshExt.cpp
vendored
Normal file
189
engine/third_party/physx/source/physxextensions/src/ExtTriangleMeshExt.cpp
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
// 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 "geometry/PxMeshQuery.h"
|
||||
#include "geometry/PxGeometryQuery.h"
|
||||
#include "geometry/PxTriangleMeshGeometry.h"
|
||||
#include "geometry/PxHeightFieldGeometry.h"
|
||||
#include "geometry/PxHeightField.h"
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
#include "extensions/PxTriangleMeshExt.h"
|
||||
#include "GuSDF.h"
|
||||
#include "GuTriangleMesh.h"
|
||||
|
||||
#include "foundation/PxAllocator.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxMeshOverlapUtil::PxMeshOverlapUtil() : mResultsMemory(mResults), mNbResults(0), mMaxNbResults(256)
|
||||
{
|
||||
}
|
||||
|
||||
PxMeshOverlapUtil::~PxMeshOverlapUtil()
|
||||
{
|
||||
if(mResultsMemory != mResults)
|
||||
PX_FREE(mResultsMemory);
|
||||
}
|
||||
|
||||
PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose)
|
||||
{
|
||||
bool overflow;
|
||||
PxU32 nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow);
|
||||
|
||||
if(overflow)
|
||||
{
|
||||
const PxU32 maxNbTris = meshGeom.triangleMesh->getNbTriangles();
|
||||
if(!maxNbTris)
|
||||
{
|
||||
mNbResults = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mMaxNbResults<maxNbTris)
|
||||
{
|
||||
if(mResultsMemory != mResults)
|
||||
PX_FREE(mResultsMemory);
|
||||
|
||||
mResultsMemory = PX_ALLOCATE(PxU32, maxNbTris, "PxMeshOverlapUtil::findOverlap");
|
||||
mMaxNbResults = maxNbTris;
|
||||
}
|
||||
nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow);
|
||||
PX_ASSERT(nbTouchedTris);
|
||||
PX_ASSERT(!overflow);
|
||||
}
|
||||
mNbResults = nbTouchedTris;
|
||||
return nbTouchedTris;
|
||||
}
|
||||
|
||||
PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose)
|
||||
{
|
||||
bool overflow = true;
|
||||
PxU32 nbTouchedTris = PxMeshQuery::findOverlapHeightField(geom, geomPose, hfGeom, hfPose, mResultsMemory, mMaxNbResults, 0, overflow);
|
||||
|
||||
if(overflow)
|
||||
{
|
||||
const PxU32 maxNbTris = hfGeom.heightField->getNbRows()*hfGeom.heightField->getNbColumns()*2;
|
||||
if(!maxNbTris)
|
||||
{
|
||||
mNbResults = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mMaxNbResults<maxNbTris)
|
||||
{
|
||||
if(mResultsMemory != mResults)
|
||||
PX_FREE(mResultsMemory);
|
||||
|
||||
mResultsMemory = PX_ALLOCATE(PxU32, maxNbTris, "PxMeshOverlapUtil::findOverlap");
|
||||
mMaxNbResults = maxNbTris;
|
||||
}
|
||||
nbTouchedTris = PxMeshQuery::findOverlapHeightField(geom, geomPose, hfGeom, hfPose, mResultsMemory, mMaxNbResults, 0, overflow);
|
||||
PX_ASSERT(nbTouchedTris);
|
||||
PX_ASSERT(!overflow);
|
||||
}
|
||||
mNbResults = nbTouchedTris;
|
||||
return nbTouchedTris;
|
||||
|
||||
}
|
||||
namespace
|
||||
{
|
||||
template<typename MeshGeometry>
|
||||
bool computeMeshPenetrationT(PxVec3& direction,
|
||||
PxReal& depth,
|
||||
const PxGeometry& geom,
|
||||
const PxTransform& geomPose,
|
||||
const MeshGeometry& meshGeom,
|
||||
const PxTransform& meshPose,
|
||||
PxU32 maxIter,
|
||||
PxU32* nbIterOut)
|
||||
{
|
||||
PxU32 nbIter = 0;
|
||||
PxTransform pose = geomPose;
|
||||
for (; nbIter < maxIter; nbIter++)
|
||||
{
|
||||
PxVec3 currentDir;
|
||||
PxF32 currentDepth;
|
||||
|
||||
if (!PxGeometryQuery::computePenetration(currentDir, currentDepth, geom, pose, meshGeom, meshPose))
|
||||
break;
|
||||
|
||||
pose.p += currentDir * currentDepth;
|
||||
}
|
||||
|
||||
if(nbIterOut)
|
||||
*nbIterOut = nbIter;
|
||||
|
||||
PxVec3 diff = pose.p - geomPose.p;
|
||||
depth = diff.magnitude();
|
||||
|
||||
if (depth>0)
|
||||
direction = diff / depth;
|
||||
|
||||
return nbIter!=0;
|
||||
}
|
||||
}
|
||||
|
||||
bool physx::PxComputeTriangleMeshPenetration(PxVec3& direction,
|
||||
PxReal& depth,
|
||||
const PxGeometry& geom,
|
||||
const PxTransform& geomPose,
|
||||
const PxTriangleMeshGeometry& meshGeom,
|
||||
const PxTransform& meshPose,
|
||||
PxU32 maxIter,
|
||||
PxU32* nbIter)
|
||||
{
|
||||
return computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, nbIter);
|
||||
}
|
||||
|
||||
bool physx::PxComputeHeightFieldPenetration(PxVec3& direction,
|
||||
PxReal& depth,
|
||||
const PxGeometry& geom,
|
||||
const PxTransform& geomPose,
|
||||
const PxHeightFieldGeometry& hfGeom,
|
||||
const PxTransform& meshPose,
|
||||
PxU32 maxIter,
|
||||
PxU32* nbIter)
|
||||
{
|
||||
return computeMeshPenetrationT(direction, depth, geom, geomPose, hfGeom, meshPose, maxIter, nbIter);
|
||||
}
|
||||
|
||||
bool physx::PxExtractIsosurfaceFromSDF(const PxTriangleMesh& triangleMesh, PxArray<PxVec3>& isosurfaceVertices, PxArray<PxU32>& isosurfaceTriangleIndices)
|
||||
{
|
||||
PxU32 dimX, dimY, dimZ;
|
||||
triangleMesh.getSDFDimensions(dimX, dimY, dimZ);
|
||||
if (dimX == 0 || dimY == 0 || dimZ == 0)
|
||||
return false;
|
||||
|
||||
const Gu::TriangleMesh* guTriangleMesh = static_cast<const Gu::TriangleMesh*>(&triangleMesh);
|
||||
const Gu::SDF& sdf = guTriangleMesh->getSdfDataFast();
|
||||
|
||||
extractIsosurfaceFromSDF(sdf, isosurfaceVertices, isosurfaceTriangleIndices);
|
||||
|
||||
return true;
|
||||
}
|
||||
53
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdRegistrationData.cpp
vendored
Normal file
53
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdRegistrationData.cpp
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 "ExtOmniPvdRegistrationData.h"
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
|
||||
void OmniPvdPxExtensionsRegistrationData::registerData(OmniPvdWriter& writer)
|
||||
{
|
||||
// auto-generate class/attribute registration code from object definition file
|
||||
#define OMNI_PVD_WRITER_VAR writer
|
||||
|
||||
#include "omnipvd/CmOmniPvdAutoGenRegisterData.h"
|
||||
#include "OmniPvdPxExtensionsTypes.h"
|
||||
#include "omnipvd/CmOmniPvdAutoGenClearDefines.h"
|
||||
|
||||
#undef OMNI_PVD_WRITER_VAR
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
72
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdRegistrationData.h
vendored
Normal file
72
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdRegistrationData.h
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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 EXT_OMNI_PVD_REGISTRATION_DATA_H
|
||||
#define EXT_OMNI_PVD_REGISTRATION_DATA_H
|
||||
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
#include "../pvdruntime/include/OmniPvdWriter.h"
|
||||
|
||||
#include "extensions/PxD6Joint.h" // for PxD6Motion
|
||||
#include "extensions/PxDistanceJoint.h" // for PxDistanceJointFlags
|
||||
#include "extensions/PxPrismaticJoint.h" // for PxPrismaticJointFlags
|
||||
#include "extensions/PxRevoluteJoint.h" // for PxRevoluteJointFlags
|
||||
#include "extensions/PxSphericalJoint.h" // for PxSphericalJointFlags
|
||||
#include "extensions/PxCustomGeometryExt.h" // for PxCustomGeometryExtBaseConvexCallbacks etc.
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxFixedJoint;
|
||||
class PxGearJoint;
|
||||
class PxRackAndPinionJoint;
|
||||
|
||||
|
||||
namespace Ext
|
||||
{
|
||||
|
||||
struct OmniPvdPxExtensionsRegistrationData
|
||||
{
|
||||
void registerData(OmniPvdWriter&);
|
||||
|
||||
// auto-generate members and setter methods from object definition file
|
||||
#include "omnipvd/CmOmniPvdAutoGenCreateRegistrationStruct.h"
|
||||
#include "OmniPvdPxExtensionsTypes.h"
|
||||
#include "omnipvd/CmOmniPvdAutoGenClearDefines.h"
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PX_SUPPORT_OMNI_PVD
|
||||
|
||||
#endif // EXT_OMNI_PVD_REGISTRATION_DATA_H
|
||||
68
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdSetData.h
vendored
Normal file
68
engine/third_party/physx/source/physxextensions/src/omnipvd/ExtOmniPvdSetData.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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 EXT_OMNI_PVD_SET_DATA_H
|
||||
#define EXT_OMNI_PVD_SET_DATA_H
|
||||
|
||||
|
||||
//
|
||||
// This header has to be included to use macros like OMNI_PVD_SET() (set attribute values,
|
||||
// object instance registration etc.)
|
||||
//
|
||||
|
||||
|
||||
#define OMNI_PVD_CONTEXT_HANDLE 1
|
||||
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
#include "OmniPvdPxExtensionsSampler.h"
|
||||
#include "omnipvd/PxOmniPvd.h"
|
||||
|
||||
//
|
||||
// Define the macros needed in CmOmniPvdAutoGenSetData.h
|
||||
//
|
||||
#undef OMNI_PVD_GET_WRITER
|
||||
#define OMNI_PVD_GET_WRITER(writer) \
|
||||
physx::PxOmniPvd::ScopedExclusiveWriter writeLock(physx::Ext::OmniPvdGetInstance()); \
|
||||
OmniPvdWriter* writer = writeLock.getWriter();
|
||||
|
||||
|
||||
#undef OMNI_PVD_GET_REGISTRATION_DATA
|
||||
#define OMNI_PVD_GET_REGISTRATION_DATA(registrationData) \
|
||||
const OmniPvdPxExtensionsRegistrationData* registrationData = physx::Ext::OmniPvdGetPxExtensionsRegistrationData();
|
||||
|
||||
#endif // PX_SUPPORT_OMNI_PVD
|
||||
|
||||
|
||||
#include "omnipvd/CmOmniPvdAutoGenSetData.h"
|
||||
// note: included in all cases since it will provide empty definitions of the helper macros such
|
||||
// that not all of them have to be guarded by PX_SUPPORT_OMNI_PVD
|
||||
|
||||
|
||||
#endif // EXT_OMNI_PVD_SET_DATA_H
|
||||
123
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsSampler.cpp
vendored
Normal file
123
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsSampler.cpp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// 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.
|
||||
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
#include "OmniPvdPxExtensionsSampler.h"
|
||||
#include "omnipvd/PxOmniPvd.h"
|
||||
|
||||
|
||||
using namespace physx;
|
||||
|
||||
|
||||
void OmniPvdPxExtensionsSampler::registerClasses()
|
||||
{
|
||||
PxOmniPvd::ScopedExclusiveWriter scope(mOmniPvdInstance);
|
||||
OmniPvdWriter* writer = scope.getWriter();
|
||||
if (writer)
|
||||
{
|
||||
mRegistrationData.registerData(*mOmniPvdInstance->getWriter());
|
||||
}
|
||||
}
|
||||
|
||||
OmniPvdPxExtensionsSampler::OmniPvdPxExtensionsSampler()
|
||||
{
|
||||
mOmniPvdInstance = NULL;
|
||||
}
|
||||
|
||||
OmniPvdPxExtensionsSampler::~OmniPvdPxExtensionsSampler()
|
||||
{
|
||||
}
|
||||
|
||||
void OmniPvdPxExtensionsSampler::setOmniPvdInstance(physx::PxOmniPvd* omniPvdInstance)
|
||||
{
|
||||
mOmniPvdInstance = omniPvdInstance;
|
||||
}
|
||||
|
||||
physx::PxOmniPvd* OmniPvdPxExtensionsSampler::getOmniPvdInstance() {
|
||||
return mOmniPvdInstance;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static OmniPvdPxExtensionsSampler* gOmniPvdPxExtensionsSampler = NULL;
|
||||
|
||||
bool OmniPvdPxExtensionsSampler::createInstance()
|
||||
{
|
||||
gOmniPvdPxExtensionsSampler = PX_NEW(OmniPvdPxExtensionsSampler)();
|
||||
return gOmniPvdPxExtensionsSampler != NULL;
|
||||
}
|
||||
|
||||
OmniPvdPxExtensionsSampler* OmniPvdPxExtensionsSampler::getInstance()
|
||||
{
|
||||
return gOmniPvdPxExtensionsSampler;
|
||||
}
|
||||
|
||||
void OmniPvdPxExtensionsSampler::destroyInstance()
|
||||
{
|
||||
PX_DELETE(gOmniPvdPxExtensionsSampler);
|
||||
}
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
|
||||
const OmniPvdPxExtensionsRegistrationData* OmniPvdGetPxExtensionsRegistrationData()
|
||||
{
|
||||
OmniPvdPxExtensionsSampler* sampler = OmniPvdPxExtensionsSampler::getInstance();
|
||||
if (sampler)
|
||||
{
|
||||
return &sampler->getRegistrationData();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PxOmniPvd* OmniPvdGetInstance()
|
||||
{
|
||||
OmniPvdPxExtensionsSampler* sampler = OmniPvdPxExtensionsSampler::getInstance();
|
||||
if (sampler)
|
||||
{
|
||||
return sampler->getOmniPvdInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
79
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsSampler.h
vendored
Normal file
79
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsSampler.h
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// 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 OMNI_PVD_EXTENSION_SAMPLER_H
|
||||
#define OMNI_PVD_EXTENSION_SAMPLER_H
|
||||
|
||||
|
||||
#if PX_SUPPORT_OMNI_PVD
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
|
||||
#include "ExtOmniPvdRegistrationData.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxOmniPvd;
|
||||
}
|
||||
|
||||
|
||||
class OmniPvdPxExtensionsSampler : public physx::PxUserAllocated
|
||||
{
|
||||
public:
|
||||
OmniPvdPxExtensionsSampler();
|
||||
~OmniPvdPxExtensionsSampler();
|
||||
void setOmniPvdInstance(physx::PxOmniPvd* omniPvdInstance);
|
||||
physx::PxOmniPvd* getOmniPvdInstance();
|
||||
void registerClasses();
|
||||
|
||||
const physx::Ext::OmniPvdPxExtensionsRegistrationData& getRegistrationData() const { return mRegistrationData; }
|
||||
|
||||
// OmniPvdPxExtensionsSampler singleton
|
||||
static bool createInstance();
|
||||
static OmniPvdPxExtensionsSampler* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
private:
|
||||
physx::PxOmniPvd* mOmniPvdInstance;
|
||||
physx::Ext::OmniPvdPxExtensionsRegistrationData mRegistrationData;
|
||||
};
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Ext
|
||||
{
|
||||
|
||||
const OmniPvdPxExtensionsRegistrationData* OmniPvdGetPxExtensionsRegistrationData();
|
||||
PxOmniPvd* OmniPvdGetInstance();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
294
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsTypes.h
vendored
Normal file
294
engine/third_party/physx/source/physxextensions/src/omnipvd/OmniPvdPxExtensionsTypes.h
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
// 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.
|
||||
|
||||
// Declare OMNI_PVD Types and Attributes here!
|
||||
// The last two attribute parameters could now be derived from the other data, so could be removed in a refactor,
|
||||
// though explicit control may be better.
|
||||
// Note that HANDLE attributes have to use (Type const *) style, otherwise it won't compile!
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Enums
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxConstraintFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eBROKEN)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eCOLLISION_ENABLED)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eVISUALIZATION)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eDRIVE_LIMITS_ARE_FORCES)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eIMPROVED_SLERP)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eDISABLE_PREPROCESSING)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eENABLE_EXTENDED_LIMITS)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eGPU_COMPATIBLE)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eALWAYS_UPDATE)
|
||||
OMNI_PVD_ENUM_VALUE (PxConstraintFlag, eDISABLE_CONSTRAINT)
|
||||
OMNI_PVD_ENUM_END (PxConstraintFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxRevoluteJointFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxRevoluteJointFlag, eLIMIT_ENABLED)
|
||||
OMNI_PVD_ENUM_VALUE (PxRevoluteJointFlag, eDRIVE_ENABLED)
|
||||
OMNI_PVD_ENUM_VALUE (PxRevoluteJointFlag, eDRIVE_FREESPIN)
|
||||
OMNI_PVD_ENUM_END (PxRevoluteJointFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxPrismaticJointFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxPrismaticJointFlag, eLIMIT_ENABLED)
|
||||
OMNI_PVD_ENUM_END (PxPrismaticJointFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxDistanceJointFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxDistanceJointFlag, eMAX_DISTANCE_ENABLED)
|
||||
OMNI_PVD_ENUM_VALUE (PxDistanceJointFlag, eMIN_DISTANCE_ENABLED)
|
||||
OMNI_PVD_ENUM_VALUE (PxDistanceJointFlag, eSPRING_ENABLED)
|
||||
OMNI_PVD_ENUM_END (PxDistanceJointFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxSphericalJointFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxSphericalJointFlag, eLIMIT_ENABLED)
|
||||
OMNI_PVD_ENUM_END (PxSphericalJointFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxD6JointDriveFlag)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6JointDriveFlag, eACCELERATION)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6JointDriveFlag, eOUTPUT_FORCE)
|
||||
OMNI_PVD_ENUM_END (PxD6JointDriveFlag)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxJointConcreteType)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eSPHERICAL)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eREVOLUTE)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, ePRISMATIC)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eFIXED)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eDISTANCE)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eD6)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eGEAR)
|
||||
OMNI_PVD_ENUM_VALUE (PxJointConcreteType, eRACK_AND_PINION)
|
||||
OMNI_PVD_ENUM_END (PxJointConcreteType)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxD6Motion)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6Motion, eLOCKED)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6Motion, eLIMITED)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6Motion, eFREE)
|
||||
OMNI_PVD_ENUM_END (PxD6Motion)
|
||||
|
||||
OMNI_PVD_ENUM_BEGIN (PxD6AngularDriveConfig)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6AngularDriveConfig, eSWING_TWIST)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6AngularDriveConfig, eSLERP)
|
||||
OMNI_PVD_ENUM_VALUE (PxD6AngularDriveConfig, eLEGACY)
|
||||
OMNI_PVD_ENUM_END (PxD6AngularDriveConfig)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Classes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_BEGIN (PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, constraint, PxConstraint* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxJoint, type, PxJointConcreteType::Enum, PxJointConcreteType)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, actor0, PxRigidActor* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, actor1, PxRigidActor* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_FIXED_SIZE (PxJoint, actor0LocalPose, PxTransform, OmniPvdDataType::eFLOAT32, 7)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_FIXED_SIZE (PxJoint, actor1LocalPose, PxTransform, OmniPvdDataType::eFLOAT32, 7)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, breakForce, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, breakTorque, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxJoint, constraintFlags, PxConstraintFlags, PxConstraintFlag)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, invMassScale0, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, invInertiaScale0, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, invMassScale1, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxJoint, invInertiaScale1, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_STRING (PxJoint, name)
|
||||
OMNI_PVD_ATTRIBUTE_STRING (PxJoint, concreteTypeName)
|
||||
OMNI_PVD_CLASS_END (PxJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxFixedJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxFixedJoint, PxJoint)
|
||||
OMNI_PVD_CLASS_END (PxFixedJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxPrismaticJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxPrismaticJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, position, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, velocity, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitLower, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitUpper, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxPrismaticJoint, limitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxPrismaticJoint, jointFlags, PxPrismaticJointFlags, PxPrismaticJointFlag)
|
||||
OMNI_PVD_CLASS_END (PxPrismaticJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxRevoluteJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxRevoluteJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, angle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, velocity, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitLower, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitUpper, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, limitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, driveVelocity, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, driveForceLimit, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxRevoluteJoint, driveGearRatio, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxRevoluteJoint, jointFlags, PxRevoluteJointFlags, PxRevoluteJointFlag)
|
||||
OMNI_PVD_CLASS_END (PxRevoluteJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxSphericalJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxSphericalJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, swingYAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, swingZAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitYAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitZAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxSphericalJoint, limitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxSphericalJoint, jointFlags, PxSphericalJointFlags, PxSphericalJointFlag)
|
||||
OMNI_PVD_CLASS_END (PxSphericalJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxDistanceJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxDistanceJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, distance, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, minDistance, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, maxDistance, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, tolerance, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, stiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxDistanceJoint, damping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxDistanceJoint, jointFlags, PxDistanceJointFlags, PxDistanceJointFlag)
|
||||
OMNI_PVD_CLASS_END (PxDistanceJoint)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxGearJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxGearJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxGearJoint, ratio, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxGearJoint, hinges, PxBase* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_CLASS_END (PxGearJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxRackAndPinionJoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxRackAndPinionJoint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxRackAndPinionJoint, ratio, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxRackAndPinionJoint, joints, PxBase* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_CLASS_END (PxRackAndPinionJoint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxD6JointDrive
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_BEGIN (PxD6JointDrive)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6JointDrive, stiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6JointDrive, damping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6JointDrive, forceLimit, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxD6JointDrive, flags, PxD6JointDriveFlags, PxD6JointDriveFlag)
|
||||
OMNI_PVD_CLASS_END (PxD6JointDrive)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxD6Joint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxD6Joint, PxJoint)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingYAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingZAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, motions, PxD6Motion::Enum, OmniPvdDataType::eUINT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, distanceLimitValue, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, distanceLimitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, distanceLimitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, distanceLimitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, distanceLimitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitLower, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitUpper, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_VARIABLE_SIZE (PxD6Joint, linearLimitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitLower, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitUpper, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, twistLimitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitYAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitZAngle, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, swingLimitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitYAngleMin, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitYAngleMax, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitZAngleMin, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitZAngleMax, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitRestitution, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitBounceThreshold, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitStiffness, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, pyramidSwingLimitDamping, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveX, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveY, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveZ, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveSwing, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveTwist, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveSlerp, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveSwing1, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE (PxD6Joint, driveSwing2, PxD6JointDrive* const, OmniPvdDataType::eOBJECT_HANDLE)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_FIXED_SIZE (PxD6Joint, drivePosition, PxTransform, OmniPvdDataType::eFLOAT32, 7)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_FIXED_SIZE (PxD6Joint, driveLinVelocity, PxVec3, OmniPvdDataType::eFLOAT32, 3)
|
||||
OMNI_PVD_ATTRIBUTE_ARRAY_FIXED_SIZE (PxD6Joint, driveAngVelocity, PxVec3, OmniPvdDataType::eFLOAT32, 3)
|
||||
OMNI_PVD_ATTRIBUTE_FLAG (PxD6Joint, angularDriveConfig, PxD6AngularDriveConfig::Enum, PxD6AngularDriveConfig)
|
||||
OMNI_PVD_CLASS_END (PxD6Joint)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxCustomGeometryExt::BaseConvexCallbacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_BEGIN (PxCustomGeometryExtBaseConvexCallbacks)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtBaseConvexCallbacks, margin, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_CLASS_END (PxCustomGeometryExtBaseConvexCallbacks)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxCustomGeometryExt::CylinderCallbacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxCustomGeometryExtCylinderCallbacks, PxCustomGeometryExtBaseConvexCallbacks)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtCylinderCallbacks, height, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtCylinderCallbacks, radius, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtCylinderCallbacks, axis, PxI32, OmniPvdDataType::eINT32)
|
||||
OMNI_PVD_CLASS_END (PxCustomGeometryExtCylinderCallbacks)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PxCustomGeometryExt::ConeCallbacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OMNI_PVD_CLASS_DERIVED_BEGIN (PxCustomGeometryExtConeCallbacks, PxCustomGeometryExtBaseConvexCallbacks)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtConeCallbacks, height, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtConeCallbacks, radius, PxReal, OmniPvdDataType::eFLOAT32)
|
||||
OMNI_PVD_ATTRIBUTE (PxCustomGeometryExtConeCallbacks, axis, PxI32, OmniPvdDataType::eINT32)
|
||||
OMNI_PVD_CLASS_END (PxCustomGeometryExtConeCallbacks)
|
||||
300
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnBinaryDeserialization.cpp
vendored
Normal file
300
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnBinaryDeserialization.cpp
vendored
Normal 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;
|
||||
}
|
||||
416
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnBinarySerialization.cpp
vendored
Normal file
416
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnBinarySerialization.cpp
vendored
Normal 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;
|
||||
}
|
||||
113
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnSerializationContext.cpp
vendored
Normal file
113
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnSerializationContext.cpp
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
282
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnSerializationContext.h
vendored
Normal file
282
engine/third_party/physx/source/physxextensions/src/serialization/Binary/SnSerializationContext.h
vendored
Normal 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
|
||||
84
engine/third_party/physx/source/physxextensions/src/serialization/File/SnFile.h
vendored
Normal file
84
engine/third_party/physx/source/physxextensions/src/serialization/File/SnFile.h
vendored
Normal 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
|
||||
|
||||
131
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialUtils.cpp
vendored
Normal file
131
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialUtils.cpp
vendored
Normal 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
|
||||
|
||||
56
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialUtils.h
vendored
Normal file
56
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialUtils.h
vendored
Normal 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
|
||||
303
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialization.cpp
vendored
Normal file
303
engine/third_party/physx/source/physxextensions/src/serialization/SnSerialization.cpp
vendored
Normal 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
270
engine/third_party/physx/source/physxextensions/src/serialization/SnSerializationRegistry.cpp
vendored
Normal file
270
engine/third_party/physx/source/physxextensions/src/serialization/SnSerializationRegistry.cpp
vendored
Normal 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
|
||||
|
||||
88
engine/third_party/physx/source/physxextensions/src/serialization/SnSerializationRegistry.h
vendored
Normal file
88
engine/third_party/physx/source/physxextensions/src/serialization/SnSerializationRegistry.h
vendored
Normal 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
|
||||
|
||||
838
engine/third_party/physx/source/physxextensions/src/serialization/Xml/PsFastXml.cpp
vendored
Normal file
838
engine/third_party/physx/source/physxextensions/src/serialization/Xml/PsFastXml.cpp
vendored
Normal 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] = {
|
||||
{ "<", 4, '<' }, { "&", 5, '&' }, { ">", 4, '>' }, { """, 6, '\"' }, { "'", 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
166
engine/third_party/physx/source/physxextensions/src/serialization/Xml/PsFastXml.h
vendored
Normal file
166
engine/third_party/physx/source/physxextensions/src/serialization/Xml/PsFastXml.h
vendored
Normal 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
|
||||
135
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnJointRepXSerializer.cpp
vendored
Normal file
135
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnJointRepXSerializer.cpp
vendored
Normal 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>;
|
||||
}
|
||||
67
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnJointRepXSerializer.h
vendored
Normal file
67
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnJointRepXSerializer.h
vendored
Normal 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
|
||||
134
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnPxStreamOperators.h
vendored
Normal file
134
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnPxStreamOperators.h
vendored
Normal 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
|
||||
244
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX1_0Defaults.h
vendored
Normal file
244
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX1_0Defaults.h
vendored
Normal 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" )
|
||||
273
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX3_1Defaults.h
vendored
Normal file
273
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX3_1Defaults.h
vendored
Normal 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" )
|
||||
312
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX3_2Defaults.h
vendored
Normal file
312
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepX3_2Defaults.h
vendored
Normal 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" )
|
||||
173
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCollection.h
vendored
Normal file
173
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCollection.h
vendored
Normal 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
|
||||
561
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCoreSerializer.cpp
vendored
Normal file
561
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCoreSerializer.cpp
vendored
Normal 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();
|
||||
}
|
||||
}
|
||||
121
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCoreSerializer.h
vendored
Normal file
121
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXCoreSerializer.h
vendored
Normal 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
|
||||
|
||||
90
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXSerializerImpl.h
vendored
Normal file
90
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXSerializerImpl.h
vendored
Normal 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
|
||||
462
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXUpgrader.cpp
vendored
Normal file
462
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXUpgrader.cpp
vendored
Normal 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;
|
||||
}
|
||||
} }
|
||||
54
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXUpgrader.h
vendored
Normal file
54
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnRepXUpgrader.h
vendored
Normal 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
|
||||
256
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnSimpleXmlWriter.h
vendored
Normal file
256
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnSimpleXmlWriter.h
vendored
Normal 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 << "<";
|
||||
break;
|
||||
case '>':
|
||||
mStream << ">";
|
||||
break;
|
||||
case '&':
|
||||
mStream << "&";
|
||||
break;
|
||||
case '\'':
|
||||
mStream << "'";
|
||||
break;
|
||||
case '"':
|
||||
mStream << """;
|
||||
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
|
||||
193
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnXmlDeserializer.h
vendored
Normal file
193
engine/third_party/physx/source/physxextensions/src/serialization/Xml/SnXmlDeserializer.h
vendored
Normal 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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user