00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BT_MATRIX3x3_H
00017 #define BT_MATRIX3x3_H
00018
00019 #include "btVector3.h"
00020 #include "btQuaternion.h"
00021
00022 #ifdef BT_USE_DOUBLE_PRECISION
00023 #define btMatrix3x3Data btMatrix3x3DoubleData
00024 #else
00025 #define btMatrix3x3Data btMatrix3x3FloatData
00026 #endif //BT_USE_DOUBLE_PRECISION
00027
00028
00031 class btMatrix3x3 {
00032
00034 btVector3 m_el[3];
00035
00036 public:
00038 btMatrix3x3 () {}
00039
00040
00041
00043 explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
00044
00045
00046
00047
00048
00049
00050
00052 btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
00053 const btScalar& yx, const btScalar& yy, const btScalar& yz,
00054 const btScalar& zx, const btScalar& zy, const btScalar& zz)
00055 {
00056 setValue(xx, xy, xz,
00057 yx, yy, yz,
00058 zx, zy, zz);
00059 }
00061 SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
00062 {
00063 m_el[0] = other.m_el[0];
00064 m_el[1] = other.m_el[1];
00065 m_el[2] = other.m_el[2];
00066 }
00068 SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
00069 {
00070 m_el[0] = other.m_el[0];
00071 m_el[1] = other.m_el[1];
00072 m_el[2] = other.m_el[2];
00073 return *this;
00074 }
00075
00078 SIMD_FORCE_INLINE btVector3 getColumn(int i) const
00079 {
00080 return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
00081 }
00082
00083
00086 SIMD_FORCE_INLINE const btVector3& getRow(int i) const
00087 {
00088 btFullAssert(0 <= i && i < 3);
00089 return m_el[i];
00090 }
00091
00094 SIMD_FORCE_INLINE btVector3& operator[](int i)
00095 {
00096 btFullAssert(0 <= i && i < 3);
00097 return m_el[i];
00098 }
00099
00102 SIMD_FORCE_INLINE const btVector3& operator[](int i) const
00103 {
00104 btFullAssert(0 <= i && i < 3);
00105 return m_el[i];
00106 }
00107
00111 btMatrix3x3& operator*=(const btMatrix3x3& m);
00112
00115 void setFromOpenGLSubMatrix(const btScalar *m)
00116 {
00117 m_el[0].setValue(m[0],m[4],m[8]);
00118 m_el[1].setValue(m[1],m[5],m[9]);
00119 m_el[2].setValue(m[2],m[6],m[10]);
00120
00121 }
00132 void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
00133 const btScalar& yx, const btScalar& yy, const btScalar& yz,
00134 const btScalar& zx, const btScalar& zy, const btScalar& zz)
00135 {
00136 m_el[0].setValue(xx,xy,xz);
00137 m_el[1].setValue(yx,yy,yz);
00138 m_el[2].setValue(zx,zy,zz);
00139 }
00140
00143 void setRotation(const btQuaternion& q)
00144 {
00145 btScalar d = q.length2();
00146 btFullAssert(d != btScalar(0.0));
00147 btScalar s = btScalar(2.0) / d;
00148 btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
00149 btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
00150 btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
00151 btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
00152 setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
00153 xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
00154 xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
00155 }
00156
00157
00163 void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
00164 {
00165 setEulerZYX(roll, pitch, yaw);
00166 }
00167
00177 void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) {
00179 btScalar ci ( btCos(eulerX));
00180 btScalar cj ( btCos(eulerY));
00181 btScalar ch ( btCos(eulerZ));
00182 btScalar si ( btSin(eulerX));
00183 btScalar sj ( btSin(eulerY));
00184 btScalar sh ( btSin(eulerZ));
00185 btScalar cc = ci * ch;
00186 btScalar cs = ci * sh;
00187 btScalar sc = si * ch;
00188 btScalar ss = si * sh;
00189
00190 setValue(cj * ch, sj * sc - cs, sj * cc + ss,
00191 cj * sh, sj * ss + cc, sj * cs - sc,
00192 -sj, cj * si, cj * ci);
00193 }
00194
00196 void setIdentity()
00197 {
00198 setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
00199 btScalar(0.0), btScalar(1.0), btScalar(0.0),
00200 btScalar(0.0), btScalar(0.0), btScalar(1.0));
00201 }
00202
00203 static const btMatrix3x3& getIdentity()
00204 {
00205 static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0),
00206 btScalar(0.0), btScalar(1.0), btScalar(0.0),
00207 btScalar(0.0), btScalar(0.0), btScalar(1.0));
00208 return identityMatrix;
00209 }
00210
00213 void getOpenGLSubMatrix(btScalar *m) const
00214 {
00215 m[0] = btScalar(m_el[0].x());
00216 m[1] = btScalar(m_el[1].x());
00217 m[2] = btScalar(m_el[2].x());
00218 m[3] = btScalar(0.0);
00219 m[4] = btScalar(m_el[0].y());
00220 m[5] = btScalar(m_el[1].y());
00221 m[6] = btScalar(m_el[2].y());
00222 m[7] = btScalar(0.0);
00223 m[8] = btScalar(m_el[0].z());
00224 m[9] = btScalar(m_el[1].z());
00225 m[10] = btScalar(m_el[2].z());
00226 m[11] = btScalar(0.0);
00227 }
00228
00231 void getRotation(btQuaternion& q) const
00232 {
00233 btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
00234 btScalar temp[4];
00235
00236 if (trace > btScalar(0.0))
00237 {
00238 btScalar s = btSqrt(trace + btScalar(1.0));
00239 temp[3]=(s * btScalar(0.5));
00240 s = btScalar(0.5) / s;
00241
00242 temp[0]=((m_el[2].y() - m_el[1].z()) * s);
00243 temp[1]=((m_el[0].z() - m_el[2].x()) * s);
00244 temp[2]=((m_el[1].x() - m_el[0].y()) * s);
00245 }
00246 else
00247 {
00248 int i = m_el[0].x() < m_el[1].y() ?
00249 (m_el[1].y() < m_el[2].z() ? 2 : 1) :
00250 (m_el[0].x() < m_el[2].z() ? 2 : 0);
00251 int j = (i + 1) % 3;
00252 int k = (i + 2) % 3;
00253
00254 btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
00255 temp[i] = s * btScalar(0.5);
00256 s = btScalar(0.5) / s;
00257
00258 temp[3] = (m_el[k][j] - m_el[j][k]) * s;
00259 temp[j] = (m_el[j][i] + m_el[i][j]) * s;
00260 temp[k] = (m_el[k][i] + m_el[i][k]) * s;
00261 }
00262 q.setValue(temp[0],temp[1],temp[2],temp[3]);
00263 }
00264
00269 void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
00270 {
00271
00272
00273 yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
00274 pitch = btScalar(btAsin(-m_el[2].x()));
00275 roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
00276
00277
00278 if (btFabs(pitch)==SIMD_HALF_PI)
00279 {
00280 if (yaw>0)
00281 yaw-=SIMD_PI;
00282 else
00283 yaw+=SIMD_PI;
00284
00285 if (roll>0)
00286 roll-=SIMD_PI;
00287 else
00288 roll+=SIMD_PI;
00289 }
00290 };
00291
00292
00298 void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
00299 {
00300 struct Euler
00301 {
00302 btScalar yaw;
00303 btScalar pitch;
00304 btScalar roll;
00305 };
00306
00307 Euler euler_out;
00308 Euler euler_out2;
00309
00310
00311
00312 if (btFabs(m_el[2].x()) >= 1)
00313 {
00314 euler_out.yaw = 0;
00315 euler_out2.yaw = 0;
00316
00317
00318 btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
00319 if (m_el[2].x() > 0)
00320 {
00321 euler_out.pitch = SIMD_PI / btScalar(2.0);
00322 euler_out2.pitch = SIMD_PI / btScalar(2.0);
00323 euler_out.roll = euler_out.pitch + delta;
00324 euler_out2.roll = euler_out.pitch + delta;
00325 }
00326 else
00327 {
00328 euler_out.pitch = -SIMD_PI / btScalar(2.0);
00329 euler_out2.pitch = -SIMD_PI / btScalar(2.0);
00330 euler_out.roll = -euler_out.pitch + delta;
00331 euler_out2.roll = -euler_out.pitch + delta;
00332 }
00333 }
00334 else
00335 {
00336 euler_out.pitch = - btAsin(m_el[2].x());
00337 euler_out2.pitch = SIMD_PI - euler_out.pitch;
00338
00339 euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch),
00340 m_el[2].z()/btCos(euler_out.pitch));
00341 euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch),
00342 m_el[2].z()/btCos(euler_out2.pitch));
00343
00344 euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch),
00345 m_el[0].x()/btCos(euler_out.pitch));
00346 euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch),
00347 m_el[0].x()/btCos(euler_out2.pitch));
00348 }
00349
00350 if (solution_number == 1)
00351 {
00352 yaw = euler_out.yaw;
00353 pitch = euler_out.pitch;
00354 roll = euler_out.roll;
00355 }
00356 else
00357 {
00358 yaw = euler_out2.yaw;
00359 pitch = euler_out2.pitch;
00360 roll = euler_out2.roll;
00361 }
00362 }
00363
00367 btMatrix3x3 scaled(const btVector3& s) const
00368 {
00369 return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
00370 m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
00371 m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
00372 }
00373
00375 btScalar determinant() const;
00377 btMatrix3x3 adjoint() const;
00379 btMatrix3x3 absolute() const;
00381 btMatrix3x3 transpose() const;
00383 btMatrix3x3 inverse() const;
00384
00385 btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
00386 btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
00387
00388 SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
00389 {
00390 return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
00391 }
00392 SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
00393 {
00394 return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
00395 }
00396 SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
00397 {
00398 return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
00399 }
00400
00401
00411 void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps)
00412 {
00413 rot.setIdentity();
00414 for (int step = maxSteps; step > 0; step--)
00415 {
00416
00417 int p = 0;
00418 int q = 1;
00419 int r = 2;
00420 btScalar max = btFabs(m_el[0][1]);
00421 btScalar v = btFabs(m_el[0][2]);
00422 if (v > max)
00423 {
00424 q = 2;
00425 r = 1;
00426 max = v;
00427 }
00428 v = btFabs(m_el[1][2]);
00429 if (v > max)
00430 {
00431 p = 1;
00432 q = 2;
00433 r = 0;
00434 max = v;
00435 }
00436
00437 btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
00438 if (max <= t)
00439 {
00440 if (max <= SIMD_EPSILON * t)
00441 {
00442 return;
00443 }
00444 step = 1;
00445 }
00446
00447
00448 btScalar mpq = m_el[p][q];
00449 btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
00450 btScalar theta2 = theta * theta;
00451 btScalar cos;
00452 btScalar sin;
00453 if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
00454 {
00455 t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
00456 : 1 / (theta - btSqrt(1 + theta2));
00457 cos = 1 / btSqrt(1 + t * t);
00458 sin = cos * t;
00459 }
00460 else
00461 {
00462
00463 t = 1 / (theta * (2 + btScalar(0.5) / theta2));
00464 cos = 1 - btScalar(0.5) * t * t;
00465 sin = cos * t;
00466 }
00467
00468
00469 m_el[p][q] = m_el[q][p] = 0;
00470 m_el[p][p] -= t * mpq;
00471 m_el[q][q] += t * mpq;
00472 btScalar mrp = m_el[r][p];
00473 btScalar mrq = m_el[r][q];
00474 m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
00475 m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
00476
00477
00478 for (int i = 0; i < 3; i++)
00479 {
00480 btVector3& row = rot[i];
00481 mrp = row[p];
00482 mrq = row[q];
00483 row[p] = cos * mrp - sin * mrq;
00484 row[q] = cos * mrq + sin * mrp;
00485 }
00486 }
00487 }
00488
00489
00490
00491
00499 btScalar cofac(int r1, int c1, int r2, int c2) const
00500 {
00501 return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
00502 }
00503
00504 void serialize(struct btMatrix3x3Data& dataOut) const;
00505
00506 void serializeFloat(struct btMatrix3x3FloatData& dataOut) const;
00507
00508 void deSerialize(const struct btMatrix3x3Data& dataIn);
00509
00510 void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
00511
00512 void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
00513
00514 };
00515
00516
00517 SIMD_FORCE_INLINE btMatrix3x3&
00518 btMatrix3x3::operator*=(const btMatrix3x3& m)
00519 {
00520 setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
00521 m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
00522 m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
00523 return *this;
00524 }
00525
00526 SIMD_FORCE_INLINE btScalar
00527 btMatrix3x3::determinant() const
00528 {
00529 return btTriple((*this)[0], (*this)[1], (*this)[2]);
00530 }
00531
00532
00533 SIMD_FORCE_INLINE btMatrix3x3
00534 btMatrix3x3::absolute() const
00535 {
00536 return btMatrix3x3(
00537 btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
00538 btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
00539 btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
00540 }
00541
00542 SIMD_FORCE_INLINE btMatrix3x3
00543 btMatrix3x3::transpose() const
00544 {
00545 return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
00546 m_el[0].y(), m_el[1].y(), m_el[2].y(),
00547 m_el[0].z(), m_el[1].z(), m_el[2].z());
00548 }
00549
00550 SIMD_FORCE_INLINE btMatrix3x3
00551 btMatrix3x3::adjoint() const
00552 {
00553 return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
00554 cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
00555 cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
00556 }
00557
00558 SIMD_FORCE_INLINE btMatrix3x3
00559 btMatrix3x3::inverse() const
00560 {
00561 btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
00562 btScalar det = (*this)[0].dot(co);
00563 btFullAssert(det != btScalar(0.0));
00564 btScalar s = btScalar(1.0) / det;
00565 return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
00566 co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
00567 co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
00568 }
00569
00570 SIMD_FORCE_INLINE btMatrix3x3
00571 btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
00572 {
00573 return btMatrix3x3(
00574 m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
00575 m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
00576 m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
00577 m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
00578 m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
00579 m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
00580 m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
00581 m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
00582 m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
00583 }
00584
00585 SIMD_FORCE_INLINE btMatrix3x3
00586 btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
00587 {
00588 return btMatrix3x3(
00589 m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
00590 m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
00591 m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
00592
00593 }
00594
00595 SIMD_FORCE_INLINE btVector3
00596 operator*(const btMatrix3x3& m, const btVector3& v)
00597 {
00598 return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
00599 }
00600
00601
00602 SIMD_FORCE_INLINE btVector3
00603 operator*(const btVector3& v, const btMatrix3x3& m)
00604 {
00605 return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
00606 }
00607
00608 SIMD_FORCE_INLINE btMatrix3x3
00609 operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
00610 {
00611 return btMatrix3x3(
00612 m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
00613 m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
00614 m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00634 SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
00635 {
00636 return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
00637 m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
00638 m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
00639 }
00640
00642 struct btMatrix3x3FloatData
00643 {
00644 btVector3FloatData m_el[3];
00645 };
00646
00648 struct btMatrix3x3DoubleData
00649 {
00650 btVector3DoubleData m_el[3];
00651 };
00652
00653
00654
00655
00656 SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
00657 {
00658 for (int i=0;i<3;i++)
00659 m_el[i].serialize(dataOut.m_el[i]);
00660 }
00661
00662 SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
00663 {
00664 for (int i=0;i<3;i++)
00665 m_el[i].serializeFloat(dataOut.m_el[i]);
00666 }
00667
00668
00669 SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
00670 {
00671 for (int i=0;i<3;i++)
00672 m_el[i].deSerialize(dataIn.m_el[i]);
00673 }
00674
00675 SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
00676 {
00677 for (int i=0;i<3;i++)
00678 m_el[i].deSerializeFloat(dataIn.m_el[i]);
00679 }
00680
00681 SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
00682 {
00683 for (int i=0;i<3;i++)
00684 m_el[i].deSerializeDouble(dataIn.m_el[i]);
00685 }
00686
00687 #endif //BT_MATRIX3x3_H
00688