Files
XCEngine/engine/third_party/physx/source/gpucommon/include/PxSpatialMatrix.h

291 lines
9.7 KiB
C
Raw Normal View History

// 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 PX_SPATIAL_MATRIX_H
#define PX_SPATIAL_MATRIX_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxMat33.h"
#include "CmSpatialVector.h"
namespace physx
{
struct PxSpatialMatrix33
{
PxReal column[3][3];
};
struct PxSpatialMatrix63
{
PxReal column[6][3];
};
struct PxSpatialMatrix36
{
PxReal column[3][6];
};
//144 bytes
struct PxSpatialMatrix
{
public:
PxReal column[6][6];
PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::UnAlignedSpatialVector operator * (const Cm::UnAlignedSpatialVector& s) const
{
PxReal st[6];
st[0] = s.top.x; st[1] = s.top.y; st[2] = s.top.z;
st[3] = s.bottom.x; st[4] = s.bottom.y; st[5] = s.bottom.z;
PxReal result[6];
for (PxU32 i = 0; i < 6; ++i)
{
result[i] = 0.f;
for (PxU32 j = 0; j < 6; ++j)
{
result[i] += column[j][i] * st[j];
}
}
Cm::UnAlignedSpatialVector temp;
temp.top.x = result[0]; temp.top.y = result[1]; temp.top.z = result[2];
temp.bottom.x = result[3]; temp.bottom.y = result[4]; temp.bottom.z = result[5];
return temp;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33 invertSym33(const PxMat33& in)
{
PxVec3 v0 = in[1].cross(in[2]),
v1 = in[2].cross(in[0]),
v2 = in[0].cross(in[1]);
PxReal det = v0.dot(in[0]);
if (det != 0)
{
PxReal recipDet = 1.0f / det;
return PxMat33(v0 * recipDet,
PxVec3(v0.y, v1.y, v1.z) * recipDet,
PxVec3(v0.z, v1.z, v2.z) * recipDet);
}
else
{
return PxMat33(PxIdentity);
}
}
PX_CUDA_CALLABLE void initialize(const PxMat33& inertia, const PxReal mass)
{
column[0][0] = 0.f; column[0][1] = 0.f; column[0][2] = 0.f;
column[1][0] = 0.f; column[1][1] = 0.f; column[1][2] = 0.f;
column[2][0] = 0.f; column[2][1] = 0.f; column[2][2] = 0.f;
column[0][3] = mass; column[0][4] = 0.f; column[0][5] = 0.f;
column[1][3] = 0.f; column[1][4] = mass; column[1][5] = 0.f;
column[2][3] = 0.f; column[2][4] = 0.f; column[2][5] = mass;
column[3][0] = inertia.column0.x; column[3][1] = inertia.column0.y; column[3][2] = inertia.column0.z;
column[4][0] = inertia.column1.x; column[4][1] = inertia.column1.y; column[4][2] = inertia.column1.z;
column[5][0] = inertia.column2.x; column[5][1] = inertia.column2.y; column[5][2] = inertia.column2.z;
column[3][3] = 0.f; column[3][4] = 0.f; column[3][5] = 0.f;
column[4][3] = 0.f; column[4][4] = 0.f; column[4][5] = 0.f;
column[5][3] = 0.f; column[5][4] = 0.f; column[5][5] = 0.f;
}
PX_CUDA_CALLABLE PxMat33 topLeft() const
{
return PxMat33( PxVec3(column[0][0], column[0][1], column[0][2]),
PxVec3(column[1][0], column[1][1], column[1][2]),
PxVec3(column[2][0], column[2][1], column[2][2]));
}
PX_CUDA_CALLABLE void setTopLeft(const PxMat33& m)
{
column[0][0] = m.column0.x; column[0][1] = m.column0.y; column[0][2] = m.column0.z;
column[1][0] = m.column1.x; column[1][1] = m.column1.y; column[1][2] = m.column1.z;
column[2][0] = m.column2.x; column[2][1] = m.column2.y; column[2][2] = m.column2.z;
}
PX_CUDA_CALLABLE PxMat33 bottomLeft() const
{
return PxMat33( PxVec3(column[0][3], column[0][4], column[0][5]),
PxVec3(column[1][3], column[1][4], column[1][5]),
PxVec3(column[2][3], column[2][4], column[2][5]));
}
PX_CUDA_CALLABLE void setBottomLeft(const PxMat33& m)
{
column[0][3] = m.column0.x; column[0][4] = m.column0.y; column[0][5] = m.column0.z;
column[1][3] = m.column1.x; column[1][4] = m.column1.y; column[1][5] = m.column1.z;
column[2][3] = m.column2.x; column[2][4] = m.column2.y; column[2][5] = m.column2.z;
}
PX_CUDA_CALLABLE PxMat33 topRight() const
{
return PxMat33( PxVec3(column[3][0], column[3][1], column[3][2]),
PxVec3(column[4][0], column[4][1], column[4][2]),
PxVec3(column[5][0], column[5][1], column[5][2]));
}
PX_CUDA_CALLABLE void setTopRight(const PxMat33& m)
{
column[3][0] = m.column0.x; column[3][1] = m.column0.y; column[3][2] = m.column0.z;
column[4][0] = m.column1.x; column[4][1] = m.column1.y; column[4][2] = m.column1.z;
column[5][0] = m.column2.x; column[5][1] = m.column2.y; column[5][2] = m.column2.z;
}
PX_CUDA_CALLABLE PxMat33 bottomRight() const
{
return PxMat33( PxVec3(column[3][3], column[3][4], column[3][5]),
PxVec3(column[4][3], column[4][4], column[4][5]),
PxVec3(column[5][3], column[5][4], column[5][5]));
}
PX_CUDA_CALLABLE void setBottomRight(const PxMat33& m)
{
column[3][3] = m.column0.x; column[3][4] = m.column0.y; column[3][5] = m.column0.z;
column[4][3] = m.column1.x; column[4][4] = m.column1.y; column[4][5] = m.column1.z;
column[5][3] = m.column2.x; column[5][4] = m.column2.y; column[5][5] = m.column2.z;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxSpatialMatrix invertInertia()
{
//bottom left
PxMat33 aa( PxVec3(column[0][3], column[0][4], column[0][5]),
PxVec3(column[1][3], column[1][4], column[1][5]),
PxVec3(column[2][3], column[2][4], column[2][5]));
// top right
PxMat33 ll(PxVec3(column[3][0], column[3][1], column[3][2]),
PxVec3(column[4][0], column[4][1], column[4][2]),
PxVec3(column[5][0], column[5][1], column[5][2]));
//top left
PxMat33 la(PxVec3(column[0][0], column[0][1], column[0][2]),
PxVec3(column[1][0], column[1][1], column[1][2]),
PxVec3(column[2][0], column[2][1], column[2][2]));
aa = (aa + aa.getTranspose())*0.5f;
ll = (ll + ll.getTranspose())*0.5f;
PxMat33 AAInv = invertSym33(aa);
PxMat33 z = -la * AAInv;
PxMat33 S = ll + z * la.getTranspose(); // Schur complement of mAA
PxMat33 LL = invertSym33(S);
PxMat33 LA = LL * z;
PxMat33 AA = AAInv + z.getTranspose() * LA;
PxSpatialMatrix result;
PxMat33 topleft = LA.getTranspose();
//top left
result.column[0][0] = topleft.column0[0];
result.column[0][1] = topleft.column0[1];
result.column[0][2] = topleft.column0[2];
result.column[1][0] = topleft.column1[0];
result.column[1][1] = topleft.column1[1];
result.column[1][2] = topleft.column1[2];
result.column[2][0] = topleft.column2[0];
result.column[2][1] = topleft.column2[1];
result.column[2][2] = topleft.column2[2];
//top right
result.column[3][0] = AA.column0[0];
result.column[3][1] = AA.column0[1];
result.column[3][2] = AA.column0[2];
result.column[4][0] = AA.column1[0];
result.column[4][1] = AA.column1[1];
result.column[4][2] = AA.column1[2];
result.column[5][0] = AA.column2[0];
result.column[5][1] = AA.column2[1];
result.column[5][2] = AA.column2[2];
//bottom left
result.column[0][3] = LL.column0[0];
result.column[0][4] = LL.column0[1];
result.column[0][5] = LL.column0[2];
result.column[1][3] = LL.column1[0];
result.column[1][4] = LL.column1[1];
result.column[1][5] = LL.column1[2];
result.column[2][3] = LL.column2[0];
result.column[2][4] = LL.column2[1];
result.column[2][5] = LL.column2[2];
//bottom right
result.column[3][3] = LA.column0[0];
result.column[3][4] = LA.column0[1];
result.column[3][5] = LA.column0[2];
result.column[4][3] = LA.column1[0];
result.column[4][4] = LA.column1[1];
result.column[4][5] = LA.column1[2];
result.column[5][3] = LA.column2[0];
result.column[5][4] = LA.column2[1];
result.column[5][5] = LA.column2[2];
return result;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal& operator()(PxU32 row, PxU32 col)
{
return column[col][row];
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal operator()(PxU32 row, PxU32 col) const
{
return column[col][row];
}
//A bit of a misuse. In featherstone articulations, we use this matrix to store
//the invMass/sqrtInvInertia of a rigid body in a way that is compatible with the
//response matrix produced by our articulation code. In order for this to work,
//we must also scale the angular term by the inertia tensor for rigid bodies.
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 multiplyInertia(const PxVec3& v) const
{
return PxVec3( column[3][0] * v.x + column[3][1] * v.y + column[3][2] * v.z,
column[4][0] * v.x + column[4][1] * v.y + column[4][2] * v.z,
column[5][0] * v.x + column[5][1] * v.y + column[5][2] * v.z
);
}
};
}
#endif