PhysicsConstraint.cpp 4.7 KB

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