RigidBody.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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 "CollisionShape.h"
  25. #include "Context.h"
  26. #include "Log.h"
  27. #include "MemoryBuffer.h"
  28. #include "PhysicsWorld.h"
  29. #include "ResourceCache.h"
  30. #include "ResourceEvents.h"
  31. #include "RigidBody.h"
  32. #include "Scene.h"
  33. #include "XMLElement.h"
  34. #include <ode/ode.h>
  35. #include "DebugNew.h"
  36. static const float DEFAULT_MASS = 1.0f;
  37. static const int DEFAULT_MASS_AXIS = 1;
  38. static const String modeNames[] =
  39. {
  40. "static",
  41. "dynamic",
  42. "kinematic"
  43. };
  44. OBJECTTYPESTATIC(RigidBody);
  45. RigidBody::RigidBody(Context* context) :
  46. Component(context),
  47. mass_(DEFAULT_MASS),
  48. massAxis_(DEFAULT_MASS_AXIS),
  49. body_(0),
  50. inPostStep_(false)
  51. {
  52. }
  53. RigidBody::~RigidBody()
  54. {
  55. ReleaseBody();
  56. if (physicsWorld_)
  57. physicsWorld_->RemoveRigidBody(this);
  58. }
  59. void RigidBody::RegisterObject(Context* context)
  60. {
  61. context->RegisterFactory<RigidBody>();
  62. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Mass", GetMass, SetMass, float, DEFAULT_MASS, AM_DEFAULT);
  63. ACCESSOR_ATTRIBUTE(RigidBody, VAR_INT, "Mass Axis", GetMassAxis, SetMassAxis, int, DEFAULT_MASS_AXIS, AM_DEFAULT);
  64. REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
  65. REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
  66. REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Lin Velocity", GetLinearVelocity, SetLinearVelocity, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
  67. REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Ang Velocity", GetAngularVelocity, SetAngularVelocity, Vector3, Vector3::ZERO, AM_FILE);
  68. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Lin Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
  69. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Lin Damp Threshold", GetLinearDampingThreshold, SetLinearDampingThreshold, float, 0.01f, AM_DEFAULT);
  70. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Lin Damp Scale", GetLinearDampingScale, SetLinearDampingScale, float, 0.0f, AM_DEFAULT);
  71. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Ang Rest Threshold", GetAngularRestThreshold, SetAngularRestThreshold, float, 0.01f, AM_DEFAULT);
  72. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Ang Damp Threshold", GetAngularDampingThreshold, SetAngularDampingThreshold, float, 0.01f, AM_DEFAULT);
  73. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Ang Damp Scale", GetAngularDampingScale, SetAngularDampingScale, float, 0.0f, AM_DEFAULT);
  74. ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Ang Max Velocity", GetAngularMaxVelocity, SetAngularMaxVelocity, float, M_INFINITY, AM_DEFAULT);
  75. REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_BUFFER, "Network Ang Velocity", GetNetAngularVelocityAttr, SetNetAngularVelocityAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
  76. ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Active", IsActive, SetActive, bool, true, AM_FILE);
  77. }
  78. void RigidBody::SetMass(float mass)
  79. {
  80. mass_ = Max(mass, 0.0f);
  81. UpdateMass();
  82. }
  83. void RigidBody::SetMassAxis(int massAxis)
  84. {
  85. massAxis_ = Clamp(massAxis, 0, 2);
  86. UpdateMass();
  87. }
  88. void RigidBody::SetPosition(const Vector3& position)
  89. {
  90. if (body_)
  91. {
  92. dBodySetPosition(body_, position.x_, position.y_, position.z_);
  93. previousPosition_ = position;
  94. }
  95. }
  96. void RigidBody::SetRotation(const Quaternion& rotation)
  97. {
  98. if (body_)
  99. {
  100. dBodySetQuaternion(body_, rotation.GetData());
  101. previousRotation_ = rotation;
  102. }
  103. }
  104. void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation)
  105. {
  106. if (body_)
  107. {
  108. dBodySetPosition(body_, position.x_, position.y_, position.z_);
  109. dBodySetQuaternion(body_, rotation.GetData());
  110. previousPosition_ = position;
  111. previousRotation_ = rotation;
  112. }
  113. }
  114. void RigidBody::SetLinearVelocity(const Vector3& velocity)
  115. {
  116. if (body_)
  117. dBodySetLinearVel(body_, velocity.x_, velocity.y_, velocity.z_);
  118. }
  119. void RigidBody::SetLinearRestThreshold(float threshold)
  120. {
  121. if (body_)
  122. dBodySetAutoDisableLinearThreshold(body_, threshold);
  123. }
  124. void RigidBody::SetLinearDampingThreshold(float threshold)
  125. {
  126. if (body_)
  127. dBodySetLinearDampingThreshold(body_, threshold);
  128. }
  129. void RigidBody::SetLinearDampingScale(float scale)
  130. {
  131. if (body_)
  132. dBodySetLinearDamping(body_, scale);
  133. }
  134. void RigidBody::SetAngularVelocity(const Vector3& velocity)
  135. {
  136. if (body_)
  137. dBodySetAngularVel(body_, velocity.x_, velocity.y_, velocity.z_);
  138. }
  139. void RigidBody::SetAngularRestThreshold(float threshold)
  140. {
  141. if (body_)
  142. dBodySetAutoDisableAngularThreshold(body_, threshold);
  143. }
  144. void RigidBody::SetAngularDampingThreshold(float threshold)
  145. {
  146. if (body_)
  147. dBodySetAngularDampingThreshold(body_, threshold);
  148. }
  149. void RigidBody::SetAngularDampingScale(float scale)
  150. {
  151. if (body_)
  152. dBodySetAngularDamping(body_, scale);
  153. }
  154. void RigidBody::SetAngularMaxVelocity(float velocity)
  155. {
  156. if (body_)
  157. dBodySetMaxAngularSpeed(body_, velocity);
  158. }
  159. void RigidBody::SetActive(bool active)
  160. {
  161. if (body_)
  162. {
  163. if (active && !dBodyIsEnabled(body_))
  164. dBodyEnable(body_);
  165. else if (!active && dBodyIsEnabled(body_))
  166. dBodyDisable(body_);
  167. }
  168. }
  169. void RigidBody::ApplyForce(const Vector3& force)
  170. {
  171. if (force == Vector3::ZERO)
  172. return;
  173. if (body_)
  174. {
  175. SetActive(true);
  176. dBodyAddForce(body_, force.x_, force.y_, force.z_);
  177. }
  178. }
  179. void RigidBody::ApplyForceAtPosition(const Vector3& force, const Vector3& position)
  180. {
  181. if (force == Vector3::ZERO)
  182. return;
  183. if (body_)
  184. {
  185. SetActive(true);
  186. dBodyAddForceAtRelPos(body_, force.x_, force.y_, force.z_, position.x_, position.y_, position.z_);
  187. }
  188. }
  189. void RigidBody::ApplyTorque(const Vector3& torque)
  190. {
  191. if (torque == Vector3::ZERO)
  192. return;
  193. if (body_)
  194. {
  195. SetActive(true);
  196. dBodyAddTorque(body_, torque.x_, torque.y_, torque.z_);
  197. }
  198. }
  199. void RigidBody::ResetForces()
  200. {
  201. if (body_)
  202. {
  203. dBodySetForce(body_, 0.0f, 0.0f, 0.0f);
  204. dBodySetTorque(body_, 0.0f, 0.0f, 0.0f);
  205. }
  206. }
  207. const Vector3& RigidBody::GetPosition() const
  208. {
  209. if (body_)
  210. return *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
  211. else
  212. return Vector3::ZERO;
  213. }
  214. const Quaternion& RigidBody::GetRotation() const
  215. {
  216. if (body_)
  217. return *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
  218. else
  219. return Quaternion::IDENTITY;
  220. }
  221. const Vector3& RigidBody::GetLinearVelocity() const
  222. {
  223. if (body_)
  224. return *reinterpret_cast<const Vector3*>(dBodyGetLinearVel(body_));
  225. else
  226. return Vector3::ZERO;
  227. }
  228. float RigidBody::GetLinearRestThreshold() const
  229. {
  230. if (body_)
  231. return dBodyGetAutoDisableLinearThreshold(body_);
  232. else
  233. return 0.0f;
  234. }
  235. float RigidBody::GetLinearDampingThreshold() const
  236. {
  237. if (body_)
  238. return dBodyGetLinearDampingThreshold(body_);
  239. else
  240. return 0.0f;
  241. }
  242. float RigidBody::GetLinearDampingScale() const
  243. {
  244. if (body_)
  245. return dBodyGetLinearDamping(body_);
  246. else
  247. return 0.0f;
  248. }
  249. const Vector3& RigidBody::GetAngularVelocity() const
  250. {
  251. if (body_)
  252. return *reinterpret_cast<const Vector3*>(dBodyGetAngularVel(body_));
  253. else
  254. return Vector3::ZERO;
  255. }
  256. float RigidBody::GetAngularRestThreshold() const
  257. {
  258. if (body_)
  259. return dBodyGetAutoDisableAngularThreshold(body_);
  260. else
  261. return 0.0f;
  262. }
  263. float RigidBody::GetAngularDampingThreshold() const
  264. {
  265. if (body_)
  266. return dBodyGetAngularDampingThreshold(body_);
  267. else
  268. return 0.0f;
  269. }
  270. float RigidBody::GetAngularDampingScale() const
  271. {
  272. if (body_)
  273. return dBodyGetAngularDamping(body_);
  274. else
  275. return 0.0f;
  276. }
  277. float RigidBody::GetAngularMaxVelocity() const
  278. {
  279. if (body_)
  280. return dBodyGetMaxAngularSpeed(body_);
  281. else
  282. return 0.0f;
  283. }
  284. bool RigidBody::IsActive() const
  285. {
  286. if (body_)
  287. return dBodyIsEnabled(body_) != 0;
  288. else
  289. return false;
  290. }
  291. void RigidBody::SetNetAngularVelocityAttr(const PODVector<unsigned char>& value)
  292. {
  293. float maxVelocity = physicsWorld_ ? physicsWorld_->GetMaxNetworkAngularVelocity() : DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY;
  294. MemoryBuffer buf(value);
  295. SetAngularVelocity(buf.ReadPackedVector3(maxVelocity));
  296. }
  297. const PODVector<unsigned char>& RigidBody::GetNetAngularVelocityAttr() const
  298. {
  299. float maxVelocity = physicsWorld_ ? physicsWorld_->GetMaxNetworkAngularVelocity() : DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY;
  300. attrBuffer_.Clear();
  301. attrBuffer_.WritePackedVector3(GetAngularVelocity(), maxVelocity);
  302. return attrBuffer_.GetBuffer();
  303. }
  304. void RigidBody::OnMarkedDirty(Node* node)
  305. {
  306. // Physics operations are not safe from worker threads
  307. Scene* scene = node->GetScene();
  308. if (scene && scene->IsThreadedUpdate())
  309. {
  310. scene->DelayedMarkedDirty(this);
  311. return;
  312. }
  313. // If the node is smoothed, do not use the dirty callback, but rather update manually during prestep
  314. if (node_->IsSmoothed())
  315. return;
  316. // Clear the dirty flag by querying world position; this way we are sure to get the dirty notification immediately
  317. // also the next time the node transform changes
  318. Vector3 newPosition = node_->GetWorldPosition();
  319. // Disregard node dirtying during the physics poststep, when we set node transform ourselves
  320. if (inPostStep_ || !body_)
  321. return;
  322. const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
  323. const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
  324. Quaternion newRotation(node_->GetWorldRotation());
  325. if (newPosition != currentPosition || newRotation != currentRotation)
  326. {
  327. SetActive(true);
  328. dBodySetPosition(body_, newPosition.x_, newPosition.y_, newPosition.z_);
  329. dBodySetQuaternion(body_, newRotation.GetData());
  330. previousPosition_ = newPosition;
  331. previousRotation_ = newRotation;
  332. }
  333. }
  334. void RigidBody::OnNodeSet(Node* node)
  335. {
  336. if (node)
  337. {
  338. Scene* scene = node->GetScene();
  339. if (scene)
  340. {
  341. physicsWorld_ = scene->GetComponent<PhysicsWorld>();
  342. if (physicsWorld_)
  343. physicsWorld_->AddRigidBody(this);
  344. CreateBody();
  345. }
  346. node->AddListener(this);
  347. }
  348. }
  349. void RigidBody::PreStep()
  350. {
  351. if (!body_)
  352. return;
  353. const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
  354. const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
  355. if (!node_->IsSmoothed())
  356. {
  357. // If no smoothing, store the current body position for interpolation
  358. previousPosition_ = currentPosition;
  359. previousRotation_ = currentRotation;
  360. }
  361. else
  362. {
  363. // If smoothing is active, get the node's target transform and check manually if it has changed
  364. Matrix3x4 transform = node_->GetWorldTargetTransform();
  365. Vector3 newPosition = transform.Translation();
  366. Quaternion newRotation = transform.Rotation();
  367. if (newPosition != currentPosition || newRotation != currentRotation)
  368. {
  369. SetActive(true);
  370. dBodySetPosition(body_, newPosition.x_, newPosition.y_, newPosition.z_);
  371. dBodySetQuaternion(body_, newRotation.GetData());
  372. }
  373. }
  374. }
  375. void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
  376. {
  377. if (!body_ || !IsActive())
  378. return;
  379. processedBodies.Insert(this);
  380. inPostStep_ = true;
  381. // If the parent node has a rigid body, process it first
  382. // Note: for optimization, we intentionally assume that the scene root node can not have a rigid body
  383. Node* parent = node_->GetParent();
  384. if (parent && parent != node_->GetScene())
  385. {
  386. RigidBody* parentBody = parent->GetComponent<RigidBody>();
  387. if (parentBody && !processedBodies.Contains(parentBody))
  388. parentBody->PostStep(t, processedBodies);
  389. }
  390. // Apply the physics transform to rendering transform now
  391. const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
  392. const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
  393. if (!parent)
  394. {
  395. // If node already has motion smoothing enabled, do not do substep interpolation
  396. if (!node_->IsSmoothed())
  397. node_->SetTransform(previousPosition_.Lerp(currentPosition, t), previousRotation_.Slerp(currentRotation, t));
  398. else
  399. node_->SetTransform(currentPosition, currentRotation);
  400. }
  401. else
  402. {
  403. // Transform rigid body's world coordinates back to parent's space
  404. if (!node_->IsSmoothed())
  405. {
  406. Matrix3x4 newTransform(parent->GetWorldTransform().Inverse() * Matrix3x4(previousPosition_.Lerp(currentPosition, t),
  407. previousRotation_.Slerp(currentRotation, t), Vector3::ONE));
  408. node_->SetTransform(newTransform.Translation(), newTransform.Rotation());
  409. }
  410. else
  411. {
  412. Matrix3x4 newTransform(parent->GetWorldTargetTransform().Inverse() * Matrix3x4(currentPosition, currentRotation,
  413. Vector3::ONE));
  414. node_->SetTransform(newTransform.Translation(), newTransform.Rotation());
  415. }
  416. }
  417. inPostStep_ = false;
  418. }
  419. void RigidBody::CreateBody()
  420. {
  421. if (!physicsWorld_)
  422. {
  423. LOGERROR("Null physics world, can not create body");
  424. return;
  425. }
  426. if (!body_)
  427. {
  428. body_ = dBodyCreate(physicsWorld_->GetWorld());
  429. // Set the user data pointer
  430. dBodySetData(body_, this);
  431. // Set initial transform. Use target position in case the node is smoothed
  432. const Vector3& position = node_->GetTargetPosition();
  433. Quaternion rotation(node_->GetTargetRotation());
  434. dBodySetPosition(body_, position.x_, position.y_, position.z_);
  435. dBodySetQuaternion(body_, rotation.GetData());
  436. previousPosition_ = position;
  437. previousRotation_ = rotation;
  438. // Associate geometries with the body
  439. PODVector<CollisionShape*> shapes;
  440. GetComponents<CollisionShape>(shapes);
  441. for (unsigned i = 0; i < shapes.Size(); ++i)
  442. shapes[i]->UpdateTransform();
  443. }
  444. UpdateMass();
  445. }
  446. void RigidBody::ReleaseBody()
  447. {
  448. if (!body_ || !physicsWorld_)
  449. return;
  450. PODVector<CollisionShape*> shapes;
  451. GetComponents<CollisionShape>(shapes);
  452. // First remove rigid body associations
  453. for (unsigned i = 0; i < shapes.Size(); ++i)
  454. {
  455. dGeomID geom = shapes[i]->GetGeometry();
  456. if (geom)
  457. dGeomSetBody(geom, 0);
  458. }
  459. dBodyDestroy(body_);
  460. body_ = 0;
  461. // Then update geometry transforms
  462. for (unsigned i = 0; i < shapes.Size(); ++i)
  463. shapes[i]->UpdateTransform();
  464. }
  465. void RigidBody::UpdateMass()
  466. {
  467. if (!body_)
  468. return;
  469. dMass mass;
  470. dMassSetZero(&mass);
  471. // Get all attached collision shapes to calculate the mass
  472. PODVector<CollisionShape*> shapes;
  473. GetComponents<CollisionShape>(shapes);
  474. float density = 1.0f;
  475. for (unsigned i = 0; i < shapes.Size(); ++i)
  476. {
  477. CollisionShape* shape = shapes[i];
  478. dMass subMass;
  479. Vector3 size = shape->GetSize() * node_->GetScale();
  480. Vector3 offset = shape->GetPosition() * node_->GetScale();
  481. switch (shape->GetShapeType())
  482. {
  483. case SHAPE_BOX:
  484. dMassSetBox(&subMass, density, size.x_, size.y_, size.z_);
  485. break;
  486. case SHAPE_SPHERE:
  487. dMassSetSphere(&subMass, density, 0.5f * size.x_);
  488. break;
  489. case SHAPE_CYLINDER:
  490. dMassSetCylinder(&subMass, density, massAxis_, 0.5f * size.x_, size.y_);
  491. break;
  492. case SHAPE_CAPSULE:
  493. dMassSetCapsule(&subMass, density, massAxis_, 0.5f * size.x_, Max(size.y_ - size.x_, 0.0f));
  494. break;
  495. case SHAPE_TRIANGLEMESH:
  496. dMassSetBox(&subMass, density, size.x_, size.y_, size.z_);
  497. break;
  498. }
  499. dMatrix3 rotMatrix;
  500. dRfromQ(rotMatrix, shape->GetRotation().GetData());
  501. dMassTranslate(&subMass, offset.x_, offset.y_, offset.z_);
  502. dMassRotate(&subMass, rotMatrix);
  503. dMassAdd(&mass, &subMass);
  504. }
  505. // If zero mass or no geometries, set kinematic mode
  506. if (mass.mass <= 0.0f)
  507. dBodySetKinematic(body_);
  508. else
  509. {
  510. // Translate final mass to center; anything else is unsupported in ODE
  511. dMassTranslate(&mass, -mass.c[0], -mass.c[1], -mass.c[2]);
  512. dMassAdjust(&mass, mass_);
  513. dBodySetMass(body_, &mass);
  514. }
  515. }