Joint.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Context.h"
  25. #include "Joint.h"
  26. #include "Log.h"
  27. #include "PhysicsWorld.h"
  28. #include "RigidBody.h"
  29. #include "Scene.h"
  30. #include <ode/ode.h>
  31. #include "DebugNew.h"
  32. static const String typeNames[] =
  33. {
  34. "None",
  35. "Ball",
  36. "Hinge",
  37. ""
  38. };
  39. OBJECTTYPESTATIC(Joint);
  40. Joint::Joint(Context* context) :
  41. Component(context),
  42. type_(JOINT_NONE),
  43. joint_(0),
  44. position_(Vector3::ZERO),
  45. axis_(Vector3::ZERO),
  46. recreateJoint_(false)
  47. {
  48. }
  49. Joint::~Joint()
  50. {
  51. Clear();
  52. if (physicsWorld_)
  53. physicsWorld_->RemoveJoint(this);
  54. }
  55. void Joint::RegisterObject(Context* context)
  56. {
  57. context->RegisterFactory<Joint>();
  58. ENUM_ATTRIBUTE(Joint, "Joint Type", type_, typeNames, JOINT_NONE, AM_DEFAULT);
  59. ACCESSOR_ATTRIBUTE(Joint, VAR_INT, "Body A", GetBodyAAttr, SetBodyAAttr, int, 0, AM_DEFAULT);
  60. ACCESSOR_ATTRIBUTE(Joint, VAR_INT, "Body B", GetBodyBAttr, SetBodyBAttr, int, 0, AM_DEFAULT);
  61. ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
  62. ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
  63. }
  64. void Joint::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
  65. {
  66. Serializable::OnSetAttribute(attr, src);
  67. // Change of the joint type requires the joint to be recreated
  68. if (attr.offset_ == offsetof(Joint, type_))
  69. recreateJoint_ = true;
  70. }
  71. void Joint::ApplyAttributes()
  72. {
  73. if (recreateJoint_)
  74. {
  75. switch (type_)
  76. {
  77. case JOINT_NONE:
  78. Clear();
  79. break;
  80. case JOINT_BALL:
  81. SetBall(position_, bodyA_, bodyB_);
  82. break;
  83. case JOINT_HINGE:
  84. SetHinge(position_, axis_, bodyA_, bodyB_);
  85. break;
  86. }
  87. recreateJoint_ = false;
  88. }
  89. }
  90. void Joint::GetDependencyNodes(PODVector<Node*>& dest)
  91. {
  92. if (bodyA_ && bodyA_->GetNode())
  93. dest.Push(bodyA_->GetNode());
  94. if (bodyB_ && bodyB_->GetNode())
  95. dest.Push(bodyB_->GetNode());
  96. }
  97. void Joint::Clear()
  98. {
  99. if (joint_ && physicsWorld_)
  100. {
  101. dJointDestroy(joint_);
  102. joint_ = 0;
  103. }
  104. bodyA_.Reset();
  105. bodyB_.Reset();
  106. type_ = JOINT_NONE;
  107. }
  108. bool Joint::SetBall(const Vector3& position, RigidBody* bodyA, RigidBody* bodyB)
  109. {
  110. Clear();
  111. if (!physicsWorld_)
  112. {
  113. LOGERROR("Null physics world, can not set joint type");
  114. return false;
  115. }
  116. if (!bodyA && !bodyB)
  117. {
  118. LOGERROR("Both bodies null, can not create joint");
  119. return false;
  120. }
  121. joint_ = dJointCreateBall(physicsWorld_->GetWorld(), 0);
  122. dJointSetData(joint_, this);
  123. dJointSetBallAnchor(joint_, position.x_, position.y_, position.z_);
  124. dJointAttach(joint_, bodyA ? bodyA->GetBody() : 0, bodyB ? bodyB->GetBody() : 0);
  125. type_ = JOINT_BALL;
  126. bodyA_ = bodyA;
  127. bodyB_ = bodyB;
  128. return true;
  129. }
  130. bool Joint::SetHinge(const Vector3& position, const Vector3& axis, RigidBody* bodyA, RigidBody* bodyB)
  131. {
  132. Clear();
  133. if (!physicsWorld_)
  134. {
  135. LOGERROR("Null physics world, can not set joint type");
  136. return false;
  137. }
  138. if (!bodyA && !bodyB)
  139. {
  140. LOGERROR("Both bodies null, can not create joint");
  141. return false;
  142. }
  143. Vector3 NormalizedAxis = axis.Normalized();
  144. joint_ = dJointCreateHinge(physicsWorld_->GetWorld(), 0);
  145. dJointSetData(joint_, this);
  146. dJointSetHingeAnchor(joint_, position.x_, position.y_, position.z_);
  147. dJointSetHingeAxis(joint_, NormalizedAxis.x_, NormalizedAxis.y_, NormalizedAxis.z_);
  148. dJointAttach(joint_, bodyA ? bodyA->GetBody() : 0, bodyB ? bodyB->GetBody() : 0);
  149. type_ = JOINT_HINGE;
  150. bodyA_ = bodyA;
  151. bodyB_ = bodyB;
  152. return true;
  153. }
  154. void Joint::SetPosition(Vector3 position)
  155. {
  156. if (joint_)
  157. {
  158. dJointType type = dJointGetType(joint_);
  159. switch (type)
  160. {
  161. case dJointTypeBall:
  162. dJointSetBallAnchor(joint_, position.x_, position.y_, position.z_);
  163. break;
  164. case dJointTypeHinge:
  165. dJointSetHingeAnchor(joint_, position.x_, position.y_, position.z_);
  166. break;
  167. }
  168. }
  169. }
  170. void Joint::SetAxis(Vector3 axis)
  171. {
  172. if (joint_)
  173. {
  174. dJointType type = dJointGetType(joint_);
  175. switch (type)
  176. {
  177. case dJointTypeHinge:
  178. dJointSetHingeAxis(joint_, axis.x_, axis.y_, axis.z_);
  179. break;
  180. }
  181. }
  182. }
  183. Vector3 Joint::GetPosition() const
  184. {
  185. dVector3 pos;
  186. if (joint_)
  187. {
  188. dJointType type = dJointGetType(joint_);
  189. switch (type)
  190. {
  191. case dJointTypeBall:
  192. dJointGetBallAnchor(joint_, pos);
  193. return Vector3(pos[0], pos[1], pos[2]);
  194. case dJointTypeHinge:
  195. dJointGetHingeAnchor(joint_, pos);
  196. return Vector3(pos[0], pos[1], pos[2]);
  197. }
  198. }
  199. return Vector3::ZERO;
  200. }
  201. Vector3 Joint::GetAxis() const
  202. {
  203. dVector3 axis;
  204. if (joint_)
  205. {
  206. dJointType type = dJointGetType(joint_);
  207. switch (type)
  208. {
  209. case dJointTypeHinge:
  210. dJointGetHingeAxis(joint_, axis);
  211. return Vector3(axis[0], axis[1], axis[2]);
  212. }
  213. }
  214. return Vector3::ZERO;
  215. }
  216. void Joint::SetBodyAAttr(int value)
  217. {
  218. Scene* scene = node_ ? node_->GetScene() : 0;
  219. bodyA_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponent(value)) : (RigidBody*)0;
  220. recreateJoint_ = true;
  221. }
  222. void Joint::SetBodyBAttr(int value)
  223. {
  224. Scene* scene = node_ ? node_->GetScene() : 0;
  225. bodyB_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponent(value)) : (RigidBody*)0;
  226. recreateJoint_ = true;
  227. }
  228. int Joint::GetBodyAAttr() const
  229. {
  230. return bodyA_ ? bodyA_->GetID() : 0;
  231. }
  232. int Joint::GetBodyBAttr() const
  233. {
  234. return bodyB_ ? bodyB_->GetID() : 0;
  235. }
  236. void Joint::OnNodeSet(Node* node)
  237. {
  238. if (node)
  239. {
  240. Scene* scene = node->GetScene();
  241. if (scene)
  242. {
  243. physicsWorld_ = scene->GetComponent<PhysicsWorld>();
  244. if (physicsWorld_)
  245. physicsWorld_->AddJoint(this);
  246. }
  247. }
  248. }