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