| 1 | // |
| 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions |
| 4 | // are met: |
| 5 | // * Redistributions of source code must retain the above copyright |
| 6 | // notice, this list of conditions and the following disclaimer. |
| 7 | // * Redistributions in binary form must reproduce the above copyright |
| 8 | // notice, this list of conditions and the following disclaimer in the |
| 9 | // documentation and/or other materials provided with the distribution. |
| 10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
| 11 | // contributors may be used to endorse or promote products derived |
| 12 | // from this software without specific prior written permission. |
| 13 | // |
| 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
| 15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | // |
| 26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
| 27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
| 28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
| 29 | |
| 30 | #ifndef DY_FEATHERSTONE_ARTICULATION_UTIL_H |
| 31 | #define DY_FEATHERSTONE_ARTICULATION_UTIL_H |
| 32 | |
| 33 | #include "PsVecMath.h" |
| 34 | #include "CmSpatialVector.h" |
| 35 | #include "PsBitUtils.h" |
| 36 | #include "foundation/PxMemory.h" |
| 37 | |
| 38 | namespace physx |
| 39 | { |
| 40 | |
| 41 | namespace Dy |
| 42 | { |
| 43 | static const size_t DY_MAX_DOF = 6; |
| 44 | |
| 45 | struct SpatialSubspaceMatrix |
| 46 | { |
| 47 | static const PxU32 MaxColumns = 3; |
| 48 | public: |
| 49 | |
| 50 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialSubspaceMatrix() :numColumns(0) |
| 51 | { |
| 52 | //PxMemZero(columns, sizeof(Cm::SpatialVectorF) * 6); |
| 53 | memset(s: columns, c: 0, n: sizeof(Cm::UnAlignedSpatialVector) * MaxColumns); |
| 54 | } |
| 55 | |
| 56 | PX_CUDA_CALLABLE PX_FORCE_INLINE void setNumColumns(const PxU32 nc) |
| 57 | { |
| 58 | numColumns = nc; |
| 59 | } |
| 60 | |
| 61 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getNumColumns() const |
| 62 | { |
| 63 | return numColumns; |
| 64 | } |
| 65 | |
| 66 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVectorF transposeMultiply(Cm::SpatialVectorF& v) const |
| 67 | { |
| 68 | PxReal result[6]; |
| 69 | for (PxU32 i = 0; i < numColumns; ++i) |
| 70 | { |
| 71 | const Cm::UnAlignedSpatialVector& row = columns[i]; |
| 72 | result[i] = row.dot(v); |
| 73 | } |
| 74 | |
| 75 | Cm::SpatialVectorF res; |
| 76 | res.top.x = result[0]; res.top.y = result[1]; res.top.z = result[2]; |
| 77 | res.bottom.x = result[3]; res.bottom.y = result[4]; res.bottom.z = result[5]; |
| 78 | |
| 79 | return res; |
| 80 | |
| 81 | } |
| 82 | |
| 83 | PX_CUDA_CALLABLE PX_FORCE_INLINE void setColumn(const PxU32 index, const PxVec3& top, const PxVec3& bottom) |
| 84 | { |
| 85 | PX_ASSERT(index < MaxColumns); |
| 86 | columns[index] = Cm::SpatialVectorF(top, bottom); |
| 87 | } |
| 88 | |
| 89 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::UnAlignedSpatialVector& operator[](unsigned int num) |
| 90 | { |
| 91 | PX_ASSERT(num < MaxColumns); |
| 92 | return columns[num]; |
| 93 | } |
| 94 | |
| 95 | PX_CUDA_CALLABLE PX_FORCE_INLINE const Cm::UnAlignedSpatialVector& operator[](unsigned int num) const |
| 96 | { |
| 97 | PX_ASSERT(num < MaxColumns); |
| 98 | return columns[num]; |
| 99 | } |
| 100 | |
| 101 | PX_CUDA_CALLABLE PX_FORCE_INLINE const Cm::UnAlignedSpatialVector* getColumns() const |
| 102 | { |
| 103 | return columns; |
| 104 | } |
| 105 | |
| 106 | |
| 107 | private: |
| 108 | Cm::UnAlignedSpatialVector columns[MaxColumns]; //192 192 |
| 109 | PxU32 numColumns; //4 208 (12 bytes padding) |
| 110 | |
| 111 | }; |
| 112 | |
| 113 | //this should be 6x6 matrix |
| 114 | //|R, 0| |
| 115 | //|-R*rX, R| |
| 116 | struct SpatialTransform |
| 117 | { |
| 118 | PxMat33 R; |
| 119 | PxQuat q; |
| 120 | PxMat33 T; |
| 121 | |
| 122 | public: |
| 123 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialTransform() : R(PxZero), T(PxZero) |
| 124 | { |
| 125 | } |
| 126 | |
| 127 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialTransform(const PxMat33& R_, const PxMat33& T_) : R(R_), T(T_) |
| 128 | { |
| 129 | q = PxQuat(R_); |
| 130 | } |
| 131 | |
| 132 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialTransform(const PxQuat& q_, const PxMat33& T_) : q(q_), T(T_) |
| 133 | { |
| 134 | R = PxMat33(q_); |
| 135 | } |
| 136 | |
| 137 | //This assume angular is the top vector and linear is the bottom vector |
| 138 | /*PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVector operator *(const Cm::SpatialVector& s) const |
| 139 | { |
| 140 | const PxVec3 angular = R * s.angular; |
| 141 | const PxVec3 linear = T * s.angular + R * s.linear; |
| 142 | return Cm::SpatialVector(linear, angular); |
| 143 | }*/ |
| 144 | |
| 145 | |
| 146 | ////This assume angular is the top vector and linear is the bottom vector |
| 147 | //PX_FORCE_INLINE Cm::SpatialVectorF operator *(Cm::SpatialVectorF& s) const |
| 148 | //{ |
| 149 | // const PxVec3 top = R * s.top; |
| 150 | // const PxVec3 bottom = T * s.top + R * s.bottom; |
| 151 | |
| 152 | // const PxVec3 top1 = q.rotate(s.top); |
| 153 | // const PxVec3 bottom1 = T * s.top + q.rotate(s.bottom); |
| 154 | |
| 155 | ///* const PxVec3 tDif = (top - top1).abs(); |
| 156 | // const PxVec3 bDif = (bottom - bottom1).abs(); |
| 157 | // const PxReal eps = 0.001f; |
| 158 | // PX_ASSERT(tDif.x < eps && tDif.y < eps && tDif.z < eps); |
| 159 | // PX_ASSERT(bDif.x < eps && bDif.y < eps && bDif.z < eps);*/ |
| 160 | // return Cm::SpatialVectorF(top1, bottom1); |
| 161 | //} |
| 162 | |
| 163 | //This assume angular is the top vector and linear is the bottom vector |
| 164 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVectorF operator *(const Cm::SpatialVectorF& s) const |
| 165 | { |
| 166 | //const PxVec3 top = R * s.top; |
| 167 | //const PxVec3 bottom = T * s.top + R * s.bottom; |
| 168 | |
| 169 | const PxVec3 top1 = q.rotate(v: s.top); |
| 170 | const PxVec3 bottom1 = T * s.top + q.rotate(v: s.bottom); |
| 171 | |
| 172 | return Cm::SpatialVectorF(top1, bottom1); |
| 173 | } |
| 174 | |
| 175 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::UnAlignedSpatialVector operator *(const Cm::UnAlignedSpatialVector& s) const |
| 176 | { |
| 177 | //const PxVec3 top = R * s.top; |
| 178 | //const PxVec3 bottom = T * s.top + R * s.bottom; |
| 179 | |
| 180 | const PxVec3 top1 = q.rotate(v: s.top); |
| 181 | const PxVec3 bottom1 = T * s.top + q.rotate(v: s.bottom); |
| 182 | |
| 183 | return Cm::UnAlignedSpatialVector(top1, bottom1); |
| 184 | } |
| 185 | |
| 186 | //transpose is the same as inverse, R(inverse) = R(transpose) |
| 187 | //|R(t), 0 | |
| 188 | //|rXR(t), R(t)| |
| 189 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialTransform getTranspose() const |
| 190 | { |
| 191 | SpatialTransform ret; |
| 192 | ret.q = q.getConjugate(); |
| 193 | ret.R = R.getTranspose(); |
| 194 | ret.T = T.getTranspose(); |
| 195 | return ret; |
| 196 | |
| 197 | } |
| 198 | |
| 199 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVectorF transposeTransform(const Cm::SpatialVectorF& s) const |
| 200 | { |
| 201 | const PxVec3 top1 = q.rotateInv(v: s.top); |
| 202 | const PxVec3 bottom1 = T.transformTranspose(other: s.top) + q.rotateInv(v: s.bottom); |
| 203 | |
| 204 | return Cm::SpatialVectorF(top1, bottom1); |
| 205 | } |
| 206 | |
| 207 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::UnAlignedSpatialVector transposeTransform(const Cm::UnAlignedSpatialVector& s) const |
| 208 | { |
| 209 | const PxVec3 top1 = q.rotateInv(v: s.top); |
| 210 | const PxVec3 bottom1 = T.transformTranspose(other: s.top) + q.rotateInv(v: s.bottom); |
| 211 | |
| 212 | return Cm::UnAlignedSpatialVector(top1, bottom1); |
| 213 | } |
| 214 | |
| 215 | PX_CUDA_CALLABLE PX_FORCE_INLINE void operator =(SpatialTransform& other) |
| 216 | { |
| 217 | R = other.R; |
| 218 | q = other.q; |
| 219 | T = other.T; |
| 220 | } |
| 221 | |
| 222 | }; |
| 223 | |
| 224 | struct InvStIs |
| 225 | { |
| 226 | PxReal invStIs[3][3]; |
| 227 | }; |
| 228 | |
| 229 | struct IsInvD |
| 230 | { |
| 231 | Cm::SpatialVectorF isInvD[3]; |
| 232 | }; |
| 233 | |
| 234 | //this should be 6x6 matrix and initialize to |
| 235 | //|0, M| |
| 236 | //|I, 0| |
| 237 | //this should be 6x6 matrix but bottomRight is the transpose of topLeft |
| 238 | //so we can get rid of bottomRight |
| 239 | struct SpatialMatrix |
| 240 | { |
| 241 | PxMat33 topLeft; // intialize to 0 |
| 242 | PxMat33 topRight; // initialize to mass matrix |
| 243 | PxMat33 bottomLeft; // initialize to inertia |
| 244 | PxU32 padding; //4 112 |
| 245 | |
| 246 | public: |
| 247 | |
| 248 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix() |
| 249 | { |
| 250 | } |
| 251 | |
| 252 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix(PxZERO r) : topLeft(PxZero), topRight(PxZero), |
| 253 | bottomLeft(PxZero) |
| 254 | { |
| 255 | PX_UNUSED(r); |
| 256 | } |
| 257 | |
| 258 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix(const PxMat33& topLeft_, const PxMat33& topRight_, const PxMat33& bottomLeft_) |
| 259 | { |
| 260 | topLeft = topLeft_; |
| 261 | topRight = topRight_; |
| 262 | bottomLeft = bottomLeft_; |
| 263 | } |
| 264 | |
| 265 | PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33 getBottomRight() const |
| 266 | { |
| 267 | return topLeft.getTranspose(); |
| 268 | } |
| 269 | |
| 270 | PX_FORCE_INLINE void setZero() |
| 271 | { |
| 272 | topLeft = PxMat33(0.f); |
| 273 | topRight = PxMat33(0.f); |
| 274 | bottomLeft = PxMat33(0.f); |
| 275 | } |
| 276 | |
| 277 | |
| 278 | //This assume angular is the top vector and linear is the bottom vector |
| 279 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVector operator *(const Cm::SpatialVector& s) const |
| 280 | { |
| 281 | const PxVec3 angular = topLeft * s.angular + topRight * s.linear; |
| 282 | const PxVec3 linear = bottomLeft * s.angular + topLeft.getTranspose() * s.linear; |
| 283 | return Cm::SpatialVector(linear, angular); |
| 284 | } |
| 285 | |
| 286 | //This assume angular is the top vector and linear is the bottom vector |
| 287 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::SpatialVectorF operator *(const Cm::SpatialVectorF& s) const |
| 288 | { |
| 289 | const PxVec3 top = topLeft * s.top + topRight * s.bottom; |
| 290 | const PxVec3 bottom = bottomLeft * s.top + topLeft.transformTranspose(other: s.bottom); |
| 291 | |
| 292 | return Cm::SpatialVectorF(top, bottom); |
| 293 | } |
| 294 | |
| 295 | PX_CUDA_CALLABLE PX_FORCE_INLINE Cm::UnAlignedSpatialVector operator *(const Cm::UnAlignedSpatialVector& s) const |
| 296 | { |
| 297 | const PxVec3 top = topLeft * s.top + topRight * s.bottom; |
| 298 | const PxVec3 bottom = bottomLeft * s.top + topLeft.transformTranspose(other: s.bottom); |
| 299 | |
| 300 | return Cm::UnAlignedSpatialVector(top, bottom); |
| 301 | } |
| 302 | |
| 303 | |
| 304 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix operator *(const PxReal& s) const |
| 305 | { |
| 306 | const PxMat33 newTopLeft = topLeft * s; |
| 307 | const PxMat33 newTopRight = topRight * s; |
| 308 | const PxMat33 newBottomLeft = bottomLeft * s; |
| 309 | |
| 310 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 311 | } |
| 312 | |
| 313 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix operator -(const SpatialMatrix& s) const |
| 314 | { |
| 315 | PxMat33 newTopLeft = topLeft - s.topLeft; |
| 316 | PxMat33 newTopRight = topRight - s.topRight; |
| 317 | PxMat33 newBottomLeft = bottomLeft - s.bottomLeft; |
| 318 | |
| 319 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 320 | } |
| 321 | |
| 322 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix operator +(const SpatialMatrix& s) const |
| 323 | { |
| 324 | PxMat33 newTopLeft = topLeft + s.topLeft; |
| 325 | PxMat33 newTopRight = topRight + s.topRight; |
| 326 | PxMat33 newBottomLeft = bottomLeft + s.bottomLeft; |
| 327 | |
| 328 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 329 | } |
| 330 | |
| 331 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix operator-() |
| 332 | { |
| 333 | PxMat33 newTopLeft = -topLeft; |
| 334 | PxMat33 newTopRight = -topRight; |
| 335 | PxMat33 newBottomLeft = -bottomLeft; |
| 336 | |
| 337 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 338 | } |
| 339 | |
| 340 | PX_CUDA_CALLABLE PX_FORCE_INLINE void operator +=(const SpatialMatrix& s) |
| 341 | { |
| 342 | topLeft += s.topLeft; |
| 343 | topRight += s.topRight; |
| 344 | bottomLeft += s.bottomLeft; |
| 345 | } |
| 346 | |
| 347 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix operator *(const SpatialMatrix& s) |
| 348 | { |
| 349 | PxMat33 sBottomRight = s.topLeft.getTranspose(); |
| 350 | PxMat33 bottomRight = topLeft.getTranspose(); |
| 351 | |
| 352 | PxMat33 newTopLeft = topLeft * s.topLeft + topRight * s.bottomLeft; |
| 353 | PxMat33 newTopRight = topLeft * s.topRight + topRight * sBottomRight; |
| 354 | PxMat33 newBottomLeft = bottomLeft * s.topLeft + bottomRight * s.bottomLeft; |
| 355 | |
| 356 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 357 | } |
| 358 | |
| 359 | static SpatialMatrix constructSpatialMatrix(const Cm::SpatialVector& Is, const Cm::SpatialVector& stI) |
| 360 | { |
| 361 | //construct top left |
| 362 | PxVec3 tLeftC0 = Is.angular * stI.angular.x; |
| 363 | PxVec3 tLeftC1 = Is.angular * stI.angular.y; |
| 364 | PxVec3 tLeftC2 = Is.angular * stI.angular.z; |
| 365 | |
| 366 | PxMat33 topLeft(tLeftC0, tLeftC1, tLeftC2); |
| 367 | |
| 368 | //construct top right |
| 369 | PxVec3 tRightC0 = Is.angular * stI.linear.x; |
| 370 | PxVec3 tRightC1 = Is.angular * stI.linear.y; |
| 371 | PxVec3 tRightC2 = Is.angular * stI.linear.z; |
| 372 | PxMat33 topRight(tRightC0, tRightC1, tRightC2); |
| 373 | |
| 374 | //construct bottom left |
| 375 | PxVec3 bLeftC0 = Is.linear * stI.angular.x; |
| 376 | PxVec3 bLeftC1 = Is.linear * stI.angular.y; |
| 377 | PxVec3 bLeftC2 = Is.linear * stI.angular.z; |
| 378 | PxMat33 bottomLeft(bLeftC0, bLeftC1, bLeftC2); |
| 379 | |
| 380 | return SpatialMatrix(topLeft, topRight, bottomLeft); |
| 381 | } |
| 382 | |
| 383 | static PX_CUDA_CALLABLE SpatialMatrix constructSpatialMatrix(const Cm::SpatialVectorF& Is, const Cm::SpatialVectorF& stI) |
| 384 | { |
| 385 | //construct top left |
| 386 | PxVec3 tLeftC0 = Is.top * stI.top.x; |
| 387 | PxVec3 tLeftC1 = Is.top * stI.top.y; |
| 388 | PxVec3 tLeftC2 = Is.top * stI.top.z; |
| 389 | |
| 390 | PxMat33 topLeft(tLeftC0, tLeftC1, tLeftC2); |
| 391 | |
| 392 | //construct top right |
| 393 | PxVec3 tRightC0 = Is.top * stI.bottom.x; |
| 394 | PxVec3 tRightC1 = Is.top * stI.bottom.y; |
| 395 | PxVec3 tRightC2 = Is.top * stI.bottom.z; |
| 396 | PxMat33 topRight(tRightC0, tRightC1, tRightC2); |
| 397 | |
| 398 | //construct bottom left |
| 399 | PxVec3 bLeftC0 = Is.bottom * stI.top.x; |
| 400 | PxVec3 bLeftC1 = Is.bottom * stI.top.y; |
| 401 | PxVec3 bLeftC2 = Is.bottom * stI.top.z; |
| 402 | PxMat33 bottomLeft(bLeftC0, bLeftC1, bLeftC2); |
| 403 | |
| 404 | return SpatialMatrix(topLeft, topRight, bottomLeft); |
| 405 | } |
| 406 | |
| 407 | static PX_CUDA_CALLABLE SpatialMatrix constructSpatialMatrix(const Cm::SpatialVectorF* columns) |
| 408 | { |
| 409 | PxMat33 topLeft(columns[0].top, columns[1].top, columns[2].top); |
| 410 | PxMat33 bottomLeft(columns[0].bottom, columns[1].bottom, columns[2].bottom); |
| 411 | PxMat33 topRight(columns[3].top, columns[4].top, columns[5].top); |
| 412 | |
| 413 | return SpatialMatrix(topLeft, topRight, bottomLeft); |
| 414 | } |
| 415 | |
| 416 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix getTranspose() |
| 417 | { |
| 418 | PxMat33 newTopLeft = topLeft.getTranspose(); |
| 419 | PxMat33 newTopRight = bottomLeft.getTranspose(); |
| 420 | PxMat33 newBottomLeft = topRight.getTranspose(); |
| 421 | //PxMat33 newBottomRight = bottomRight.getTranspose(); |
| 422 | |
| 423 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft);// , newBottomRight); |
| 424 | } |
| 425 | |
| 426 | //static bool isTranspose(const PxMat33& a, const PxMat33& b) |
| 427 | //{ |
| 428 | // PxReal eps = 0.01f; |
| 429 | // //test bottomRight is the transpose of topLeft |
| 430 | // for (PxU32 i = 0; i <3; ++i) |
| 431 | // { |
| 432 | // for (PxU32 j = 0; j <3; ++j) |
| 433 | // { |
| 434 | // if (PxAbs(a[i][j] - b[j][i]) > eps) |
| 435 | // return false; |
| 436 | // } |
| 437 | // } |
| 438 | |
| 439 | // return true; |
| 440 | //} |
| 441 | |
| 442 | PX_FORCE_INLINE bool isIdentity(const PxMat33& matrix) |
| 443 | { |
| 444 | PxReal eps = 0.00001f; |
| 445 | float x = PxAbs(a: 1.f - matrix.column0.x); |
| 446 | float y = PxAbs(a: 1.f - matrix.column1.y); |
| 447 | float z = PxAbs(a: 1.f - matrix.column2.z); |
| 448 | bool identity = ((x < eps) && PxAbs(a: matrix.column0.y - 0.f) < eps && PxAbs(a: matrix.column0.z - 0.f) < eps) && |
| 449 | (PxAbs(a: matrix.column1.x - 0.f) < eps && (y < eps) && PxAbs(a: matrix.column1.z - 0.f) < eps) && |
| 450 | (PxAbs(a: matrix.column2.x - 0.f) < eps && PxAbs(a: matrix.column2.y - 0.f) < eps && (z < eps)); |
| 451 | |
| 452 | return identity; |
| 453 | } |
| 454 | |
| 455 | PX_FORCE_INLINE bool isZero(const PxMat33& matrix) |
| 456 | { |
| 457 | PxReal eps = 0.0001f; |
| 458 | for (PxU32 i = 0; i < 3; ++i) |
| 459 | { |
| 460 | for (PxU32 j = 0; j < 3; ++j) |
| 461 | { |
| 462 | if (PxAbs(a: matrix[i][j]) > eps) |
| 463 | return false; |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | return true; |
| 468 | } |
| 469 | |
| 470 | PX_FORCE_INLINE bool isIdentity() |
| 471 | { |
| 472 | bool topLeftIsIdentity = isIdentity(matrix: topLeft); |
| 473 | |
| 474 | bool topRightIsZero = isZero(matrix: topRight); |
| 475 | |
| 476 | bool bottomLeftIsZero = isZero(matrix: bottomLeft); |
| 477 | |
| 478 | return topLeftIsIdentity && topRightIsZero && bottomLeftIsZero; |
| 479 | } |
| 480 | |
| 481 | static bool isEqual(const PxMat33& s0, const PxMat33& s1) |
| 482 | { |
| 483 | PxReal eps = 0.00001f; |
| 484 | for (PxU32 i = 0; i < 3; ++i) |
| 485 | { |
| 486 | for (PxU32 j = 0; j < 3; ++j) |
| 487 | { |
| 488 | PxReal t = s0[i][j] - s1[i][j]; |
| 489 | if (PxAbs(a: t) > eps) |
| 490 | return false; |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | return true; |
| 495 | } |
| 496 | |
| 497 | PX_FORCE_INLINE bool isEqual(const SpatialMatrix& s) |
| 498 | { |
| 499 | bool topLeftEqual = isEqual(s0: topLeft, s1: s.topLeft); |
| 500 | bool topRightEqual = isEqual(s0: topRight, s1: s.topRight); |
| 501 | bool bottomLeftEqual = isEqual(s0: bottomLeft, s1: s.bottomLeft); |
| 502 | |
| 503 | return topLeftEqual && topRightEqual && bottomLeftEqual; |
| 504 | } |
| 505 | |
| 506 | static PX_CUDA_CALLABLE PX_FORCE_INLINE PxMat33 invertSym33(const PxMat33& in) |
| 507 | { |
| 508 | PxVec3 v0 = in[1].cross(v: in[2]), |
| 509 | v1 = in[2].cross(v: in[0]), |
| 510 | v2 = in[0].cross(v: in[1]); |
| 511 | |
| 512 | PxReal det = v0.dot(v: in[0]); |
| 513 | |
| 514 | if (det != 0) |
| 515 | { |
| 516 | PxReal recipDet = 1.0f / det; |
| 517 | |
| 518 | return PxMat33(v0 * recipDet, |
| 519 | PxVec3(v0.y, v1.y, v1.z) * recipDet, |
| 520 | PxVec3(v0.z, v1.z, v2.z) * recipDet); |
| 521 | } |
| 522 | else |
| 523 | { |
| 524 | return PxMat33(PxIdentity); |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | static PX_FORCE_INLINE Ps::aos::Mat33V invertSym33(const Ps::aos::Mat33V& in) |
| 529 | { |
| 530 | using namespace Ps::aos; |
| 531 | const Vec3V v0 = V3Cross(a: in.col1, b: in.col2); |
| 532 | const Vec3V v1 = V3Cross(a: in.col2, b: in.col0); |
| 533 | const Vec3V v2 = V3Cross(a: in.col0, b: in.col1); |
| 534 | |
| 535 | FloatV det = V3Dot(a: v0, b: in.col0); |
| 536 | |
| 537 | const FloatV recipDet = FRecip(a: det); |
| 538 | |
| 539 | if (!FAllEq(a: det, b: FZero())) |
| 540 | { |
| 541 | return Mat33V(V3Scale(a: v0, b: recipDet), |
| 542 | V3Scale(a: V3Merge(x: V3GetY(f: v0), y: V3GetY(f: v1), z: V3GetZ(f: v1)), b: recipDet), |
| 543 | V3Scale(a: V3Merge(x: V3GetZ(f: v0), y: V3GetZ(f: v1), z: V3GetZ(f: v2)), b: recipDet)); |
| 544 | } |
| 545 | else |
| 546 | { |
| 547 | return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ()); |
| 548 | } |
| 549 | |
| 550 | //return M33Inverse(in); |
| 551 | } |
| 552 | |
| 553 | PX_CUDA_CALLABLE PX_FORCE_INLINE SpatialMatrix invertInertia() |
| 554 | { |
| 555 | PxMat33 aa = bottomLeft, ll = topRight, la = topLeft; |
| 556 | |
| 557 | aa = (aa + aa.getTranspose())*0.5f; |
| 558 | ll = (ll + ll.getTranspose())*0.5f; |
| 559 | |
| 560 | PxMat33 AAInv = invertSym33(in: aa); |
| 561 | |
| 562 | PxMat33 z = -la * AAInv; |
| 563 | PxMat33 S = ll + z * la.getTranspose(); // Schur complement of mAA |
| 564 | |
| 565 | PxMat33 LL = invertSym33(in: S); |
| 566 | |
| 567 | PxMat33 LA = LL * z; |
| 568 | PxMat33 AA = AAInv + z.getTranspose() * LA; |
| 569 | |
| 570 | SpatialMatrix result(LA.getTranspose(), AA, LL);// , LA); |
| 571 | |
| 572 | return result; |
| 573 | } |
| 574 | |
| 575 | PX_FORCE_INLINE void M33Store(const Ps::aos::Mat33V& src, PxMat33& dest) |
| 576 | { |
| 577 | Ps::aos::V3StoreU(a: src.col0, f&: dest.column0); |
| 578 | Ps::aos::V3StoreU(a: src.col1, f&: dest.column1); |
| 579 | Ps::aos::V3StoreU(a: src.col2, f&: dest.column2); |
| 580 | } |
| 581 | |
| 582 | PX_FORCE_INLINE void invertInertiaV(SpatialMatrix& result) |
| 583 | { |
| 584 | using namespace Ps::aos; |
| 585 | Mat33V aa = M33Load(m: bottomLeft), ll = M33Load(m: topRight), la = M33Load(m: topLeft); |
| 586 | |
| 587 | aa = M33Scale(a: M33Add(a: aa, b: M33Trnsps(a: aa)), b: FHalf()); |
| 588 | ll = M33Scale(a: M33Add(a: ll, b: M33Trnsps(a: ll)), b: FHalf()); |
| 589 | |
| 590 | Mat33V AAInv = invertSym33(in: aa); |
| 591 | |
| 592 | Mat33V z = M33MulM33(a: M33Neg(a: la), b: AAInv); |
| 593 | Mat33V S = M33Add(a: ll, b: M33MulM33(a: z, b: M33Trnsps(a: la))); // Schur complement of mAA |
| 594 | |
| 595 | Mat33V LL = invertSym33(in: S); |
| 596 | |
| 597 | Mat33V LA = M33MulM33(a: LL, b: z); |
| 598 | Mat33V AA = M33Add(a: AAInv, b: M33MulM33(a: M33Trnsps(a: z), b: LA)); |
| 599 | |
| 600 | M33Store(src: M33Trnsps(a: LA), dest&: result.topLeft); |
| 601 | M33Store(src: AA, dest&: result.topRight); |
| 602 | M33Store(src: LL, dest&: result.bottomLeft); |
| 603 | } |
| 604 | |
| 605 | SpatialMatrix getInverse() |
| 606 | { |
| 607 | PxMat33 bottomRight = topLeft.getTranspose(); |
| 608 | |
| 609 | PxMat33 blInverse = bottomLeft.getInverse(); |
| 610 | PxMat33 lComp0 = blInverse * (-bottomRight); |
| 611 | PxMat33 lComp1 = topLeft * lComp0 + topRight; |
| 612 | |
| 613 | //This can be simplified |
| 614 | PxMat33 newBottomLeft = lComp1.getInverse(); |
| 615 | PxMat33 newTopLeft = lComp0 * newBottomLeft; |
| 616 | |
| 617 | PxMat33 trInverse = topRight.getInverse(); |
| 618 | PxMat33 rComp0 = trInverse * (-topLeft); |
| 619 | PxMat33 rComp1 = bottomLeft + bottomRight * rComp0; |
| 620 | |
| 621 | PxMat33 newTopRight = rComp1.getInverse(); |
| 622 | |
| 623 | return SpatialMatrix(newTopLeft, newTopRight, newBottomLeft); |
| 624 | } |
| 625 | |
| 626 | void zero() |
| 627 | { |
| 628 | topLeft = PxMat33(PxZero); |
| 629 | topRight = PxMat33(PxZero); |
| 630 | bottomLeft = PxMat33(PxZero); |
| 631 | } |
| 632 | |
| 633 | }; |
| 634 | |
| 635 | struct SpatialImpulseResponseMatrix |
| 636 | { |
| 637 | Cm::SpatialVectorF rows[6]; |
| 638 | |
| 639 | Cm::SpatialVectorF getResponse(const Cm::SpatialVectorF& impulse) const |
| 640 | { |
| 641 | /*return rows[0] * impulse.top.x + rows[1] * impulse.top.y + rows[2] * impulse.top.z |
| 642 | + rows[3] * impulse.bottom.x + rows[4] * impulse.bottom.y + rows[5] * impulse.bottom.z;*/ |
| 643 | |
| 644 | using namespace Ps::aos; |
| 645 | Cm::SpatialVectorV row0(V3LoadA(f: &rows[0].top.x), V3LoadA(f: &rows[0].bottom.x)); |
| 646 | Cm::SpatialVectorV row1(V3LoadA(f: &rows[1].top.x), V3LoadA(f: &rows[1].bottom.x)); |
| 647 | Cm::SpatialVectorV row2(V3LoadA(f: &rows[2].top.x), V3LoadA(f: &rows[2].bottom.x)); |
| 648 | Cm::SpatialVectorV row3(V3LoadA(f: &rows[3].top.x), V3LoadA(f: &rows[3].bottom.x)); |
| 649 | Cm::SpatialVectorV row4(V3LoadA(f: &rows[4].top.x), V3LoadA(f: &rows[4].bottom.x)); |
| 650 | Cm::SpatialVectorV row5(V3LoadA(f: &rows[5].top.x), V3LoadA(f: &rows[5].bottom.x)); |
| 651 | |
| 652 | Vec4V top = V4LoadA(f: &impulse.top.x); |
| 653 | Vec4V bottom = V4LoadA(f: &impulse.bottom.x); |
| 654 | |
| 655 | const FloatV ix = V4GetX(f: top); |
| 656 | const FloatV iy = V4GetY(f: top); |
| 657 | const FloatV iz = V4GetZ(f: top); |
| 658 | const FloatV ia = V4GetX(f: bottom); |
| 659 | const FloatV ib = V4GetY(f: bottom); |
| 660 | const FloatV ic = V4GetZ(f: bottom); |
| 661 | |
| 662 | Cm::SpatialVectorV res = row0 * ix + row1 * iy + row2 * iz + row3 * ia + row4 * ib + row5 * ic; |
| 663 | |
| 664 | Cm::SpatialVectorF returnVal; |
| 665 | V4StoreA(a: Vec4V_From_Vec3V(f: res.linear), f: &returnVal.top.x); |
| 666 | V4StoreA(a: Vec4V_From_Vec3V(f: res.angular), f: &returnVal.bottom.x); |
| 667 | |
| 668 | return returnVal; |
| 669 | |
| 670 | } |
| 671 | |
| 672 | Cm::SpatialVectorV getResponse(const Cm::SpatialVectorV& impulse) const |
| 673 | { |
| 674 | using namespace Ps::aos; |
| 675 | Cm::SpatialVectorV row0(V3LoadA(f: &rows[0].top.x), V3LoadA(f: &rows[0].bottom.x)); |
| 676 | Cm::SpatialVectorV row1(V3LoadA(f: &rows[1].top.x), V3LoadA(f: &rows[1].bottom.x)); |
| 677 | Cm::SpatialVectorV row2(V3LoadA(f: &rows[2].top.x), V3LoadA(f: &rows[2].bottom.x)); |
| 678 | Cm::SpatialVectorV row3(V3LoadA(f: &rows[3].top.x), V3LoadA(f: &rows[3].bottom.x)); |
| 679 | Cm::SpatialVectorV row4(V3LoadA(f: &rows[4].top.x), V3LoadA(f: &rows[4].bottom.x)); |
| 680 | Cm::SpatialVectorV row5(V3LoadA(f: &rows[5].top.x), V3LoadA(f: &rows[5].bottom.x)); |
| 681 | |
| 682 | const Vec3V top = impulse.linear; |
| 683 | const Vec3V bottom = impulse.angular; |
| 684 | |
| 685 | const FloatV ix = V3GetX(f: top); |
| 686 | const FloatV iy = V3GetY(f: top); |
| 687 | const FloatV iz = V3GetZ(f: top); |
| 688 | const FloatV ia = V3GetX(f: bottom); |
| 689 | const FloatV ib = V3GetY(f: bottom); |
| 690 | const FloatV ic = V3GetZ(f: bottom); |
| 691 | |
| 692 | Cm::SpatialVectorV res = row0 * ix + row1 * iy + row2 * iz + row3 * ia + row4 * ib + row5 * ic; |
| 693 | return res; |
| 694 | } |
| 695 | }; |
| 696 | |
| 697 | struct Temp6x6Matrix; |
| 698 | |
| 699 | struct Temp6x3Matrix |
| 700 | { |
| 701 | PxReal column[3][6]; |
| 702 | public: |
| 703 | |
| 704 | Temp6x3Matrix() |
| 705 | { |
| 706 | |
| 707 | } |
| 708 | |
| 709 | Temp6x3Matrix(const Cm::SpatialVectorF* spatialAxis) |
| 710 | { |
| 711 | constructColumn(dest: column[0], v: spatialAxis[0]); |
| 712 | constructColumn(dest: column[1], v: spatialAxis[1]); |
| 713 | constructColumn(dest: column[2], v: spatialAxis[2]); |
| 714 | } |
| 715 | |
| 716 | void constructColumn(PxReal* dest, const Cm::SpatialVectorF& v) |
| 717 | { |
| 718 | dest[0] = v.top.x; |
| 719 | dest[1] = v.top.y; |
| 720 | dest[2] = v.top.z; |
| 721 | |
| 722 | dest[3] = v.bottom.x; |
| 723 | dest[4] = v.bottom.y; |
| 724 | dest[5] = v.bottom.z; |
| 725 | } |
| 726 | |
| 727 | Temp6x6Matrix operator * (PxReal s[6][3]); |
| 728 | |
| 729 | ////s is 3x6 matrix |
| 730 | //PX_FORCE_INLINE Temp6x6Matrix operator * (PxReal s[6][3]) |
| 731 | //{ |
| 732 | // Temp6x6Matrix temp; |
| 733 | |
| 734 | // for (PxU32 i = 0; i < 6; ++i) |
| 735 | // { |
| 736 | // PxReal* tc = temp.column[i]; |
| 737 | |
| 738 | // for (PxU32 j = 0; j < 6; ++j) |
| 739 | // { |
| 740 | // tc[j] = 0.f; |
| 741 | // for (PxU32 k = 0; k < 3; ++k) |
| 742 | // { |
| 743 | // tc[j] += column[k][j] * s[i][k]; |
| 744 | // } |
| 745 | // } |
| 746 | // } |
| 747 | |
| 748 | // return temp; |
| 749 | //} |
| 750 | |
| 751 | PX_FORCE_INLINE Temp6x3Matrix operator * (const PxMat33& s) |
| 752 | { |
| 753 | Temp6x3Matrix temp; |
| 754 | |
| 755 | for (PxU32 i = 0; i < 3; ++i) |
| 756 | { |
| 757 | PxReal* tc = temp.column[i]; |
| 758 | PxVec3 sc = s[i]; |
| 759 | |
| 760 | for (PxU32 j = 0; j < 6; ++j) |
| 761 | { |
| 762 | tc[j] = 0.f; |
| 763 | for (PxU32 k = 0; k < 3; ++k) |
| 764 | { |
| 765 | tc[j] += column[k][j] * sc[k]; |
| 766 | } |
| 767 | } |
| 768 | } |
| 769 | |
| 770 | return temp; |
| 771 | } |
| 772 | |
| 773 | PX_FORCE_INLINE bool isColumnEqual(const PxU32 ind, const Cm::SpatialVectorF& col) |
| 774 | { |
| 775 | PxReal temp[6]; |
| 776 | constructColumn(dest: temp, v: col); |
| 777 | const PxReal eps = 0.00001f; |
| 778 | for (PxU32 i = 0; i < 6; ++i) |
| 779 | { |
| 780 | const PxReal dif = column[ind][i] - temp[i]; |
| 781 | if (PxAbs(a: dif) > eps) |
| 782 | return false; |
| 783 | } |
| 784 | return true; |
| 785 | } |
| 786 | |
| 787 | }; |
| 788 | |
| 789 | |
| 790 | struct Temp6x6Matrix |
| 791 | { |
| 792 | PxReal column[6][6]; |
| 793 | public: |
| 794 | Temp6x6Matrix() |
| 795 | { |
| 796 | |
| 797 | } |
| 798 | |
| 799 | Temp6x6Matrix(const SpatialMatrix& spatialMatrix) |
| 800 | { |
| 801 | constructColumn(dest: column[0], top: spatialMatrix.topLeft.column0, bottom: spatialMatrix.bottomLeft.column0); |
| 802 | constructColumn(dest: column[1], top: spatialMatrix.topLeft.column1, bottom: spatialMatrix.bottomLeft.column1); |
| 803 | constructColumn(dest: column[2], top: spatialMatrix.topLeft.column2, bottom: spatialMatrix.bottomLeft.column2); |
| 804 | |
| 805 | const PxMat33 bottomRight = spatialMatrix.getBottomRight(); |
| 806 | constructColumn(dest: column[3], top: spatialMatrix.topRight.column0, bottom: bottomRight.column0); |
| 807 | constructColumn(dest: column[4], top: spatialMatrix.topRight.column1, bottom: bottomRight.column1); |
| 808 | constructColumn(dest: column[5], top: spatialMatrix.topRight.column2, bottom: bottomRight.column2); |
| 809 | } |
| 810 | |
| 811 | void constructColumn(const PxU32 ind, const PxReal* const values) |
| 812 | { |
| 813 | for (PxU32 i = 0; i < 6; ++i) |
| 814 | { |
| 815 | column[ind][i] = values[i]; |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | void constructColumn(PxReal* dest, const PxVec3& top, const PxVec3& bottom) |
| 820 | { |
| 821 | dest[0] = top.x; |
| 822 | dest[1] = top.y; |
| 823 | dest[2] = top.z; |
| 824 | |
| 825 | dest[3] = bottom.x; |
| 826 | dest[4] = bottom.y; |
| 827 | dest[5] = bottom.z; |
| 828 | } |
| 829 | |
| 830 | Temp6x6Matrix getTranspose() const |
| 831 | { |
| 832 | Temp6x6Matrix temp; |
| 833 | for (PxU32 i = 0; i < 6; ++i) |
| 834 | { |
| 835 | for (PxU32 j = 0; j < 6; ++j) |
| 836 | { |
| 837 | temp.column[i][j] = column[j][i]; |
| 838 | } |
| 839 | } |
| 840 | return temp; |
| 841 | } |
| 842 | |
| 843 | PX_FORCE_INLINE Cm::SpatialVector operator * (const Cm::SpatialVector& s) const |
| 844 | { |
| 845 | Temp6x6Matrix tempMatrix = getTranspose(); |
| 846 | PxReal st[6]; |
| 847 | st[0] = s.angular.x; st[1] = s.angular.y; st[2] = s.angular.z; |
| 848 | st[3] = s.linear.x; st[4] = s.linear.y; st[5] = s.linear.z; |
| 849 | |
| 850 | PxReal result[6]; |
| 851 | for (PxU32 i = 0; i < 6; i++) |
| 852 | { |
| 853 | result[i] = 0; |
| 854 | for (PxU32 j = 0; j < 6; ++j) |
| 855 | { |
| 856 | result[i] += tempMatrix.column[i][j] * st[j]; |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | |
| 861 | Cm::SpatialVector temp; |
| 862 | temp.angular.x = result[0]; temp.angular.y = result[1]; temp.angular.z = result[2]; |
| 863 | temp.linear.x = result[3]; temp.linear.y = result[4]; temp.linear.z = result[5]; |
| 864 | return temp; |
| 865 | } |
| 866 | |
| 867 | |
| 868 | PX_FORCE_INLINE Cm::SpatialVectorF operator * (const Cm::SpatialVectorF& s) const |
| 869 | { |
| 870 | PxReal st[6]; |
| 871 | st[0] = s.top.x; st[1] = s.top.y; st[2] = s.top.z; |
| 872 | st[3] = s.bottom.x; st[4] = s.bottom.y; st[5] = s.bottom.z; |
| 873 | |
| 874 | PxReal result[6]; |
| 875 | for (PxU32 i = 0; i < 6; ++i) |
| 876 | { |
| 877 | result[i] = 0.f; |
| 878 | for (PxU32 j = 0; j < 6; ++j) |
| 879 | { |
| 880 | result[i] += column[j][i] * st[j]; |
| 881 | } |
| 882 | } |
| 883 | |
| 884 | Cm::SpatialVectorF temp; |
| 885 | temp.top.x = result[0]; temp.top.y = result[1]; temp.top.z = result[2]; |
| 886 | temp.bottom.x = result[3]; temp.bottom.y = result[4]; temp.bottom.z = result[5]; |
| 887 | return temp; |
| 888 | } |
| 889 | |
| 890 | PX_FORCE_INLINE Temp6x3Matrix operator * (const Temp6x3Matrix& s) const |
| 891 | { |
| 892 | Temp6x3Matrix temp; |
| 893 | for (PxU32 i = 0; i < 3; ++i) |
| 894 | { |
| 895 | PxReal* result = temp.column[i]; |
| 896 | |
| 897 | const PxReal* input = s.column[i]; |
| 898 | |
| 899 | for (PxU32 j = 0; j < 6; ++j) |
| 900 | { |
| 901 | result[j] = 0.f; |
| 902 | for (PxU32 k = 0; k < 6; ++k) |
| 903 | { |
| 904 | result[j] += column[k][j] * input[k]; |
| 905 | } |
| 906 | } |
| 907 | } |
| 908 | |
| 909 | return temp; |
| 910 | |
| 911 | } |
| 912 | |
| 913 | PX_FORCE_INLINE Cm::SpatialVector spatialVectorMul(const Cm::SpatialVector& s) |
| 914 | { |
| 915 | PxReal st[6]; |
| 916 | st[0] = s.angular.x; st[1] = s.angular.y; st[2] = s.angular.z; |
| 917 | st[3] = s.linear.x; st[4] = s.linear.y; st[5] = s.linear.z; |
| 918 | |
| 919 | PxReal result[6]; |
| 920 | for (PxU32 i = 0; i < 6; ++i) |
| 921 | { |
| 922 | result[i] = 0.f; |
| 923 | for (PxU32 j = 0; j < 6; j++) |
| 924 | { |
| 925 | result[i] += column[i][j] * st[j]; |
| 926 | } |
| 927 | } |
| 928 | |
| 929 | Cm::SpatialVector temp; |
| 930 | temp.angular.x = result[0]; temp.angular.y = result[1]; temp.angular.z = result[2]; |
| 931 | temp.linear.x = result[3]; temp.linear.y = result[4]; temp.linear.z = result[5]; |
| 932 | return temp; |
| 933 | } |
| 934 | |
| 935 | PX_FORCE_INLINE bool isEqual(const Cm::SpatialVectorF* m) |
| 936 | { |
| 937 | PxReal temp[6]; |
| 938 | PxReal eps = 0.00001f; |
| 939 | for (PxU32 i = 0; i < 6; ++i) |
| 940 | { |
| 941 | temp[0] = m[i].top.x; temp[1] = m[i].top.y; temp[2] = m[i].top.z; |
| 942 | temp[3] = m[i].bottom.x; temp[4] = m[i].bottom.y; temp[5] = m[i].bottom.z; |
| 943 | |
| 944 | for (PxU32 j = 0; j < 6; ++j) |
| 945 | { |
| 946 | PxReal dif = column[i][j] - temp[j]; |
| 947 | if (PxAbs(a: dif) > eps) |
| 948 | return false; |
| 949 | } |
| 950 | } |
| 951 | |
| 952 | return true; |
| 953 | } |
| 954 | }; |
| 955 | |
| 956 | //s is 3x6 matrix |
| 957 | PX_FORCE_INLINE Temp6x6Matrix Temp6x3Matrix::operator * (PxReal s[6][3]) |
| 958 | { |
| 959 | Temp6x6Matrix temp; |
| 960 | |
| 961 | for (PxU32 i = 0; i < 6; ++i) |
| 962 | { |
| 963 | PxReal* tc = temp.column[i]; |
| 964 | |
| 965 | for (PxU32 j = 0; j < 6; ++j) |
| 966 | { |
| 967 | tc[j] = 0.f; |
| 968 | for (PxU32 k = 0; k < 3; ++k) |
| 969 | { |
| 970 | tc[j] += column[k][j] * s[i][k]; |
| 971 | } |
| 972 | } |
| 973 | } |
| 974 | |
| 975 | return temp; |
| 976 | } |
| 977 | |
| 978 | PX_FORCE_INLINE void calculateNewVelocity(const PxTransform& newTransform, const PxTransform& oldTransform, |
| 979 | const PxReal dt, PxVec3& linear, PxVec3& angular) |
| 980 | { |
| 981 | //calculate the new velocity |
| 982 | linear = (newTransform.p - oldTransform.p) / dt; |
| 983 | PxQuat quat = newTransform.q * oldTransform.q.getConjugate(); |
| 984 | |
| 985 | if (quat.w < 0) //shortest angle. |
| 986 | quat = -quat; |
| 987 | |
| 988 | PxReal angle; |
| 989 | PxVec3 axis; |
| 990 | quat.toRadiansAndUnitAxis(angle, axis); |
| 991 | angular = (axis * angle) / dt; |
| 992 | } |
| 993 | |
| 994 | |
| 995 | // generates a pair of quaternions (swing, twist) such that in = swing * twist, with |
| 996 | // swing.x = 0 |
| 997 | // twist.y = twist.z = 0, and twist is a unit quat |
| 998 | PX_CUDA_CALLABLE PX_FORCE_INLINE void separateSwingTwist(const PxQuat& q, PxQuat& twist, PxQuat& swing1, PxQuat& swing2) |
| 999 | { |
| 1000 | twist = q.x != 0.0f ? PxQuat(q.x, 0, 0, q.w).getNormalized() : PxQuat(PxIdentity); |
| 1001 | PxQuat swing = q * twist.getConjugate(); |
| 1002 | swing1 = swing.y != 0.f ? PxQuat(0.f, swing.y, 0.f, swing.w).getNormalized() : PxQuat(PxIdentity); |
| 1003 | swing = swing * swing1.getConjugate(); |
| 1004 | swing2 = swing.z != 0.f ? PxQuat(0.f, 0.f, swing.z, swing.w).getNormalized() : PxQuat(PxIdentity); |
| 1005 | } |
| 1006 | |
| 1007 | PX_CUDA_CALLABLE PX_FORCE_INLINE void separateSwingTwist2(const PxQuat& q, PxQuat& twist, PxQuat& swing1, PxQuat& swing2) |
| 1008 | { |
| 1009 | swing2 = q.z != 0.0f ? PxQuat(0.f, 0.f, q.z, q.w).getNormalized() : PxQuat(PxIdentity); |
| 1010 | PxQuat swing = q * swing2.getConjugate(); |
| 1011 | swing1 = swing.y != 0.f ? PxQuat(0.f, swing.y, 0.f, swing.w).getNormalized() : PxQuat(PxIdentity); |
| 1012 | swing = swing * swing1.getConjugate(); |
| 1013 | twist = swing.x != 0.f ? PxQuat(swing.x, 0.f, 0.f, swing.w).getNormalized() : PxQuat(PxIdentity); |
| 1014 | } |
| 1015 | |
| 1016 | |
| 1017 | } //namespace Dy |
| 1018 | |
| 1019 | } |
| 1020 | |
| 1021 | #endif |
| 1022 | |