PhysicsConstraint.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "Base.h"
  2. #include "PhysicsConstraint.h"
  3. #include "Game.h"
  4. #include "Node.h"
  5. #include "PhysicsMotionState.h"
  6. #include "PhysicsRigidBody.h"
  7. namespace gameplay
  8. {
  9. PhysicsConstraint::PhysicsConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
  10. : _a(a), _b(b), _constraint(NULL)
  11. {
  12. }
  13. PhysicsConstraint::~PhysicsConstraint()
  14. {
  15. // Remove the physics rigid bodies' references to this constraint.
  16. if (_a)
  17. _a->removeConstraint(this);
  18. if (_b)
  19. _b->removeConstraint(this);
  20. // Remove the constraint from the physics world and delete the Bullet object.
  21. Game::getInstance()->getPhysicsController()->removeConstraint(this);
  22. SAFE_DELETE(_constraint);
  23. }
  24. Vector3 PhysicsConstraint::centerOfMassMidpoint(const Node* a, const Node* b)
  25. {
  26. Vector3 tA, tB;
  27. a->getWorldMatrix().getTranslation(&tA);
  28. b->getWorldMatrix().getTranslation(&tB);
  29. tA = getWorldCenterOfMass(a->getModel());
  30. tB = getWorldCenterOfMass(b->getModel());
  31. Vector3 d(tA, tB);
  32. d.scale(0.5f);
  33. Vector3 c(tA);
  34. c.add(d);
  35. return c;
  36. }
  37. Quaternion PhysicsConstraint::getRotationOffset(const Node* node, const Vector3& point)
  38. {
  39. // Create a translation matrix that translates to the given origin.
  40. Matrix m;
  41. Matrix::createTranslation(point, &m);
  42. // Calculate the rotation offset to the rigid body by transforming
  43. // the translation matrix above into the rigid body's local space
  44. // (multiply by the inverse world matrix) and extracting the rotation.
  45. Matrix mi;
  46. node->getWorldMatrix().invert(&mi);
  47. mi.multiply(m);
  48. Quaternion r;
  49. mi.getRotation(&r);
  50. return r;
  51. }
  52. Vector3 PhysicsConstraint::getTranslationOffset(const Node* node, const Vector3& point)
  53. {
  54. // Create a translation matrix that translates to the given origin.
  55. Matrix m;
  56. Matrix::createTranslation(point, &m);
  57. // Calculate the translation offset to the rigid body by transforming
  58. // the translation matrix above into the rigid body's local space
  59. // (multiply by the inverse world matrix) and extracting the translation.
  60. Matrix mi;
  61. node->getWorldMatrix().invert(&mi);
  62. mi.multiply(m);
  63. Vector3 t;
  64. mi.getTranslation(&t);
  65. Vector3 s;
  66. node->getWorldMatrix().getScale(&s);
  67. t.x *= s.x;
  68. t.y *= s.y;
  69. t.z *= s.z;
  70. t = offsetByCenterOfMass(node, t);
  71. return t;
  72. }
  73. btTransform PhysicsConstraint::getTransformOffset(const Node* node, const Vector3& origin)
  74. {
  75. // Create a translation matrix that translates to the given origin.
  76. Matrix m;
  77. Matrix::createTranslation(origin, &m);
  78. // Calculate the translation and rotation offset to the rigid body
  79. // by transforming the translation matrix above into the rigid body's
  80. // local space (multiply by the inverse world matrix and extract components).
  81. Matrix mi;
  82. node->getWorldMatrix().invert(&mi);
  83. mi.multiply(m);
  84. Quaternion r;
  85. mi.getRotation(&r);
  86. Vector3 t;
  87. mi.getTranslation(&t);
  88. Vector3 s;
  89. node->getWorldMatrix().getScale(&s);
  90. t.x *= s.x;
  91. t.y *= s.y;
  92. t.z *= s.z;
  93. t = offsetByCenterOfMass(node, t);
  94. return btTransform(BQ(r), BV(t));
  95. }
  96. Vector3 PhysicsConstraint::getWorldCenterOfMass(const Model* model)
  97. {
  98. Vector3 center;
  99. const BoundingBox& box = model->getMesh()->getBoundingBox();
  100. if (!(box.min.isZero() && box.max.isZero()))
  101. {
  102. Vector3 bMin, bMax;
  103. model->getNode()->getWorldMatrix().transformPoint(box.min, &bMin);
  104. model->getNode()->getWorldMatrix().transformPoint(box.max, &bMax);
  105. center.set(bMin, bMax);
  106. center.scale(0.5f);
  107. center.add(bMin);
  108. }
  109. else
  110. {
  111. const BoundingSphere& sphere = model->getMesh()->getBoundingSphere();
  112. if (!(sphere.center.isZero() && sphere.radius == 0))
  113. {
  114. model->getNode()->getWorldMatrix().transformPoint(sphere.center, &center);
  115. }
  116. else
  117. {
  118. // Warn the user that the model has no bounding volume.
  119. WARN_VARG("Model \'%s\' has no bounding volume - center of mass is defaulting to local coordinate origin.", model->getNode()->getId());
  120. model->getNode()->getWorldMatrix().transformPoint(&center);
  121. }
  122. }
  123. return center;
  124. }
  125. Vector3 PhysicsConstraint::offsetByCenterOfMass(const Node* node, const Vector3& v)
  126. {
  127. btVector3 centerOfMassOffset = (node->getCollisionObject()->getMotionState())->_centerOfMassOffset.getOrigin();
  128. return Vector3(v.x + centerOfMassOffset.x(), v.y + centerOfMassOffset.y(), v.z + centerOfMassOffset.z());
  129. }
  130. }