File indexing completed on 2025-06-01 03:50:40
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #ifndef B2_MATH_H 0020 #define B2_MATH_H 0021 0022 #include <Box2D/Common/b2Settings.h> 0023 0024 #include <cmath> 0025 #include <cfloat> 0026 #include <cstddef> 0027 #include <limits> 0028 0029 /// This function is used to ensure that a floating point number is 0030 /// not a NaN or infinity. 0031 inline bool b2IsValid(qreal x) 0032 { 0033 if (x != x) 0034 { 0035 // NaN. 0036 return false; 0037 } 0038 0039 qreal infinity = std::numeric_limits<qreal>::infinity(); 0040 return -infinity < x && x < infinity; 0041 } 0042 0043 template<size_t size> struct b2InvSqrt_magic; 0044 template<> struct b2InvSqrt_magic<4> { static inline int32_t value() { return 0x5f3759df; } }; 0045 template<> struct b2InvSqrt_magic<8> { static inline int64_t value() { return 0x5fe6eb50c7aa19f9ULL; } }; 0046 0047 /// This is a approximate yet fast inverse square-root. 0048 inline qreal b2InvSqrt(qreal x) 0049 { 0050 union 0051 { 0052 qreal x; 0053 int32 i; 0054 } convert; 0055 0056 convert.x = x; 0057 qreal xhalf = 0.5f * x; 0058 convert.i = b2InvSqrt_magic<sizeof(qreal)>::value() - (convert.i >> 1); 0059 x = convert.x; 0060 x = x * (1.5f - xhalf * x * x); 0061 return x; 0062 } 0063 0064 #define b2Sqrt(x) std::sqrt(x) 0065 #define b2Atan2(y, x) std::atan2(y, x) 0066 0067 inline qreal b2Abs(qreal a) 0068 { 0069 return a > 0.0f ? a : -a; 0070 } 0071 0072 /// A 2D column vector. 0073 struct b2Vec2 0074 { 0075 /// Default constructor does nothing (for performance). 0076 b2Vec2() {} 0077 0078 /// Construct using coordinates. 0079 b2Vec2(qreal x, qreal y) : x(x), y(y) {} 0080 0081 /// Set this vector to all zeros. 0082 void SetZero() { x = 0.0f; y = 0.0f; } 0083 0084 /// Set this vector to some specified coordinates. 0085 void Set(qreal x_, qreal y_) { x = x_; y = y_; } 0086 0087 /// Negate this vector. 0088 b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } 0089 0090 /// Read from and indexed element. 0091 qreal operator () (int32 i) const 0092 { 0093 return (&x)[i]; 0094 } 0095 0096 /// Write to an indexed element. 0097 qreal& operator () (int32 i) 0098 { 0099 return (&x)[i]; 0100 } 0101 0102 /// Add a vector to this vector. 0103 void operator += (const b2Vec2& v) 0104 { 0105 x += v.x; y += v.y; 0106 } 0107 0108 /// Subtract a vector from this vector. 0109 void operator -= (const b2Vec2& v) 0110 { 0111 x -= v.x; y -= v.y; 0112 } 0113 0114 /// Multiply this vector by a scalar. 0115 void operator *= (qreal a) 0116 { 0117 x *= a; y *= a; 0118 } 0119 0120 /// Get the length of this vector (the norm). 0121 qreal Length() const 0122 { 0123 return b2Sqrt(x * x + y * y); 0124 } 0125 0126 /// Get the length squared. For performance, use this instead of 0127 /// b2Vec2::Length (if possible). 0128 qreal LengthSquared() const 0129 { 0130 return x * x + y * y; 0131 } 0132 0133 /// Convert this vector into a unit vector. Returns the length. 0134 qreal Normalize() 0135 { 0136 qreal length = Length(); 0137 if (length < b2_epsilon) 0138 { 0139 return 0.0f; 0140 } 0141 qreal invLength = 1.0f / length; 0142 x *= invLength; 0143 y *= invLength; 0144 0145 return length; 0146 } 0147 0148 /// Does this vector contain finite coordinates? 0149 bool IsValid() const 0150 { 0151 return b2IsValid(x) && b2IsValid(y); 0152 } 0153 0154 qreal x, y; 0155 }; 0156 0157 /// A 2D column vector with 3 elements. 0158 struct b2Vec3 0159 { 0160 /// Default constructor does nothing (for performance). 0161 b2Vec3() {} 0162 0163 /// Construct using coordinates. 0164 b2Vec3(qreal x, qreal y, qreal z) : x(x), y(y), z(z) {} 0165 0166 /// Set this vector to all zeros. 0167 void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; } 0168 0169 /// Set this vector to some specified coordinates. 0170 void Set(qreal x_, qreal y_, qreal z_) { x = x_; y = y_; z = z_; } 0171 0172 /// Negate this vector. 0173 b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; } 0174 0175 /// Add a vector to this vector. 0176 void operator += (const b2Vec3& v) 0177 { 0178 x += v.x; y += v.y; z += v.z; 0179 } 0180 0181 /// Subtract a vector from this vector. 0182 void operator -= (const b2Vec3& v) 0183 { 0184 x -= v.x; y -= v.y; z -= v.z; 0185 } 0186 0187 /// Multiply this vector by a scalar. 0188 void operator *= (qreal s) 0189 { 0190 x *= s; y *= s; z *= s; 0191 } 0192 0193 qreal x, y, z; 0194 }; 0195 0196 /// A 2-by-2 matrix. Stored in column-major order. 0197 struct b2Mat22 0198 { 0199 /// The default constructor does nothing (for performance). 0200 b2Mat22() {} 0201 0202 /// Construct this matrix using columns. 0203 b2Mat22(const b2Vec2& c1, const b2Vec2& c2) 0204 { 0205 col1 = c1; 0206 col2 = c2; 0207 } 0208 0209 /// Construct this matrix using scalars. 0210 b2Mat22(qreal a11, qreal a12, qreal a21, qreal a22) 0211 { 0212 col1.x = a11; col1.y = a21; 0213 col2.x = a12; col2.y = a22; 0214 } 0215 0216 /// Construct this matrix using an angle. This matrix becomes 0217 /// an orthonormal rotation matrix. 0218 explicit b2Mat22(qreal angle) 0219 { 0220 // TODO_ERIN compute sin+cos together. 0221 qreal c = cosf(angle), s = sinf(angle); 0222 col1.x = c; col2.x = -s; 0223 col1.y = s; col2.y = c; 0224 } 0225 0226 /// Initialize this matrix using columns. 0227 void Set(const b2Vec2& c1, const b2Vec2& c2) 0228 { 0229 col1 = c1; 0230 col2 = c2; 0231 } 0232 0233 /// Initialize this matrix using an angle. This matrix becomes 0234 /// an orthonormal rotation matrix. 0235 void Set(qreal angle) 0236 { 0237 qreal c = cosf(angle), s = sinf(angle); 0238 col1.x = c; col2.x = -s; 0239 col1.y = s; col2.y = c; 0240 } 0241 0242 /// Set this to the identity matrix. 0243 void SetIdentity() 0244 { 0245 col1.x = 1.0f; col2.x = 0.0f; 0246 col1.y = 0.0f; col2.y = 1.0f; 0247 } 0248 0249 /// Set this matrix to all zeros. 0250 void SetZero() 0251 { 0252 col1.x = 0.0f; col2.x = 0.0f; 0253 col1.y = 0.0f; col2.y = 0.0f; 0254 } 0255 0256 /// Extract the angle from this matrix (assumed to be 0257 /// a rotation matrix). 0258 qreal GetAngle() const 0259 { 0260 return b2Atan2(col1.y, col1.x); 0261 } 0262 0263 b2Mat22 GetInverse() const 0264 { 0265 qreal a = col1.x, b = col2.x, c = col1.y, d = col2.y; 0266 b2Mat22 B; 0267 qreal det = a * d - b * c; 0268 if (det != 0.0f) 0269 { 0270 det = 1.0f / det; 0271 } 0272 B.col1.x = det * d; B.col2.x = -det * b; 0273 B.col1.y = -det * c; B.col2.y = det * a; 0274 return B; 0275 } 0276 0277 /// Solve A * x = b, where b is a column vector. This is more efficient 0278 /// than computing the inverse in one-shot cases. 0279 b2Vec2 Solve(const b2Vec2& b) const 0280 { 0281 qreal a11 = col1.x, a12 = col2.x, a21 = col1.y, a22 = col2.y; 0282 qreal det = a11 * a22 - a12 * a21; 0283 if (det != 0.0f) 0284 { 0285 det = 1.0f / det; 0286 } 0287 b2Vec2 x; 0288 x.x = det * (a22 * b.x - a12 * b.y); 0289 x.y = det * (a11 * b.y - a21 * b.x); 0290 return x; 0291 } 0292 0293 b2Vec2 col1, col2; 0294 }; 0295 0296 /// A 3-by-3 matrix. Stored in column-major order. 0297 struct b2Mat33 0298 { 0299 /// The default constructor does nothing (for performance). 0300 b2Mat33() {} 0301 0302 /// Construct this matrix using columns. 0303 b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3) 0304 { 0305 col1 = c1; 0306 col2 = c2; 0307 col3 = c3; 0308 } 0309 0310 /// Set this matrix to all zeros. 0311 void SetZero() 0312 { 0313 col1.SetZero(); 0314 col2.SetZero(); 0315 col3.SetZero(); 0316 } 0317 0318 /// Solve A * x = b, where b is a column vector. This is more efficient 0319 /// than computing the inverse in one-shot cases. 0320 b2Vec3 Solve33(const b2Vec3& b) const; 0321 0322 /// Solve A * x = b, where b is a column vector. This is more efficient 0323 /// than computing the inverse in one-shot cases. Solve only the upper 0324 /// 2-by-2 matrix equation. 0325 b2Vec2 Solve22(const b2Vec2& b) const; 0326 0327 b2Vec3 col1, col2, col3; 0328 }; 0329 0330 /// A transform contains translation and rotation. It is used to represent 0331 /// the position and orientation of rigid frames. 0332 struct b2Transform 0333 { 0334 /// The default constructor does nothing (for performance). 0335 b2Transform() {} 0336 0337 /// Initialize using a position vector and a rotation matrix. 0338 b2Transform(const b2Vec2& position, const b2Mat22& R) : position(position), R(R) {} 0339 0340 /// Set this to the identity transform. 0341 void SetIdentity() 0342 { 0343 position.SetZero(); 0344 R.SetIdentity(); 0345 } 0346 0347 /// Set this based on the position and angle. 0348 void Set(const b2Vec2& p, qreal angle) 0349 { 0350 position = p; 0351 R.Set(angle); 0352 } 0353 0354 /// Calculate the angle that the rotation matrix represents. 0355 qreal GetAngle() const 0356 { 0357 return b2Atan2(R.col1.y, R.col1.x); 0358 } 0359 0360 b2Vec2 position; 0361 b2Mat22 R; 0362 }; 0363 0364 /// This describes the motion of a body/shape for TOI computation. 0365 /// Shapes are defined with respect to the body origin, which may 0366 /// no coincide with the center of mass. However, to support dynamics 0367 /// we must interpolate the center of mass position. 0368 struct b2Sweep 0369 { 0370 /// Get the interpolated transform at a specific time. 0371 /// @param beta is a factor in [0,1], where 0 indicates alpha0. 0372 void GetTransform(b2Transform* xf, qreal beta) const; 0373 0374 /// Advance the sweep forward, yielding a new initial state. 0375 /// @param alpha the new initial time. 0376 void Advance(qreal alpha); 0377 0378 /// Normalize the angles. 0379 void Normalize(); 0380 0381 b2Vec2 localCenter; ///< local center of mass position 0382 b2Vec2 c0, c; ///< center world positions 0383 qreal a0, a; ///< world angles 0384 0385 /// Fraction of the current time step in the range [0,1] 0386 /// c0 and a0 are the positions at alpha0. 0387 qreal alpha0; 0388 }; 0389 0390 0391 extern const b2Vec2 b2Vec2_zero; 0392 extern const b2Mat22 b2Mat22_identity; 0393 extern const b2Transform b2Transform_identity; 0394 0395 /// Perform the dot product on two vectors. 0396 inline qreal b2Dot(const b2Vec2& a, const b2Vec2& b) 0397 { 0398 return a.x * b.x + a.y * b.y; 0399 } 0400 0401 /// Perform the cross product on two vectors. In 2D this produces a scalar. 0402 inline qreal b2Cross(const b2Vec2& a, const b2Vec2& b) 0403 { 0404 return a.x * b.y - a.y * b.x; 0405 } 0406 0407 /// Perform the cross product on a vector and a scalar. In 2D this produces 0408 /// a vector. 0409 inline b2Vec2 b2Cross(const b2Vec2& a, qreal s) 0410 { 0411 return b2Vec2(s * a.y, -s * a.x); 0412 } 0413 0414 /// Perform the cross product on a scalar and a vector. In 2D this produces 0415 /// a vector. 0416 inline b2Vec2 b2Cross(qreal s, const b2Vec2& a) 0417 { 0418 return b2Vec2(-s * a.y, s * a.x); 0419 } 0420 0421 /// Multiply a matrix times a vector. If a rotation matrix is provided, 0422 /// then this transforms the vector from one frame to another. 0423 inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v) 0424 { 0425 return b2Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y); 0426 } 0427 0428 /// Multiply a matrix transpose times a vector. If a rotation matrix is provided, 0429 /// then this transforms the vector from one frame to another (inverse transform). 0430 inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v) 0431 { 0432 return b2Vec2(b2Dot(v, A.col1), b2Dot(v, A.col2)); 0433 } 0434 0435 /// Add two vectors component-wise. 0436 inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b) 0437 { 0438 return b2Vec2(a.x + b.x, a.y + b.y); 0439 } 0440 0441 /// Subtract two vectors component-wise. 0442 inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b) 0443 { 0444 return b2Vec2(a.x - b.x, a.y - b.y); 0445 } 0446 0447 inline b2Vec2 operator * (qreal s, const b2Vec2& a) 0448 { 0449 return b2Vec2(s * a.x, s * a.y); 0450 } 0451 0452 inline bool operator == (const b2Vec2& a, const b2Vec2& b) 0453 { 0454 return a.x == b.x && a.y == b.y; 0455 } 0456 0457 inline qreal b2Distance(const b2Vec2& a, const b2Vec2& b) 0458 { 0459 b2Vec2 c = a - b; 0460 return c.Length(); 0461 } 0462 0463 inline qreal b2DistanceSquared(const b2Vec2& a, const b2Vec2& b) 0464 { 0465 b2Vec2 c = a - b; 0466 return b2Dot(c, c); 0467 } 0468 0469 inline b2Vec3 operator * (qreal s, const b2Vec3& a) 0470 { 0471 return b2Vec3(s * a.x, s * a.y, s * a.z); 0472 } 0473 0474 /// Add two vectors component-wise. 0475 inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b) 0476 { 0477 return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z); 0478 } 0479 0480 /// Subtract two vectors component-wise. 0481 inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b) 0482 { 0483 return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z); 0484 } 0485 0486 /// Perform the dot product on two vectors. 0487 inline qreal b2Dot(const b2Vec3& a, const b2Vec3& b) 0488 { 0489 return a.x * b.x + a.y * b.y + a.z * b.z; 0490 } 0491 0492 /// Perform the cross product on two vectors. 0493 inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b) 0494 { 0495 return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); 0496 } 0497 0498 inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B) 0499 { 0500 return b2Mat22(A.col1 + B.col1, A.col2 + B.col2); 0501 } 0502 0503 // A * B 0504 inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B) 0505 { 0506 return b2Mat22(b2Mul(A, B.col1), b2Mul(A, B.col2)); 0507 } 0508 0509 // A^T * B 0510 inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B) 0511 { 0512 b2Vec2 c1(b2Dot(A.col1, B.col1), b2Dot(A.col2, B.col1)); 0513 b2Vec2 c2(b2Dot(A.col1, B.col2), b2Dot(A.col2, B.col2)); 0514 return b2Mat22(c1, c2); 0515 } 0516 0517 /// Multiply a matrix times a vector. 0518 inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v) 0519 { 0520 return v.x * A.col1 + v.y * A.col2 + v.z * A.col3; 0521 } 0522 0523 inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v) 0524 { 0525 qreal x = T.position.x + T.R.col1.x * v.x + T.R.col2.x * v.y; 0526 qreal y = T.position.y + T.R.col1.y * v.x + T.R.col2.y * v.y; 0527 0528 return b2Vec2(x, y); 0529 } 0530 0531 inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v) 0532 { 0533 return b2MulT(T.R, v - T.position); 0534 } 0535 0536 // v2 = A.R' * (B.R * v1 + B.p - A.p) = (A.R' * B.R) * v1 + (B.p - A.p) 0537 inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B) 0538 { 0539 b2Transform C; 0540 C.R = b2MulT(A.R, B.R); 0541 C.position = B.position - A.position; 0542 return C; 0543 } 0544 0545 inline b2Vec2 b2Abs(const b2Vec2& a) 0546 { 0547 return b2Vec2(b2Abs(a.x), b2Abs(a.y)); 0548 } 0549 0550 inline b2Mat22 b2Abs(const b2Mat22& A) 0551 { 0552 return b2Mat22(b2Abs(A.col1), b2Abs(A.col2)); 0553 } 0554 0555 template <typename T> 0556 inline T b2Min(T a, T b) 0557 { 0558 return a < b ? a : b; 0559 } 0560 0561 inline qreal b2Min(qreal a, qreal b) 0562 { 0563 return a < b ? a : b; 0564 } 0565 0566 inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b) 0567 { 0568 return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)); 0569 } 0570 0571 template <typename T> 0572 inline T b2Max(T a, T b) 0573 { 0574 return a > b ? a : b; 0575 } 0576 0577 inline qreal b2Max(qreal a, qreal b) 0578 { 0579 return a > b ? a : b; 0580 } 0581 0582 inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b) 0583 { 0584 return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)); 0585 } 0586 0587 template <typename T> 0588 inline T b2Clamp(T a, T low, T high) 0589 { 0590 return b2Max(low, b2Min(a, high)); 0591 } 0592 0593 inline qreal b2Clamp(qreal a, qreal low, qreal high) 0594 { 0595 return b2Max(low, b2Min(a, high)); 0596 } 0597 0598 inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high) 0599 { 0600 return b2Max(low, b2Min(a, high)); 0601 } 0602 0603 template<typename T> inline void b2Swap(T& a, T& b) 0604 { 0605 T tmp = a; 0606 a = b; 0607 b = tmp; 0608 } 0609 0610 /// "Next Largest Power of 2 0611 /// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm 0612 /// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with 0613 /// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next 0614 /// largest power of 2. For a 32-bit value:" 0615 inline uint32 b2NextPowerOfTwo(uint32 x) 0616 { 0617 x |= (x >> 1); 0618 x |= (x >> 2); 0619 x |= (x >> 4); 0620 x |= (x >> 8); 0621 x |= (x >> 16); 0622 return x + 1; 0623 } 0624 0625 inline bool b2IsPowerOfTwo(uint32 x) 0626 { 0627 bool result = x > 0 && (x & (x - 1)) == 0; 0628 return result; 0629 } 0630 0631 inline void b2Sweep::GetTransform(b2Transform* xf, qreal beta) const 0632 { 0633 xf->position = (1.0f - beta) * c0 + beta * c; 0634 qreal angle = (1.0f - beta) * a0 + beta * a; 0635 xf->R.Set(angle); 0636 0637 // Shift to origin 0638 xf->position -= b2Mul(xf->R, localCenter); 0639 } 0640 0641 inline void b2Sweep::Advance(qreal alpha) 0642 { 0643 b2Assert(alpha0 < 1.0f); 0644 qreal beta = (alpha - alpha0) / (1.0f - alpha0); 0645 c0 = (1.0f - beta) * c0 + beta * c; 0646 a0 = (1.0f - beta) * a0 + beta * a; 0647 alpha0 = alpha; 0648 } 0649 0650 /// Normalize an angle in radians to be between -pi and pi 0651 inline void b2Sweep::Normalize() 0652 { 0653 qreal twoPi = 2.0f * b2_pi; 0654 qreal d = twoPi * floorf(a0 / twoPi); 0655 a0 -= d; 0656 a -= d; 0657 } 0658 0659 #endif