PhysicsConstraint.cpp 5.0 KB

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