This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,575 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "DyArticulationUtils.h"
#include "DyArticulationScalar.h"
#include "DyArticulationReference.h"
#include "DyArticulationFnsDebug.h"
namespace physx
{
namespace Dy
{
namespace ArticulationRef
{
Cm::SpatialVector propagateImpulse(const FsRow& row,
const FsJointVectors& j,
PxVec3& SZ,
const Cm::SpatialVector& Z,
const FsRowAux& aux)
{
typedef ArticulationFnsScalar Fns;
SZ = Fns::axisDot(reinterpret_cast<const Cm::SpatialVector*>(aux.S), Z);
return Fns::translateForce(getParentOffset(j), Z - Fns::axisMultiply(getDSI(row), SZ));
}
Cm::SpatialVector propagateVelocity(const FsRow& row,
const FsJointVectors& j,
const PxVec3& SZ,
const Cm::SpatialVector& v,
const FsRowAux& aux)
{
typedef ArticulationFnsScalar Fns;
Cm::SpatialVector w = Fns::translateMotion(-getParentOffset(j), v);
PxVec3 DSZ = Fns::multiply(row.D, SZ);
return w - Fns::axisMultiply(reinterpret_cast<const Cm::SpatialVector*>(aux.S), DSZ + Fns::axisDot(getDSI(row), w));
}
void applyImpulse(const FsData& matrix,
Cm::SpatialVector* velocity,
PxU32 linkID,
const Cm::SpatialVector& impulse)
{
typedef ArticulationFnsScalar Fns;
PX_ASSERT(matrix.linkCount<=DY_ARTICULATION_MAX_SIZE);
const FsRow* rows = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
Cm::SpatialVector dV[DY_ARTICULATION_MAX_SIZE];
PxVec3 SZ[DY_ARTICULATION_MAX_SIZE];
for(PxU32 i=0;i<matrix.linkCount;i++)
SZ[i] = PxVec3(0);
Cm::SpatialVector Z = -impulse;
for(;linkID!=0; linkID = matrix.parent[linkID])
Z = ArticulationRef::propagateImpulse(rows[linkID], jointVectors[linkID], SZ[linkID], Z, aux[linkID]);
dV[0] = Fns::getRootDeltaV(matrix,-Z);
for(PxU32 i=1;i<matrix.linkCount; i++)
dV[i] = ArticulationRef::propagateVelocity(rows[i], jointVectors[i], SZ[i], dV[matrix.parent[i]], aux[i]);
for(PxU32 i=0;i<matrix.linkCount;i++)
velocity[i] += dV[i];
}
void ltbFactor(FsData& m)
{
typedef ArticulationFnsScalar Fns;
LtbRow* rows = getLtbRows(m);
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
for(PxU32 i=0;i<m.linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(rows[i].inertia);
Cm::SpatialVector j[3];
for(PxU32 i=m.linkCount; --i>0;)
{
LtbRow& b = rows[i];
inertia[i] = Fns::invertInertia(inertia[i]);
PxU32 p = m.parent[i];
Cm::SpatialVector* j0 = &reinterpret_cast<Cm::SpatialVector&>(*b.j0),
* j1 = &reinterpret_cast<Cm::SpatialVector&>(*b.j1);
Fns::multiply(j, inertia[i], j1);
PxMat33 jResponse = Fns::invertSym33(-Fns::multiplySym(j, j1));
j1[0] = j[0]; j1[1] = j[1]; j1[2] = j[2];
b.jResponse = Mat33V_From_PxMat33(jResponse);
Fns::multiply(j, j0, jResponse);
inertia[p] = Fns::multiplySubtract(inertia[p], j, j0);
j0[0] = j[0]; j0[1] = j[1]; j0[2] = j[2];
}
rows[0].inertia = Fns::invertInertia(inertia[0]);
for(PxU32 i=1;i<m.linkCount;i++)
rows[i].inertia = inertia[i];
}
}
#if 0
void ltbSolve(const FsData& m,
Vec3V* c, // rhs error to solve for
Cm::SpatialVector* y) // velocity delta output
{
typedef ArticulationFnsScalar Fns;
PxVec4* b = reinterpret_cast<PxVec4*>(c);
const LtbRow* rows = getLtbRows(m);
PxMemZero(y, m.linkCount*sizeof(Cm::SpatialVector));
for(PxU32 i=m.linkCount;i-->1;)
{
PxU32 p = m.parent[i];
const LtbRow& r = rows[i];
b[i] -= PxVec4(Fns::axisDot(&static_cast<const Cm::SpatialVector&>(*r.j1), y[i]),0);
y[p] -= Fns::axisMultiply(&static_cast<const Cm::SpatialVector&>(*r.j0), b[i].getXYZ());
}
y[0] = Fns::multiply(rows[0].inertia,y[0]);
for(PxU32 i=1; i<m.linkCount; i++)
{
PxU32 p = m.parent[i];
const LtbRow& r = rows[i];
PxVec3 t = Fns::multiply(r.jResponse, b[i].getXYZ()) - Fns::axisDot(&static_cast<const Cm::SpatialVector&>(*r.j0), y[p]);
y[i] = Fns::multiply(r.inertia, y[i]) - Fns::axisMultiply(&static_cast<const Cm::SpatialVector&>(*r.j1), t);
}
}
void PxcFsPropagateDrivenInertiaScalar(FsData& matrix,
const FsInertia* baseInertia,
const PxReal* isf,
const Mat33V* load)
{
typedef ArticulationFnsScalar Fns;
Cm::SpatialVector IS[3], DSI[3];
PxMat33 D;
FsRow* rows = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
for(PxU32 i=0;i<matrix.linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(baseInertia[i]);
for(PxU32 i=matrix.linkCount; --i>0;)
{
FsRow& r = rows[i];
const FsRowAux& a = aux[i];
const FsJointVectors& jv = jointVectors[i];
Fns::multiply(IS, inertia[i], &static_cast<const Cm::SpatialVector&>(*a.S));
PX_ALIGN(16, PxMat33) L;
PxMat33_From_Mat33V(load[i], L);
D = Fns::invertSym33(Fns::multiplySym(&static_cast<const Cm::SpatialVector&>(*a.S), IS) + L*isf[i]);
Fns::multiply(DSI, IS, D);
r.D = Mat33V_From_PxMat33(D);
static_cast<Cm::SpatialVector&>(r.DSI[0]) = DSI[0];
static_cast<Cm::SpatialVector&>(r.DSI[1]) = DSI[1];
static_cast<Cm::SpatialVector&>(r.DSI[2]) = DSI[2];
inertia[matrix.parent[i]] += Fns::translate(getParentOffset(jv), Fns::multiplySubtract(inertia[i], DSI, IS));
}
FsInertia& m = getRootInverseInertia(matrix);
m = FsInertia(Fns::invertInertia(inertia[0]));
}
// no need to compile this ecxcept for verification, and it consumes huge amounts of stack space
void PxcFsComputeJointLoadsScalar(const FsData& matrix,
const FsInertia*PX_RESTRICT baseInertia,
Mat33V*PX_RESTRICT load,
const PxReal*PX_RESTRICT isf,
PxU32 linkCount,
PxU32 maxIterations)
{
typedef ArticulationFnsScalar Fns;
// the childward S
SpInertia leafwardInertia[DY_ARTICULATION_MAX_SIZE];
SpInertia rootwardInertia[DY_ARTICULATION_MAX_SIZE];
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
SpInertia contribToParent[DY_ARTICULATION_MAX_SIZE];
// total articulated inertia assuming the articulation is rooted here
const FsRow* row = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
PX_UNUSED(row);
PxMat33 load_[DY_ARTICULATION_MAX_SIZE];
for(PxU32 iter=0;iter<maxIterations;iter++)
{
for(PxU32 i=0;i<linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(baseInertia[i]);
for(PxU32 i=linkCount;i-->1;)
{
const FsJointVectors& j = jointVectors[i];
leafwardInertia[i] = inertia[i];
contribToParent[i] = Fns::propagate(inertia[i], &static_cast<const Cm::SpatialVector&>(*aux[i].S), load_[i], isf[i]);
inertia[matrix.parent[i]] += Fns::translate((PxVec3&)j.parentOffset, contribToParent[i]);
}
for(PxU32 i=1;i<linkCount;i++)
{
rootwardInertia[i] = Fns::translate(-(PxVec3&)jointVectors[i].parentOffset, inertia[matrix.parent[i]]) - contribToParent[i];
inertia[i] += Fns::propagate(rootwardInertia[i], &static_cast<const Cm::SpatialVector&>(*aux[i].S), load_[i], isf[i]);
}
for(PxU32 i=1;i<linkCount;i++)
{
load_[i] = Fns::computeDriveInertia(leafwardInertia[i], rootwardInertia[i], &static_cast<const Cm::SpatialVector&>(*aux[i].S));
PX_ASSERT(load_[i][0].isFinite() && load_[i][1].isFinite() && load_[2][i].isFinite());
}
}
for(PxU32 i=1;i<linkCount;i++)
load[i] = Mat33V_From_PxMat33(load_[i]);
}
void PxcFsApplyImpulse(const FsData& matrix,
PxU32 linkID,
const Cm::SpatialVector& impulse)
{
#if DY_ARTICULATION_DEBUG_VERIFY
PxcFsRefApplyImpulse(matrix, state.refVelocity, linkID, impulse);
#endif
Cm::SpatialVector Z = -impulse;
for(PxU32 i = linkID; i!=0; i = matrix.row[i].parent)
{
PxVec3 SZ;
Z = propagateImpulse(matrix.row[i], SZ, Z, matrix.aux[i]);
deferredSZRef(state,i) += SZ;
}
static_cast<Cm::SpatialVector &>(state.deferredZ) += Z;
state.dirty |= matrix.row[linkID].pathToRoot;
}
Cm::SpatialVector PxcFsGetVelocity(const FsData& matrix,
PxU32 linkID)
{
// find the dirty node on the path (including the root) with the lowest index
ArticulationBitField toUpdate = matrix.row[linkID].pathToRoot & state.dirty;
if(toUpdate)
{
ArticulationBitField ignoreNodes = (toUpdate & (0-toUpdate))-1;
ArticulationBitField path = matrix.row[linkID].pathToRoot & ~ignoreNodes, p = path;
ArticulationBitField newDirty = 0;
Cm::SpatialVector dV = Cm::SpatialVector::zero();
if(p & 1)
{
dV = getRootDeltaV(matrix, -deferredZ(state));
velocityRef(state, 0) += dV;
for(ArticulationBitField defer = matrix.row[0].children & ~path; defer; defer &= (defer-1))
deferredVelRef(state, ArticulationLowestSetBit(defer)) += dV;
deferredZRef(state) = Cm::SpatialVector::zero();
newDirty = matrix.row[0].children;
p--;
}
for(; p; p &= (p-1))
{
PxU32 i = ArticulationLowestSetBit(p);
dV = propagateVelocity(matrix.row[i], deferredSZ(state,i), dV + state.deferredVel[i], matrix.aux[i]);
velocityRef(state,i) += dV;
for(ArticulationBitField defer = matrix.row[i].children & ~path; defer; defer &= (defer-1))
deferredVelRef(state,ArticulationLowestSetBit(defer)) += dV;
newDirty |= matrix.row[i].children;
deferredVelRef(state,i) = Cm::SpatialVector::zero();
deferredSZRef(state,i) = PxVec3(0);
}
state.dirty = (state.dirty | newDirty)&~path;
}
#if DY_ARTICULATION_DEBUG_VERIFY
Cm::SpatialVector v = state.velocity[linkID];
Cm::SpatialVector rv = state.refVelocity[linkID];
PX_ASSERT((v-rv).magnitude()<1e-4f * rv.magnitude());
#endif
return state.velocity[linkID];
}
void PxcFsFlushVelocity(const FsData& matrix)
{
Cm::SpatialVector V = getRootDeltaV(matrix, -deferredZ(state));
deferredZRef(state) = Cm::SpatialVector::zero();
velocityRef(state,0) += V;
for(ArticulationBitField defer = matrix.row[0].children; defer; defer &= (defer-1))
deferredVelRef(state,ArticulationLowestSetBit(defer)) += V;
for(PxU32 i = 1; i<matrix.linkCount; i++)
{
Cm::SpatialVector V = propagateVelocity(matrix.row[i], deferredSZ(state,i), state.deferredVel[i], matrix.aux[i]);
deferredVelRef(state,i) = Cm::SpatialVector::zero();
deferredSZRef(state,i) = PxVec3(0);
velocityRef(state,i) += V;
for(ArticulationBitField defer = matrix.row[i].children; defer; defer &= (defer-1))
deferredVelRef(state,ArticulationLowestSetBit(defer)) += V;
}
state.dirty = 0;
}
void PxcFsPropagateDrivenInertiaScalar(FsData& matrix,
const FsInertia* baseInertia,
const PxReal* isf,
const Mat33V* load,
PxcFsScratchAllocator allocator)
{
typedef ArticulationFnsSimd<ArticulationFnsSimdBase> Fns;
Cm::SpatialVectorV IS[3];
PxMat33 D;
FsRow* rows = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
FsInertia *inertia = allocator.alloc<FsInertia>(matrix.linkCount);
PxMemCopy(inertia, baseInertia, matrix.linkCount*sizeof(FsInertia));
for(PxU32 i=matrix.linkCount; --i>0;)
{
FsRow& r = rows[i];
const FsRowAux& a = aux[i];
const FsJointVectors& jv = jointVectors[i];
Mat33V m = Fns::computeSIS(inertia[i], a.S, IS);
FloatV f = FLoad(isf[i]);
Mat33V D = Fns::invertSym33(Mat33V(V3ScaleAdd(load[i].col0, f, m.col0),
V3ScaleAdd(load[i].col1, f, m.col1),
V3ScaleAdd(load[i].col2, f, m.col2)));
r.D = D;
inertia[matrix.parent[i]] = Fns::addInertia(inertia[matrix.parent[i]],
Fns::translateInertia(jv.parentOffset, Fns::multiplySubtract(inertia[i], D, IS, r.DSI)));
}
getRootInverseInertia(matrix) = Fns::invertInertia(inertia[0]);
}
void PxcLtbSolve(const FsData& m,
Vec3V* c, // rhs error to solve for
Cm::SpatialVector* y) // velocity delta output
{
typedef ArticulationFnsScalar Fns;
PxVec4* b = reinterpret_cast<PxVec4*>(c);
const LtbRow* rows = getLtbRows(m);
PxMemZero(y, m.linkCount*sizeof(Cm::SpatialVector));
for(PxU32 i=m.linkCount;i-->1;)
{
PxU32 p = m.parent[i];
const LtbRow& r = rows[i];
b[i] -= PxVec4(Fns::axisDot(&static_cast<const Cm::SpatialVector&>(*r.j1), y[i]),0);
y[p] -= Fns::axisMultiply(&static_cast<const Cm::SpatialVector&>(*r.j0), b[i].getXYZ());
}
y[0] = Fns::multiply(rows[0].inertia,y[0]);
for(PxU32 i=1; i<m.linkCount; i++)
{
PxU32 p = m.parent[i];
const LtbRow& r = rows[i];
PxVec3 t = Fns::multiply(r.jResponse, b[i].getXYZ()) - Fns::axisDot(&static_cast<const Cm::SpatialVector&>(*r.j0), y[p]);
y[i] = Fns::multiply(r.inertia, y[i]) - Fns::axisMultiply(&static_cast<const Cm::SpatialVector&>(*r.j1), t);
}
}
#endif
#if DY_ARTICULATION_DEBUG_VERIFY
void PxcLtbFactorScalar(FsData& m)
{
typedef ArticulationFnsScalar Fns;
LtbRow* rows = getLtbRows(m);
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
for(PxU32 i=0;i<m.linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(rows[i].inertia);
Cm::SpatialVector j[3];
for(PxU32 i=m.linkCount; --i>0;)
{
LtbRow& b = rows[i];
inertia[i] = Fns::invertInertia(inertia[i]);
PxU32 p = m.parent[i];
Cm::SpatialVector* j0 = &reinterpret_cast<Cm::SpatialVector&>(*b.j0),
* j1 = &reinterpret_cast<Cm::SpatialVector&>(*b.j1);
Fns::multiply(j, inertia[i], j1);
PxMat33 jResponse = Fns::invertSym33(-Fns::multiplySym(j, j1));
j1[0] = j[0]; j1[1] = j[1]; j1[2] = j[2];
b.jResponse = Mat33V_From_PxMat33(jResponse);
Fns::multiply(j, j0, jResponse);
inertia[p] = Fns::multiplySubtract(inertia[p], j, j0);
j0[0] = j[0]; j0[1] = j[1]; j0[2] = j[2];
}
rows[0].inertia = Fns::invertInertia(inertia[0]);
for(PxU32 i=1;i<m.linkCount;i++)
rows[i].inertia = inertia[i];
}
void PxcFsPropagateDrivenInertiaScalar(FsData& matrix,
const FsInertia* baseInertia,
const PxReal* isf,
const Mat33V* load)
{
typedef ArticulationFnsScalar Fns;
Cm::SpatialVector IS[3], DSI[3];
PxMat33 D;
FsRow* rows = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
for(PxU32 i=0;i<matrix.linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(baseInertia[i]);
for(PxU32 i=matrix.linkCount; --i>0;)
{
FsRow& r = rows[i];
const FsRowAux& a = aux[i];
const FsJointVectors& jv = jointVectors[i];
Fns::multiply(IS, inertia[i], &reinterpret_cast<const Cm::SpatialVector&>(*a.S));
PX_ALIGN(16, PxMat33) L;
PxMat33_From_Mat33V(load[i], L);
D = Fns::invertSym33(Fns::multiplySym(&reinterpret_cast<const Cm::SpatialVector&>(*a.S), IS) + L*isf[i]);
Fns::multiply(DSI, IS, D);
r.D = Mat33V_From_PxMat33(D);
reinterpret_cast<Cm::SpatialVector&>(r.DSI[0]) = DSI[0];
reinterpret_cast<Cm::SpatialVector&>(r.DSI[1]) = DSI[1];
reinterpret_cast<Cm::SpatialVector&>(r.DSI[2]) = DSI[2];
inertia[matrix.parent[i]] += Fns::translate(getParentOffset(jv), Fns::multiplySubtract(inertia[i], DSI, IS));
}
FsInertia& m = getRootInverseInertia(matrix);
m = FsInertia(Fns::invertInertia(inertia[0]));
}
// no need to compile this ecxcept for verification, and it consumes huge amounts of stack space
void PxcFsComputeJointLoadsScalar(const FsData& matrix,
const FsInertia*PX_RESTRICT baseInertia,
Mat33V*PX_RESTRICT load,
const PxReal*PX_RESTRICT isf,
PxU32 linkCount,
PxU32 maxIterations)
{
typedef ArticulationFnsScalar Fns;
// the childward S
SpInertia leafwardInertia[DY_ARTICULATION_MAX_SIZE];
SpInertia rootwardInertia[DY_ARTICULATION_MAX_SIZE];
SpInertia inertia[DY_ARTICULATION_MAX_SIZE];
SpInertia contribToParent[DY_ARTICULATION_MAX_SIZE];
// total articulated inertia assuming the articulation is rooted here
const FsRow* row = getFsRows(matrix);
const FsRowAux* aux = getAux(matrix);
const FsJointVectors* jointVectors = getJointVectors(matrix);
PX_UNUSED(row);
PxMat33 load_[DY_ARTICULATION_MAX_SIZE];
for(PxU32 iter=0;iter<maxIterations;iter++)
{
for(PxU32 i=0;i<linkCount;i++)
inertia[i] = ArticulationFnsDebug::unsimdify(baseInertia[i]);
for(PxU32 i=linkCount;i-->1;)
{
const FsJointVectors& j = jointVectors[i];
leafwardInertia[i] = inertia[i];
contribToParent[i] = Fns::propagate(inertia[i], &reinterpret_cast<const Cm::SpatialVector&>(*aux[i].S), load_[i], isf[i]);
inertia[matrix.parent[i]] += Fns::translate((PxVec3&)j.parentOffset, contribToParent[i]);
}
for(PxU32 i=1;i<linkCount;i++)
{
rootwardInertia[i] = Fns::translate(-(PxVec3&)jointVectors[i].parentOffset, inertia[matrix.parent[i]]) - contribToParent[i];
inertia[i] += Fns::propagate(rootwardInertia[i], &reinterpret_cast<const Cm::SpatialVector&>(*aux[i].S), load_[i], isf[i]);
}
for(PxU32 i=1;i<linkCount;i++)
{
load_[i] = Fns::computeDriveInertia(leafwardInertia[i], rootwardInertia[i], &reinterpret_cast<const Cm::SpatialVector&>(*aux[i].S));
PX_ASSERT(load_[i][0].isFinite() && load_[i][1].isFinite() && load_[2][i].isFinite());
}
}
for(PxU32 i=1;i<linkCount;i++)
load[i] = Mat33V_From_PxMat33(load_[i]);
}
#endif
}
}