1 /* 2 * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 3 * 4 * This software is provided 'as-is', without any express or implied 5 * warranty. In no event will the authors be held liable for any damages 6 * arising from the use of this software. 7 * Permission is granted to anyone to use this software for any purpose, 8 * including commercial applications, and to alter it and redistribute it 9 * freely, subject to the following restrictions: 10 * 1. The origin of this software must not be misrepresented; you must not 11 * claim that you wrote the original software. If you use this software 12 * in a product, an acknowledgment in the product documentation would be 13 * appreciated but is not required. 14 * 2. Altered source versions must be plainly marked as such, and must not be 15 * misrepresented as being the original software. 16 * 3. This notice may not be removed or altered from any source distribution. 17 */ 18 19 #ifndef B2_MATH_H 20 #define B2_MATH_H 21 22 #include <Box2D/Common/b2Settings.h> 23 24 #include <cmath> 25 #include <cfloat> 26 #include <cstddef> 27 #include <float.h> 28 29 /// This function is used to ensure that a floating point number is 30 inline bool b2IsValid(float32 x) 31 { 32 int32 ix = *reinterpret_cast<int32*>(&x); 33 return (ix & 0x7f800000) != 0x7f800000; 34 } 35 36 /// This is a approximate yet fast inverse square-root. 37 inline float32 b2InvSqrt(float32 x) 38 { 39 union 40 { 41 float32 x; 42 int32 i; 43 } convert; 44 45 convert.x = x; 46 float32 xhalf = 0.5f * x; 47 convert.i = 0x5f3759df - (convert.i >> 1); 48 x = convert.x; 49 x = x * (1.5f - xhalf * x * x); 50 return x; 51 } 52 53 #define b2Sqrt(x) std::sqrt(x) 54 #define b2Atan2(y, x) std::atan2(y, x) 55 56 /// A 2D column vector. 57 struct b2Vec2 58 { 59 /// Default constructor does nothing (for performance). 60 b2Vec2() {} 61 62 /// Construct using coordinates. 63 b2Vec2(float32 x, float32 y) : x(x), y(y) {} 64 65 /// Set this vector to all zeros. 66 void SetZero() { x = 0.0f; y = 0.0f; } 67 68 /// Set this vector to some specified coordinates. 69 void Set(float32 x_, float32 y_) { x = x_; y = y_; } 70 71 /// Negate this vector. 72 b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } 73 74 /// Read from and indexed element. 75 float32 operator () (int32 i) const 76 { 77 return (&x)[i]; 78 } 79 80 /// Write to an indexed element. 81 float32& operator () (int32 i) 82 { 83 return (&x)[i]; 84 } 85 86 /// Add a vector to this vector. 87 void operator += (const b2Vec2& v) 88 { 89 x += v.x; y += v.y; 90 } 91 92 /// Subtract a vector from this vector. 93 void operator -= (const b2Vec2& v) 94 { 95 x -= v.x; y -= v.y; 96 } 97 98 /// Multiply this vector by a scalar. 99 void operator *= (float32 a) 100 { 101 x *= a; y *= a; 102 } 103 104 /// Get the length of this vector (the norm). 105 float32 Length() const 106 { 107 return b2Sqrt(x * x + y * y); 108 } 109 110 /// Get the length squared. For performance, use this instead of 111 /// b2Vec2::Length (if possible). 112 float32 LengthSquared() const 113 { 114 return x * x + y * y; 115 } 116 117 /// Convert this vector into a unit vector. Returns the length. 118 float32 Normalize() 119 { 120 float32 length = Length(); 121 if (length < b2_epsilon) 122 { 123 return 0.0f; 124 } 125 float32 invLength = 1.0f / length; 126 x *= invLength; 127 y *= invLength; 128 129 return length; 130 } 131 132 /// Does this vector contain finite coordinates? 133 bool IsValid() const 134 { 135 return b2IsValid(x) && b2IsValid(y); 136 } 137 138 /// Get the skew vector such that dot(skew_vec, other) == cross(vec, other) 139 b2Vec2 Skew() const 140 { 141 return b2Vec2(-y, x); 142 } 143 144 float32 x, y; 145 }; 146 147 /// A 2D column vector with 3 elements. 148 struct b2Vec3 149 { 150 /// Default constructor does nothing (for performance). 151 b2Vec3() {} 152 153 /// Construct using coordinates. 154 b2Vec3(float32 x, float32 y, float32 z) : x(x), y(y), z(z) {} 155 156 /// Set this vector to all zeros. 157 void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; } 158 159 /// Set this vector to some specified coordinates. 160 void Set(float32 x_, float32 y_, float32 z_) { x = x_; y = y_; z = z_; } 161 162 /// Negate this vector. 163 b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; } 164 165 /// Add a vector to this vector. 166 void operator += (const b2Vec3& v) 167 { 168 x += v.x; y += v.y; z += v.z; 169 } 170 171 /// Subtract a vector from this vector. 172 void operator -= (const b2Vec3& v) 173 { 174 x -= v.x; y -= v.y; z -= v.z; 175 } 176 177 /// Multiply this vector by a scalar. 178 void operator *= (float32 s) 179 { 180 x *= s; y *= s; z *= s; 181 } 182 183 float32 x, y, z; 184 }; 185 186 /// A 2-by-2 matrix. Stored in column-major order. 187 struct b2Mat22 188 { 189 /// The default constructor does nothing (for performance). 190 b2Mat22() {} 191 192 /// Construct this matrix using columns. 193 b2Mat22(const b2Vec2& c1, const b2Vec2& c2) 194 { 195 ex = c1; 196 ey = c2; 197 } 198 199 /// Construct this matrix using scalars. 200 b2Mat22(float32 a11, float32 a12, float32 a21, float32 a22) 201 { 202 ex.x = a11; ex.y = a21; 203 ey.x = a12; ey.y = a22; 204 } 205 206 /// Initialize this matrix using columns. 207 void Set(const b2Vec2& c1, const b2Vec2& c2) 208 { 209 ex = c1; 210 ey = c2; 211 } 212 213 /// Set this to the identity matrix. 214 void SetIdentity() 215 { 216 ex.x = 1.0f; ey.x = 0.0f; 217 ex.y = 0.0f; ey.y = 1.0f; 218 } 219 220 /// Set this matrix to all zeros. 221 void SetZero() 222 { 223 ex.x = 0.0f; ey.x = 0.0f; 224 ex.y = 0.0f; ey.y = 0.0f; 225 } 226 227 b2Mat22 GetInverse() const 228 { 229 float32 a = ex.x, b = ey.x, c = ex.y, d = ey.y; 230 b2Mat22 B; 231 float32 det = a * d - b * c; 232 if (det != 0.0f) 233 { 234 det = 1.0f / det; 235 } 236 B.ex.x = det * d; B.ey.x = -det * b; 237 B.ex.y = -det * c; B.ey.y = det * a; 238 return B; 239 } 240 241 /// Solve A * x = b, where b is a column vector. This is more efficient 242 /// than computing the inverse in one-shot cases. 243 b2Vec2 Solve(const b2Vec2& b) const 244 { 245 float32 a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y; 246 float32 det = a11 * a22 - a12 * a21; 247 if (det != 0.0f) 248 { 249 det = 1.0f / det; 250 } 251 b2Vec2 x; 252 x.x = det * (a22 * b.x - a12 * b.y); 253 x.y = det * (a11 * b.y - a21 * b.x); 254 return x; 255 } 256 257 b2Vec2 ex, ey; 258 }; 259 260 /// A 3-by-3 matrix. Stored in column-major order. 261 struct b2Mat33 262 { 263 /// The default constructor does nothing (for performance). 264 b2Mat33() {} 265 266 /// Construct this matrix using columns. 267 b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3) 268 { 269 ex = c1; 270 ey = c2; 271 ez = c3; 272 } 273 274 /// Set this matrix to all zeros. 275 void SetZero() 276 { 277 ex.SetZero(); 278 ey.SetZero(); 279 ez.SetZero(); 280 } 281 282 /// Solve A * x = b, where b is a column vector. This is more efficient 283 /// than computing the inverse in one-shot cases. 284 b2Vec3 Solve33(const b2Vec3& b) const; 285 286 /// Solve A * x = b, where b is a column vector. This is more efficient 287 /// than computing the inverse in one-shot cases. Solve only the upper 288 /// 2-by-2 matrix equation. 289 b2Vec2 Solve22(const b2Vec2& b) const; 290 291 /// Get the inverse of this matrix as a 2-by-2. 292 /// Returns the zero matrix if singular. 293 void GetInverse22(b2Mat33* M) const; 294 295 /// Get the symmetric inverse of this matrix as a 3-by-3. 296 /// Returns the zero matrix if singular. 297 void GetSymInverse33(b2Mat33* M) const; 298 299 b2Vec3 ex, ey, ez; 300 }; 301 302 /// Rotation 303 struct b2Rot 304 { 305 b2Rot() {} 306 307 /// Initialize from an angle in radians 308 explicit b2Rot(float32 angle) 309 { 310 /// TODO_ERIN optimize 311 s = sinf(angle); 312 c = cosf(angle); 313 } 314 315 /// Set using an angle in radians. 316 void Set(float32 angle) 317 { 318 /// TODO_ERIN optimize 319 s = sinf(angle); 320 c = cosf(angle); 321 } 322 323 /// Set to the identity rotation 324 void SetIdentity() 325 { 326 s = 0.0f; 327 c = 1.0f; 328 } 329 330 /// Get the angle in radians 331 float32 GetAngle() const 332 { 333 return b2Atan2(s, c); 334 } 335 336 /// Get the x-axis 337 b2Vec2 GetXAxis() const 338 { 339 return b2Vec2(c, s); 340 } 341 342 /// Get the u-axis 343 b2Vec2 GetYAxis() const 344 { 345 return b2Vec2(-s, c); 346 } 347 348 /// Sine and cosine 349 float32 s, c; 350 }; 351 352 /// A transform contains translation and rotation. It is used to represent 353 /// the position and orientation of rigid frames. 354 struct b2Transform 355 { 356 /// The default constructor does nothing. 357 b2Transform() {} 358 359 /// Initialize using a position vector and a rotation. 360 b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {} 361 362 /// Set this to the identity transform. 363 void SetIdentity() 364 { 365 p.SetZero(); 366 q.SetIdentity(); 367 } 368 369 /// Set this based on the position and angle. 370 void Set(const b2Vec2& position, float32 angle) 371 { 372 p = position; 373 q.Set(angle); 374 } 375 376 b2Vec2 p; 377 b2Rot q; 378 }; 379 380 /// This describes the motion of a body/shape for TOI computation. 381 /// Shapes are defined with respect to the body origin, which may 382 /// no coincide with the center of mass. However, to support dynamics 383 /// we must interpolate the center of mass position. 384 struct b2Sweep 385 { 386 /// Get the interpolated transform at a specific time. 387 /// @param beta is a factor in [0,1], where 0 indicates alpha0. 388 void GetTransform(b2Transform* xfb, float32 beta) const; 389 390 /// Advance the sweep forward, yielding a new initial state. 391 /// @param alpha the new initial time. 392 void Advance(float32 alpha); 393 394 /// Normalize the angles. 395 void Normalize(); 396 397 b2Vec2 localCenter; ///< local center of mass position 398 b2Vec2 c0, c; ///< center world positions 399 float32 a0, a; ///< world angles 400 401 /// Fraction of the current time step in the range [0,1] 402 /// c0 and a0 are the positions at alpha0. 403 float32 alpha0; 404 }; 405 406 /// Useful constant 407 extern const b2Vec2 b2Vec2_zero; 408 409 /// Perform the dot product on two vectors. 410 inline float32 b2Dot(const b2Vec2& a, const b2Vec2& b) 411 { 412 return a.x * b.x + a.y * b.y; 413 } 414 415 /// Perform the cross product on two vectors. In 2D this produces a scalar. 416 inline float32 b2Cross(const b2Vec2& a, const b2Vec2& b) 417 { 418 return a.x * b.y - a.y * b.x; 419 } 420 421 /// Perform the cross product on a vector and a scalar. In 2D this produces 422 /// a vector. 423 inline b2Vec2 b2Cross(const b2Vec2& a, float32 s) 424 { 425 return b2Vec2(s * a.y, -s * a.x); 426 } 427 428 /// Perform the cross product on a scalar and a vector. In 2D this produces 429 /// a vector. 430 inline b2Vec2 b2Cross(float32 s, const b2Vec2& a) 431 { 432 return b2Vec2(-s * a.y, s * a.x); 433 } 434 435 /// Multiply a matrix times a vector. If a rotation matrix is provided, 436 /// then this transforms the vector from one frame to another. 437 inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v) 438 { 439 return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); 440 } 441 442 /// Multiply a matrix transpose times a vector. If a rotation matrix is provided, 443 /// then this transforms the vector from one frame to another (inverse transform). 444 inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v) 445 { 446 return b2Vec2(b2Dot(v, A.ex), b2Dot(v, A.ey)); 447 } 448 449 /// Add two vectors component-wise. 450 inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b) 451 { 452 return b2Vec2(a.x + b.x, a.y + b.y); 453 } 454 455 /// Subtract two vectors component-wise. 456 inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b) 457 { 458 return b2Vec2(a.x - b.x, a.y - b.y); 459 } 460 461 inline b2Vec2 operator * (float32 s, const b2Vec2& a) 462 { 463 return b2Vec2(s * a.x, s * a.y); 464 } 465 466 inline bool operator == (const b2Vec2& a, const b2Vec2& b) 467 { 468 return a.x == b.x && a.y == b.y; 469 } 470 471 inline float32 b2Distance(const b2Vec2& a, const b2Vec2& b) 472 { 473 b2Vec2 c = a - b; 474 return c.Length(); 475 } 476 477 inline float32 b2DistanceSquared(const b2Vec2& a, const b2Vec2& b) 478 { 479 b2Vec2 c = a - b; 480 return b2Dot(c, c); 481 } 482 483 inline b2Vec3 operator * (float32 s, const b2Vec3& a) 484 { 485 return b2Vec3(s * a.x, s * a.y, s * a.z); 486 } 487 488 /// Add two vectors component-wise. 489 inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b) 490 { 491 return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z); 492 } 493 494 /// Subtract two vectors component-wise. 495 inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b) 496 { 497 return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z); 498 } 499 500 /// Perform the dot product on two vectors. 501 inline float32 b2Dot(const b2Vec3& a, const b2Vec3& b) 502 { 503 return a.x * b.x + a.y * b.y + a.z * b.z; 504 } 505 506 /// Perform the cross product on two vectors. 507 inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b) 508 { 509 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); 510 } 511 512 inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B) 513 { 514 return b2Mat22(A.ex + B.ex, A.ey + B.ey); 515 } 516 517 // A * B 518 inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B) 519 { 520 return b2Mat22(b2Mul(A, B.ex), b2Mul(A, B.ey)); 521 } 522 523 // A^T * B 524 inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B) 525 { 526 b2Vec2 c1(b2Dot(A.ex, B.ex), b2Dot(A.ey, B.ex)); 527 b2Vec2 c2(b2Dot(A.ex, B.ey), b2Dot(A.ey, B.ey)); 528 return b2Mat22(c1, c2); 529 } 530 531 /// Multiply a matrix times a vector. 532 inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v) 533 { 534 return v.x * A.ex + v.y * A.ey + v.z * A.ez; 535 } 536 537 /// Multiply a matrix times a vector. 538 inline b2Vec2 b2Mul22(const b2Mat33& A, const b2Vec2& v) 539 { 540 return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); 541 } 542 543 /// Multiply two rotations: q * r 544 inline b2Rot b2Mul(const b2Rot& q, const b2Rot& r) 545 { 546 // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] 547 // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] 548 // s = qs * rc + qc * rs 549 // c = qc * rc - qs * rs 550 b2Rot qr; 551 qr.s = q.s * r.c + q.c * r.s; 552 qr.c = q.c * r.c - q.s * r.s; 553 return qr; 554 } 555 556 /// Transpose multiply two rotations: qT * r 557 inline b2Rot b2MulT(const b2Rot& q, const b2Rot& r) 558 { 559 // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc] 560 // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc] 561 // s = qc * rs - qs * rc 562 // c = qc * rc + qs * rs 563 b2Rot qr; 564 qr.s = q.c * r.s - q.s * r.c; 565 qr.c = q.c * r.c + q.s * r.s; 566 return qr; 567 } 568 569 /// Rotate a vector 570 inline b2Vec2 b2Mul(const b2Rot& q, const b2Vec2& v) 571 { 572 return b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y); 573 } 574 575 /// Inverse rotate a vector 576 inline b2Vec2 b2MulT(const b2Rot& q, const b2Vec2& v) 577 { 578 return b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y); 579 } 580 581 inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v) 582 { 583 float32 x = (T.q.c * v.x - T.q.s * v.y) + T.p.x; 584 float32 y = (T.q.s * v.x + T.q.c * v.y) + T.p.y; 585 586 return b2Vec2(x, y); 587 } 588 589 inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v) 590 { 591 float32 px = v.x - T.p.x; 592 float32 py = v.y - T.p.y; 593 float32 x = (T.q.c * px + T.q.s * py); 594 float32 y = (-T.q.s * px + T.q.c * py); 595 596 return b2Vec2(x, y); 597 } 598 599 // v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p 600 // = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p 601 inline b2Transform b2Mul(const b2Transform& A, const b2Transform& B) 602 { 603 b2Transform C; 604 C.q = b2Mul(A.q, B.q); 605 C.p = b2Mul(A.q, B.p) + A.p; 606 return C; 607 } 608 609 // v2 = A.q' * (B.q * v1 + B.p - A.p) 610 // = A.q' * B.q * v1 + A.q' * (B.p - A.p) 611 inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B) 612 { 613 b2Transform C; 614 C.q = b2MulT(A.q, B.q); 615 C.p = b2MulT(A.q, B.p - A.p); 616 return C; 617 } 618 619 template <typename T> 620 inline T b2Abs(T a) 621 { 622 return a > T(0) ? a : -a; 623 } 624 625 inline b2Vec2 b2Abs(const b2Vec2& a) 626 { 627 return b2Vec2(b2Abs(a.x), b2Abs(a.y)); 628 } 629 630 inline b2Mat22 b2Abs(const b2Mat22& A) 631 { 632 return b2Mat22(b2Abs(A.ex), b2Abs(A.ey)); 633 } 634 635 template <typename T> 636 inline T b2Min(T a, T b) 637 { 638 return a < b ? a : b; 639 } 640 641 inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b) 642 { 643 return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)); 644 } 645 646 template <typename T> 647 inline T b2Max(T a, T b) 648 { 649 return a > b ? a : b; 650 } 651 652 inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b) 653 { 654 return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)); 655 } 656 657 template <typename T> 658 inline T b2Clamp(T a, T low, T high) 659 { 660 return b2Max(low, b2Min(a, high)); 661 } 662 663 inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high) 664 { 665 return b2Max(low, b2Min(a, high)); 666 } 667 668 template<typename T> inline void b2Swap(T& a, T& b) 669 { 670 T tmp = a; 671 a = b; 672 b = tmp; 673 } 674 675 /// "Next Largest Power of 2 676 /// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm 677 /// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with 678 /// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next 679 /// largest power of 2. For a 32-bit value:" 680 inline uint32 b2NextPowerOfTwo(uint32 x) 681 { 682 x |= (x >> 1); 683 x |= (x >> 2); 684 x |= (x >> 4); 685 x |= (x >> 8); 686 x |= (x >> 16); 687 return x + 1; 688 } 689 690 inline bool b2IsPowerOfTwo(uint32 x) 691 { 692 bool result = x > 0 && (x & (x - 1)) == 0; 693 return result; 694 } 695 696 inline void b2Sweep::GetTransform(b2Transform* xf, float32 beta) const 697 { 698 xf->p = (1.0f - beta) * c0 + beta * c; 699 float32 angle = (1.0f - beta) * a0 + beta * a; 700 xf->q.Set(angle); 701 702 // Shift to origin 703 xf->p -= b2Mul(xf->q, localCenter); 704 } 705 706 inline void b2Sweep::Advance(float32 alpha) 707 { 708 b2Assert(alpha0 < 1.0f); 709 float32 beta = (alpha - alpha0) / (1.0f - alpha0); 710 c0 += beta * (c - c0); 711 a0 += beta * (a - a0); 712 alpha0 = alpha; 713 } 714 715 /// Normalize an angle in radians to be between -pi and pi 716 inline void b2Sweep::Normalize() 717 { 718 float32 twoPi = 2.0f * b2_pi; 719 float32 d = twoPi * floorf(a0 / twoPi); 720 a0 -= d; 721 a -= d; 722 } 723 724 #endif 725