RigidBody.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  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 "DebugRenderer.h"
  25. #include "Log.h"
  26. #include "PhysicsWorld.h"
  27. #include "ReplicationUtils.h"
  28. #include "ResourceCache.h"
  29. #include "RigidBody.h"
  30. #include "StringUtils.h"
  31. #include "XMLElement.h"
  32. #include <ode/ode.h>
  33. #include <../ode/src/heightfield.h>
  34. #include <../ode/src/collision_std.h>
  35. #include "DebugNew.h"
  36. static const std::string modeNames[] =
  37. {
  38. "static",
  39. "dynamic",
  40. "kinematic"
  41. };
  42. RigidBody::RigidBody(PhysicsWorld* world, const std::string& name) :
  43. Node(NODE_RIGIDBODY, name),
  44. mWorld(world),
  45. mMode(PHYS_STATIC),
  46. mMass(1.0f),
  47. mFriction(0.5f),
  48. mBounce(0.0f),
  49. mCollisionGroup(M_MAX_UNSIGNED),
  50. mCollisionMask(M_MAX_UNSIGNED),
  51. mBody(0),
  52. mTempDisabled(false)
  53. {
  54. if (!mWorld)
  55. EXCEPTION("Null physics world for RigidBody");
  56. mWorld->addRigidBody(this);
  57. }
  58. RigidBody::~RigidBody()
  59. {
  60. removeGeometries();
  61. removeBody();
  62. mWorld->removeRigidBody(this);
  63. }
  64. void RigidBody::save(Serializer& dest)
  65. {
  66. // Write Component properties
  67. Component::save(dest);
  68. // Write transform
  69. dest.writeVector3(getPhysicsPosition());
  70. dest.writeQuaternion(getPhysicsRotation());
  71. dest.writeVector3(Node::getScale());
  72. // Write parent node reference (should be no parent)
  73. ComponentRef parentRef(mParent);
  74. parentRef.write(dest);
  75. // Write the RigidBody properties we store ourselves
  76. dest.writeUByte((unsigned char)mMode);
  77. dest.writeFloat(mMass);
  78. dest.writeFloat(mFriction);
  79. dest.writeFloat(mBounce);
  80. dest.writeStringHash(getResourceHash(mCollisionShape));
  81. dest.writeUInt(mCollisionGroup);
  82. dest.writeUInt(mCollisionMask);
  83. // Write the RigidBody properties contained within the body object
  84. dest.writeVector3(getLinearVelocity());
  85. dest.writeFloat(getLinearRestThreshold());
  86. dest.writeFloat(getLinearDampingThreshold());
  87. dest.writeFloat(getLinearDampingScale());
  88. dest.writeVector3(getAngularVelocity());
  89. dest.writeFloat(getAngularRestThreshold());
  90. dest.writeFloat(getAngularDampingThreshold());
  91. dest.writeFloat(getAngularDampingScale());
  92. dest.writeFloat(getAngularMaxVelocity());
  93. dest.writeBool(isActive());
  94. }
  95. void RigidBody::load(Deserializer& source, ResourceCache* cache)
  96. {
  97. // Read Component properties
  98. Component::load(source, cache);
  99. // Read transform
  100. Vector3 position = source.readVector3();
  101. Quaternion rotation = source.readQuaternion();
  102. setTransform(position, rotation);
  103. setScale(source.readVector3());
  104. // Read parent node reference
  105. mParentRef.read(source);
  106. // Read the RigidBody properties we store ourselves
  107. setMode((PhysicsMode)source.readUByte());
  108. setMass(source.readFloat());
  109. mFriction = source.readFloat();
  110. mBounce = source.readFloat();
  111. setCollisionShape(cache->getResource<CollisionShape>(source.readStringHash()));
  112. setCollisionGroup(source.readUInt());
  113. setCollisionMask(source.readUInt());
  114. // Read the RigidBody properties contained within the body object
  115. setLinearVelocity(source.readVector3());
  116. setLinearRestThreshold(source.readFloat());
  117. float threshold = source.readFloat();
  118. float scale = source.readFloat();
  119. setLinearDamping(threshold, scale);
  120. setAngularVelocity(source.readVector3());
  121. setAngularRestThreshold(source.readFloat());
  122. threshold = source.readFloat();
  123. scale = source.readFloat();
  124. setAngularDamping(threshold, scale);
  125. setAngularMaxVelocity(source.readFloat());
  126. setActive(source.readBool());
  127. resetForces();
  128. }
  129. void RigidBody::saveXML(XMLElement& dest)
  130. {
  131. // Write Component properties
  132. Component::saveXML(dest);
  133. // Write transform
  134. XMLElement transformElem = dest.createChildElement("transform");
  135. transformElem.setVector3("pos", getPosition());
  136. transformElem.setQuaternion("rot", getRotation());
  137. transformElem.setVector3("scale", getScale());
  138. // Write parent node reference
  139. ComponentRef parentRef(mParent, true);
  140. if (parentRef.mEntityID)
  141. {
  142. XMLElement parentElem = dest.createChildElement("parent");
  143. parentRef.writeXML(parentElem);
  144. }
  145. // Write the RigidBody properties
  146. XMLElement bodyElem = dest.createChildElement("body");
  147. bodyElem.setString("mode", modeNames[mMode]);
  148. bodyElem.setFloat("mass", mMass);
  149. bodyElem.setFloat("friction", mFriction);
  150. bodyElem.setFloat("bounce", mBounce);
  151. bodyElem.setBool("active", isActive());
  152. XMLElement collisionElem = dest.createChildElement("collision");
  153. collisionElem.setString("shape", getResourceName(mCollisionShape));
  154. collisionElem.setInt("group", mCollisionGroup);
  155. collisionElem.setInt("mask", mCollisionMask);
  156. XMLElement linearElem = dest.createChildElement("linear");
  157. linearElem.setVector3("velocity", getLinearVelocity());
  158. linearElem.setFloat("restthreshold", getLinearRestThreshold());
  159. linearElem.setFloat("dampingthreshold", getLinearDampingThreshold());
  160. linearElem.setFloat("dampingscale", getLinearDampingScale());
  161. XMLElement angularElem = dest.createChildElement("angular");
  162. angularElem.setVector3("velocity", getAngularVelocity());
  163. angularElem.setFloat("restthreshold", getAngularRestThreshold());
  164. angularElem.setFloat("dampingthreshold", getAngularDampingThreshold());
  165. angularElem.setFloat("dampingscale", getAngularDampingScale());
  166. angularElem.setFloat("maxvelocity", getAngularMaxVelocity());
  167. }
  168. void RigidBody::loadXML(const XMLElement& source, ResourceCache* cache)
  169. {
  170. // Read Component properties
  171. Component::loadXML(source, cache);
  172. // Read transform
  173. XMLElement transformElem = source.getChildElement("transform");
  174. Vector3 position = transformElem.getVector3("pos");
  175. Quaternion rotation = transformElem.getQuaternion("rot");
  176. setTransform(position, rotation);
  177. setScale(transformElem.getVector3("scale"));
  178. // Read parent node reference
  179. if (source.hasChildElement("parent"))
  180. {
  181. XMLElement parentElem = source.getChildElement("parent");
  182. mParentRef.readXML(parentElem);
  183. }
  184. else
  185. mParentRef = ComponentRef();
  186. // Read the RigidBody properties we store ourselves
  187. XMLElement bodyElem = source.getChildElement("body");
  188. setMode((PhysicsMode)getIndexFromStringList(bodyElem.getStringLower("mode"), modeNames, 3, 0));
  189. setMass(bodyElem.getFloat("mass"));
  190. mFriction = bodyElem.getFloat("friction");
  191. mBounce = bodyElem.getFloat("bounce");
  192. XMLElement collisionElem = source.getChildElement("collision");
  193. setCollisionShape(cache->getResource<CollisionShape>(collisionElem.getString("shape")));
  194. setCollisionGroup(collisionElem.getInt("group"));
  195. setCollisionMask(collisionElem.getInt("mask"));
  196. // Read the RigidBody properties contained within the body object
  197. if (source.hasChildElement("linear"))
  198. {
  199. XMLElement linearElem = source.getChildElement("linear");
  200. setLinearVelocity(linearElem.getVector3("velocity"));
  201. setLinearRestThreshold(linearElem.getFloat("restthreshold"));
  202. setLinearDamping(linearElem.getFloat("dampingthreshold"), linearElem.getFloat("dampingscale"));
  203. }
  204. if (source.hasChildElement("angular"))
  205. {
  206. XMLElement angularElem = source.getChildElement("angular");
  207. setAngularVelocity(angularElem.getVector3("velocity"));
  208. setAngularRestThreshold(angularElem.getFloat("restthreshold"));
  209. setAngularDamping(angularElem.getFloat("dampingthreshold"), angularElem.getFloat("dampingscale"));
  210. setAngularMaxVelocity(angularElem.getFloat("maxvelocity"));
  211. }
  212. setActive(bodyElem.getBool("active"));
  213. resetForces();
  214. }
  215. bool RigidBody::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deserializer& baseRevision, const NetUpdateInfo& info)
  216. {
  217. Vector3 position = getPhysicsPosition();
  218. Quaternion rotation = getPhysicsRotation();
  219. Vector3 scale = getScale();
  220. ComponentRef parentRef(mParent);
  221. // Build bitmask of changed properties
  222. unsigned char bits = 0;
  223. unsigned char bits2 = 0;
  224. checkVector3(position, Vector3::sZero, baseRevision, bits, 1);
  225. checkQuaternion(rotation, Quaternion::sIdentity, baseRevision, bits, 2);
  226. checkVector3(scale, Vector3::sUnity, baseRevision, bits, 4);
  227. checkComponentRef(parentRef, ComponentRef(), baseRevision, bits, 8);
  228. checkUByte((unsigned char)mMode, (unsigned char)PHYS_STATIC, baseRevision, bits, 16);
  229. checkFloat(mMass, 1.0f, baseRevision, bits, 32);
  230. checkVector3(getLinearVelocity(), Vector3::sZero, baseRevision, bits, 64);
  231. checkVector3(getAngularVelocity(), Vector3::sZero, baseRevision, bits, 128);
  232. checkStringHash(getResourceHash(mCollisionShape), baseRevision, bits2, 1);
  233. checkUInt(mCollisionGroup, M_MAX_UNSIGNED, baseRevision, bits2, 2);
  234. checkUInt(mCollisionMask, M_MAX_UNSIGNED, baseRevision, bits2, 2);
  235. checkFloat(mFriction, 0.5f, baseRevision, bits, 4);
  236. checkFloat(mBounce, 0.0f, baseRevision, bits, 8);
  237. checkFloat(getLinearRestThreshold(), 0.01f, baseRevision, bits2, 16);
  238. checkFloat(getLinearDampingThreshold(), 0.01f, baseRevision, bits2, 16);
  239. checkFloat(getLinearDampingScale(), 0.0f, baseRevision, bits2, 16);
  240. checkFloat(getAngularRestThreshold(), 0.01f, baseRevision, bits2, 32);
  241. checkFloat(getAngularDampingThreshold(), 0.01f, baseRevision, bits2, 32);
  242. checkFloat(getAngularDampingScale(), 0.0f, baseRevision, bits2, 32);
  243. checkFloat(getAngularMaxVelocity(), M_INFINITY, baseRevision, bits2, 64);
  244. // If body is active and dynamic, keep sending the physics state
  245. // This is because clients will extrapolate, and need to be snapped to the right state
  246. if ((mMode == PHYS_DYNAMIC) && (isActive()))
  247. bits |= (1 | 2 | 64 | 128);
  248. // Remove unnecessary properties
  249. if (mMode == PHYS_STATIC)
  250. {
  251. bits &= ~(64 | 128);
  252. bits2 &= ~(16 | 32 | 64);
  253. }
  254. if (getAngularMaxVelocity() == 0.0f)
  255. bits &= ~128;
  256. // Update replication state fully, and network stream by delta
  257. dest.writeUByte(bits);
  258. dest.writeUByte(bits2);
  259. writeVector3Delta(position, dest, destRevision, bits & 1);
  260. writePackedQuaternionDelta(rotation, dest, destRevision, bits & 2);
  261. writeVector3Delta(scale, dest, destRevision, bits & 4);
  262. writeComponentRefDelta(parentRef, dest, destRevision, bits & 8);
  263. writeUByteDelta((unsigned char)mMode, dest, destRevision, bits & 16);
  264. writeFloatDelta(mMass, dest, destRevision, bits & 32);
  265. writeVector3Delta(getLinearVelocity(), dest, destRevision, bits & 64);
  266. writePackedVector3Delta(getAngularVelocity(), mWorld->getAngularMaxNetVelocity(), dest, destRevision, bits & 128);
  267. writeStringHashDelta(getResourceHash(mCollisionShape), dest, destRevision, bits2 & 1);
  268. writeUIntDelta(mCollisionGroup, dest, destRevision, bits2 & 2);
  269. writeUIntDelta(mCollisionMask, dest, destRevision, bits2 & 2);
  270. writeFloatDelta(mFriction, dest, destRevision, bits2 & 4);
  271. writeFloatDelta(mBounce, dest, destRevision, bits2 & 8);
  272. writeFloatDelta(getLinearRestThreshold(), dest, destRevision, bits2 & 16);
  273. writeFloatDelta(getLinearDampingThreshold(), dest, destRevision, bits2 & 16);
  274. writeFloatDelta(getLinearDampingScale(), dest, destRevision, bits2 & 16);
  275. writeFloatDelta(getAngularRestThreshold(), dest, destRevision, bits2 & 32);
  276. writeFloatDelta(getAngularDampingThreshold(), dest, destRevision, bits2 & 32);
  277. writeFloatDelta(getAngularDampingScale(), dest, destRevision, bits2 & 32);
  278. writeFloatDelta(getAngularMaxVelocity(), dest, destRevision, bits2 & 64);
  279. return (bits | bits2) != 0;
  280. }
  281. void RigidBody::readNetUpdate(Deserializer& source, ResourceCache* cache, const NetUpdateInfo& info)
  282. {
  283. unsigned char bits = source.readUByte();
  284. unsigned char bits2 = source.readUByte();
  285. if (bits & 1)
  286. setPosition(source.readVector3());
  287. if (bits & 2)
  288. setRotation(source.readPackedQuaternion());
  289. if (bits & 4)
  290. setScale(source.readVector3());
  291. if (bits & 8)
  292. mParentRef.readPacked(source);
  293. if (bits & 16)
  294. setMode((PhysicsMode)source.readUByte());
  295. if (bits & 32)
  296. setMass(source.readFloat());
  297. if (bits & 64)
  298. setLinearVelocity(source.readVector3());
  299. if (bits & 128)
  300. setAngularVelocity(source.readPackedVector3(mWorld->getAngularMaxNetVelocity()));
  301. if (bits2 & 1)
  302. setCollisionShape(cache->getResource<CollisionShape>(source.readStringHash()));
  303. if (bits2 & 2)
  304. {
  305. setCollisionGroup(source.readUInt());
  306. setCollisionMask(source.readUInt());
  307. }
  308. if (bits2 & 4)
  309. mFriction = source.readFloat();
  310. if (bits2 & 8)
  311. mBounce = source.readFloat();
  312. if (bits2 & 16)
  313. {
  314. setLinearRestThreshold(source.readFloat());
  315. float threshold = source.readFloat();
  316. float scale = source.readFloat();
  317. setLinearDamping(threshold, scale);
  318. }
  319. if (bits2 & 32)
  320. {
  321. setAngularRestThreshold(source.readFloat());
  322. float threshold = source.readFloat();
  323. float scale = source.readFloat();
  324. setAngularDamping(threshold, scale);
  325. }
  326. if (bits2 & 64)
  327. setAngularMaxVelocity(source.readFloat());
  328. resetForces();
  329. if (bits & (1 | 2 | 64 | 128))
  330. {
  331. // If the last network update was stationary, forcibly disable the body so it will not start drifting
  332. bool active = (getLinearVelocity().getLengthFast() > getLinearRestThreshold()) ||
  333. (getAngularVelocity().getLengthFast() > getAngularRestThreshold());
  334. if (!active)
  335. {
  336. setLinearVelocity(Vector3::sZero);
  337. setAngularVelocity(Vector3::sZero);
  338. setActive(false);
  339. }
  340. }
  341. }
  342. void RigidBody::interpolate(bool snapToEnd)
  343. {
  344. // Set the current physics position/rotation as the new interpolation target
  345. Vector3 position = getPhysicsPosition();
  346. Quaternion rotation = getPhysicsRotation();
  347. if ((isActive()) || (position != mInterpolationPosition) || (rotation != mInterpolationRotation))
  348. {
  349. mInterpolationPosition = position;
  350. mInterpolationRotation = rotation;
  351. mInterpolationFlags |= (INTERP_POS | INTERP_ROT);
  352. }
  353. Node::interpolate(snapToEnd);
  354. }
  355. void RigidBody::getResourceRefs(std::vector<Resource*>& dest)
  356. {
  357. if (mCollisionShape)
  358. dest.push_back(mCollisionShape);
  359. }
  360. void RigidBody::setMode(PhysicsMode mode)
  361. {
  362. mMode = mode;
  363. switch (mMode)
  364. {
  365. case PHYS_STATIC:
  366. removeBody();
  367. break;
  368. case PHYS_DYNAMIC:
  369. case PHYS_KINEMATIC:
  370. createBody();
  371. break;
  372. }
  373. }
  374. void RigidBody::setMass(float mass)
  375. {
  376. // Zero mass causes ODE assert on dynamic body. So rather set it very small
  377. mMass = max(mass, M_EPSILON);
  378. updateMass();
  379. }
  380. void RigidBody::setFriction(float friction)
  381. {
  382. mFriction = max(friction, 0.0f);
  383. }
  384. void RigidBody::setBounce(float bounce)
  385. {
  386. mBounce = max(bounce, 0.0f);
  387. }
  388. void RigidBody::setCollisionShape(CollisionShape* shape)
  389. {
  390. if (shape == mCollisionShape)
  391. return;
  392. mCollisionShape = shape;
  393. updateGeometries();
  394. }
  395. void RigidBody::setCollisionGroup(unsigned group)
  396. {
  397. mCollisionGroup = group;
  398. for (unsigned i = 0; i < mGeometries.size(); ++i)
  399. dGeomSetCategoryBits(mGeometries[i], group);
  400. }
  401. void RigidBody::setCollisionMask(unsigned mask)
  402. {
  403. mCollisionMask = mask;
  404. for (unsigned i = 0; i < mGeometries.size(); ++i)
  405. dGeomSetCollideBits(mGeometries[i], mask);
  406. }
  407. void RigidBody::setPosition(const Vector3& position)
  408. {
  409. // For clients all physics motion is smoothed, so do not set transform directly if already have a body
  410. if ((!isProxy()) || (!mBody))
  411. Node::setPosition(position);
  412. if (mBody)
  413. {
  414. if (getPhysicsPosition() != position)
  415. {
  416. setActive(true);
  417. dBodySetPosition(mBody, position.mX, position.mY, position.mZ);
  418. }
  419. mPreviousPosition = position;
  420. }
  421. else
  422. {
  423. // If no body, must set the geometry transforms manually
  424. if (mCollisionShape)
  425. mCollisionShape->setBodyAndTransforms(mGeometries, 0, Node::getPosition(), Node::getRotation(), Node::getScale());
  426. }
  427. }
  428. void RigidBody::setRotation(const Quaternion& rotation)
  429. {
  430. // For clients all physics motion is smoothed, so do not set transform directly if already have a body
  431. if ((!isProxy()) || (!mBody))
  432. Node::setRotation(rotation);
  433. if (mBody)
  434. {
  435. if (getPhysicsRotation() != rotation)
  436. {
  437. // As a convention, if the body has angular velocity disabled (player controllers and such)
  438. // setting the rotation only will not cause activation
  439. if (getAngularMaxVelocity() > 0.0f)
  440. setActive(true);
  441. dBodySetQuaternion(mBody, rotation.getData());
  442. }
  443. mPreviousRotation = rotation;
  444. }
  445. else
  446. {
  447. // If no body, must set the geometry transforms manually
  448. if (mCollisionShape)
  449. mCollisionShape->setBodyAndTransforms(mGeometries, 0, Node::getPosition(), Node::getRotation(), Node::getScale());
  450. }
  451. }
  452. void RigidBody::setScale(float scale)
  453. {
  454. Vector3 scaleVec(scale, scale, scale);
  455. if (Node::getScale() == scaleVec)
  456. return;
  457. Node::setScale(scale);
  458. updateGeometries();
  459. }
  460. void RigidBody::setScale(const Vector3& scale)
  461. {
  462. if (Node::getScale() == scale)
  463. return;
  464. Node::setScale(scale);
  465. updateGeometries();
  466. }
  467. void RigidBody::setTransform(const Vector3& position, const Quaternion& rotation)
  468. {
  469. // For clients all physics motion is smoothed, so do not set transform directly if already have a body
  470. if ((!isProxy()) || (!mBody))
  471. {
  472. Node::setPosition(position);
  473. Node::setRotation(rotation);
  474. }
  475. if (mBody)
  476. {
  477. if ((getPhysicsPosition() != position) || (getPhysicsRotation() != rotation))
  478. {
  479. setActive(true);
  480. dBodySetPosition(mBody, position.mX, position.mY, position.mZ);
  481. dBodySetQuaternion(mBody, rotation.getData());
  482. }
  483. mPreviousPosition = position;
  484. mPreviousRotation = rotation;
  485. }
  486. else
  487. {
  488. // If no body, must set the geometry transforms manually
  489. if (mCollisionShape)
  490. mCollisionShape->setBodyAndTransforms(mGeometries, 0, Node::getPosition(), Node::getRotation(), Node::getScale());
  491. }
  492. }
  493. void RigidBody::setTransform(const Vector3& position, const Quaternion& rotation, float scale)
  494. {
  495. setTransform(position, rotation);
  496. setScale(scale);
  497. }
  498. void RigidBody::setTransform(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
  499. {
  500. setTransform(position, rotation);
  501. setScale(scale);
  502. }
  503. void RigidBody::scale(float scale)
  504. {
  505. if (scale == 1.0f)
  506. return;
  507. Node::scale(scale);
  508. updateGeometries();
  509. }
  510. void RigidBody::scale(const Vector3& scale)
  511. {
  512. if (scale == Vector3::sUnity)
  513. return;
  514. Node::scale(scale);
  515. updateGeometries();
  516. }
  517. void RigidBody::setLinearVelocity(const Vector3& velocity)
  518. {
  519. if (mBody)
  520. dBodySetLinearVel(mBody, velocity.mX, velocity.mY, velocity.mZ);
  521. }
  522. void RigidBody::setLinearRestThreshold(float threshold)
  523. {
  524. if (mBody)
  525. dBodySetAutoDisableLinearThreshold(mBody, threshold);
  526. }
  527. void RigidBody::setLinearDamping(float threshold, float scale)
  528. {
  529. if (mBody)
  530. {
  531. dBodySetLinearDampingThreshold(mBody, threshold);
  532. dBodySetLinearDamping(mBody, scale);
  533. }
  534. }
  535. void RigidBody::setAngularVelocity(const Vector3& velocity)
  536. {
  537. if (mBody)
  538. dBodySetAngularVel(mBody, velocity.mX, velocity.mY, velocity.mZ);
  539. }
  540. void RigidBody::setAngularRestThreshold(float threshold)
  541. {
  542. if (mBody)
  543. dBodySetAutoDisableAngularThreshold(mBody, threshold);
  544. }
  545. void RigidBody::setAngularDamping(float threshold, float scale)
  546. {
  547. if (mBody)
  548. {
  549. dBodySetAngularDampingThreshold(mBody, threshold);
  550. dBodySetAngularDamping(mBody, scale);
  551. }
  552. }
  553. void RigidBody::setAngularMaxVelocity(float velocity)
  554. {
  555. if (mBody)
  556. dBodySetMaxAngularSpeed(mBody, velocity);
  557. }
  558. void RigidBody::setActive(bool active)
  559. {
  560. if (mTempDisabled)
  561. active = false;
  562. if (mBody)
  563. {
  564. if ((active) && (!dBodyIsEnabled(mBody)))
  565. dBodyEnable(mBody);
  566. else if ((!active) && (dBodyIsEnabled(mBody)))
  567. dBodyDisable(mBody);
  568. }
  569. }
  570. void RigidBody::applyForce(const Vector3& force)
  571. {
  572. if (force == Vector3::sZero)
  573. return;
  574. if (mBody)
  575. {
  576. setActive(true);
  577. dBodyAddForce(mBody, force.mX, force.mY, force.mZ);
  578. }
  579. }
  580. void RigidBody::applyForceAtPosition(const Vector3& force, const Vector3& position)
  581. {
  582. if (force == Vector3::sZero)
  583. return;
  584. if (mBody)
  585. {
  586. setActive(true);
  587. dBodyAddForceAtRelPos(mBody, force.mX, force.mY, force.mZ, position.mX, position.mY, position.mZ);
  588. }
  589. }
  590. void RigidBody::applyTorque(const Vector3& torque)
  591. {
  592. if (torque == Vector3::sZero)
  593. return;
  594. if (mBody)
  595. {
  596. setActive(true);
  597. dBodyAddTorque(mBody, torque.mX, torque.mY, torque.mZ);
  598. }
  599. }
  600. void RigidBody::resetForces()
  601. {
  602. if (mBody)
  603. {
  604. dBodySetForce(mBody, 0.0f, 0.0f, 0.0f);
  605. dBodySetTorque(mBody, 0.0f, 0.0f, 0.0f);
  606. }
  607. }
  608. Vector3 RigidBody::getPhysicsPosition() const
  609. {
  610. if (mBody)
  611. {
  612. const dReal* pos = dBodyGetPosition(mBody);
  613. return Vector3(pos[0], pos[1], pos[2]);
  614. }
  615. else return Node::getPosition();
  616. }
  617. Quaternion RigidBody::getPhysicsRotation() const
  618. {
  619. if (mBody)
  620. {
  621. const dReal* quat = dBodyGetQuaternion(mBody);
  622. return Quaternion(quat[0], quat[1], quat[2], quat[3]);
  623. }
  624. else return Node::getRotation();
  625. }
  626. Vector3 RigidBody::getLinearVelocity() const
  627. {
  628. if (mBody)
  629. {
  630. const dReal* vel = dBodyGetLinearVel(mBody);
  631. return Vector3(vel[0], vel[1], vel[2]);
  632. }
  633. else
  634. return Vector3::sZero;
  635. }
  636. float RigidBody::getLinearRestThreshold() const
  637. {
  638. if (mBody)
  639. return dBodyGetAutoDisableLinearThreshold(mBody);
  640. else
  641. return 0.0f;
  642. }
  643. float RigidBody::getLinearDampingThreshold() const
  644. {
  645. if (mBody)
  646. return dBodyGetLinearDampingThreshold(mBody);
  647. else
  648. return 0.0f;
  649. }
  650. float RigidBody::getLinearDampingScale() const
  651. {
  652. if (mBody)
  653. return dBodyGetLinearDamping(mBody);
  654. else
  655. return 0.0f;
  656. }
  657. Vector3 RigidBody::getAngularVelocity() const
  658. {
  659. if (mBody)
  660. {
  661. const dReal* vel = dBodyGetAngularVel(mBody);
  662. return Vector3(vel[0], vel[1], vel[2]);
  663. }
  664. else
  665. return Vector3::sZero;
  666. }
  667. float RigidBody::getAngularRestThreshold() const
  668. {
  669. if (mBody)
  670. return dBodyGetAutoDisableAngularThreshold(mBody);
  671. else
  672. return 0.0f;
  673. }
  674. float RigidBody::getAngularDampingThreshold() const
  675. {
  676. if (mBody)
  677. return dBodyGetAngularDampingThreshold(mBody);
  678. else
  679. return 0.0f;
  680. }
  681. float RigidBody::getAngularDampingScale() const
  682. {
  683. if (mBody)
  684. return dBodyGetAngularDamping(mBody);
  685. else
  686. return 0.0f;
  687. }
  688. float RigidBody::getAngularMaxVelocity() const
  689. {
  690. if (mBody)
  691. return dBodyGetMaxAngularSpeed(mBody);
  692. else
  693. return 0.0f;
  694. }
  695. bool RigidBody::isActive() const
  696. {
  697. if (mBody)
  698. return dBodyIsEnabled(mBody) != 0;
  699. else
  700. return false;
  701. }
  702. void RigidBody::drawDebugGeometry(DebugRenderer* debug)
  703. {
  704. Color color;
  705. if (!isActive())
  706. color = Color(0.0f, 1.0f, 0.0f);
  707. for (unsigned i = 0; i < mGeometries.size(); ++i)
  708. {
  709. dGeomID geom = mGeometries[i];
  710. const dReal* pos = dGeomGetPosition(geom);
  711. dQuaternion quat;
  712. dGeomGetQuaternion(geom, quat);
  713. Matrix4x3 transform;
  714. transform.define(Vector3(pos[0], pos[1], pos[2]), Quaternion(quat[0], quat[1], quat[2], quat[3]), 1.0f);
  715. switch (dGeomGetClass(geom))
  716. {
  717. case dSphereClass:
  718. {
  719. float radius = dGeomSphereGetRadius(geom);
  720. for (unsigned i = 0; i < 360; i += 45)
  721. {
  722. unsigned j = i + 45;
  723. float a = radius * sinf(i * M_DEGTORAD);
  724. float b = radius * cosf(i * M_DEGTORAD);
  725. float c = radius * sinf(j * M_DEGTORAD);
  726. float d = radius * cosf(j * M_DEGTORAD);
  727. Vector3 start, end;
  728. start = transform * Vector3(a, b, 0.0f);
  729. end = transform * Vector3(c, d, 0.0f);
  730. debug->addLine(start, end, color);
  731. start = transform * Vector3(a, 0.0f, b);
  732. end = transform * Vector3(c, 0.0f, d);
  733. debug->addLine(start, end, color);
  734. start = transform * Vector3(0.0f, a, b);
  735. end = transform * Vector3(0.0f, c, d);
  736. debug->addLine(start, end, color);
  737. }
  738. }
  739. break;
  740. case dBoxClass:
  741. {
  742. dVector3 size;
  743. dGeomBoxGetLengths(geom, size);
  744. BoundingBox box(0.5f * Vector3(size[0], size[1], size[2]), 0.5f * Vector3(-size[0], -size[1], -size[2]));
  745. debug->addBoundingBox(box, transform, color);
  746. }
  747. break;
  748. case dCapsuleClass:
  749. {
  750. float radius, length;
  751. dGeomCapsuleGetParams(geom, &radius, &length);
  752. for (unsigned i = 0; i < 360; i += 45)
  753. {
  754. unsigned j = i + 45;
  755. float a = radius * sinf(i * M_DEGTORAD);
  756. float b = radius * cosf(i * M_DEGTORAD);
  757. float c = radius * sinf(j * M_DEGTORAD);
  758. float d = radius * cosf(j * M_DEGTORAD);
  759. Vector3 start, end;
  760. start = transform * Vector3(a, b, 0.5f * length);
  761. end = transform * Vector3(c, d, 0.5f * length);
  762. debug->addLine(start, end, color);
  763. start = transform * Vector3(a, b, -0.5f * length);
  764. end = transform * Vector3(c, d, -0.5f * length);
  765. debug->addLine(start, end, color);
  766. if (!(i & 1))
  767. {
  768. start = transform * Vector3(a, b, 0.5f * length);
  769. end = transform * Vector3(a, b, -0.5f * length);
  770. debug->addLine(start, end, color);
  771. }
  772. if (b > -M_EPSILON)
  773. {
  774. start = transform * Vector3(a, 0.0f, b + 0.5f * length);
  775. end = transform * Vector3(c, 0.0f, d + 0.5f * length);
  776. debug->addLine(start, end, color);
  777. start = transform * Vector3(0.0f, a, b + 0.5f * length);
  778. end = transform * Vector3(0.0f, c, d + 0.5f * length);
  779. debug->addLine(start, end, color);
  780. start = transform * Vector3(a, 0.0f, -b - 0.5f * length);
  781. end = transform * Vector3(c, 0.0f, -d - 0.5f * length);
  782. debug->addLine(start, end, color);
  783. start = transform * Vector3(0.0f, a, -b - 0.5f * length);
  784. end = transform * Vector3(0.0f, c, -d - 0.5f * length);
  785. debug->addLine(start, end, color);
  786. }
  787. }
  788. }
  789. break;
  790. case dCylinderClass:
  791. {
  792. float radius, length;
  793. dGeomCylinderGetParams(geom, &radius, &length);
  794. for (unsigned i = 0; i < 360; i += 45)
  795. {
  796. unsigned j = i + 45;
  797. float a = radius * sinf(i * M_DEGTORAD);
  798. float b = radius * cosf(i * M_DEGTORAD);
  799. float c = radius * sinf(j * M_DEGTORAD);
  800. float d = radius * cosf(j * M_DEGTORAD);
  801. Vector3 start, end;
  802. start = transform * Vector3(a, b, 0.5f * length);
  803. end = transform * Vector3(c, d, 0.5f * length);
  804. debug->addLine(start, end, color);
  805. start = transform * Vector3(a, b, -0.5f * length);
  806. end = transform * Vector3(c, d, -0.5f * length);
  807. debug->addLine(start, end, color);
  808. start = transform * Vector3(a, b, 0.5f * length);
  809. end = transform * Vector3(a, b, -0.5f * length);
  810. debug->addLine(start, end, color);
  811. }
  812. }
  813. break;
  814. case dTriMeshClass:
  815. {
  816. unsigned numTriangles = dGeomTriMeshGetTriangleCount(geom);
  817. for (unsigned i = 0; i < numTriangles; ++i)
  818. {
  819. dVector3 v0;
  820. dVector3 v1;
  821. dVector3 v2;
  822. dGeomTriMeshGetTriangle(geom, i, &v0, &v1, &v2);
  823. Vector3 a(v0[0], v0[1], v0[2]);
  824. Vector3 b(v1[0], v1[1], v1[2]);
  825. Vector3 c(v2[0], v2[1], v2[2]);
  826. debug->addLine(a, b, color);
  827. debug->addLine(b, c, color);
  828. debug->addLine(c, a, color);
  829. }
  830. }
  831. break;
  832. case dHeightfieldClass:
  833. {
  834. dHeightfieldDataID heightData = dGeomHeightfieldGetHeightfieldData(geom);
  835. unsigned xPoints = heightData->m_nWidthSamples;
  836. unsigned zPoints = heightData->m_nDepthSamples;
  837. float xWidth = heightData->m_fWidth;
  838. float zWidth = heightData->m_fDepth;
  839. float xBase = -0.5f * xWidth;
  840. float zBase = -0.5f * zWidth;
  841. float xSpacing = xWidth / (xPoints - 1);
  842. float zSpacing = zWidth / (zPoints - 1);
  843. float* heights = (float*)heightData->m_pHeightData;
  844. for (unsigned z = 0; z < zPoints - 1; ++z)
  845. {
  846. for (unsigned x = 0; x < xPoints - 1; ++x)
  847. {
  848. Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
  849. Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
  850. Vector3 c = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
  851. debug->addLine(a, b, color);
  852. debug->addLine(a, c, color);
  853. }
  854. }
  855. for (unsigned z = 0; z < zPoints - 1; ++z)
  856. {
  857. unsigned x = xPoints - 1;
  858. Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
  859. Vector3 b = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
  860. debug->addLine(a, b, color);
  861. }
  862. for (unsigned x = 0; x < xPoints - 1; ++x)
  863. {
  864. unsigned z = zPoints - 1;
  865. Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
  866. Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
  867. debug->addLine(a, b, color);
  868. }
  869. }
  870. break;
  871. }
  872. }
  873. }
  874. void RigidBody::preStep()
  875. {
  876. if (mTempDisabled)
  877. return;
  878. // Store the previous position for interpolation
  879. if (mBody)
  880. {
  881. const dReal* pos = dBodyGetPosition(mBody);
  882. const dReal* quat = dBodyGetQuaternion(mBody);
  883. mPreviousPosition = Vector3(pos[0], pos[1], pos[2]);
  884. mPreviousRotation = Quaternion(quat[0], quat[1], quat[2], quat[3]);
  885. }
  886. }
  887. void RigidBody::postStep(float t)
  888. {
  889. if (mTempDisabled)
  890. return;
  891. // If no body (static object), or body is inactive, no rendering interpolation necessary
  892. // Network proxies also use different kind of rendering interpolation (smoothing)
  893. if ((isProxy()) || (!mBody) || (!dBodyIsEnabled(mBody)))
  894. return;
  895. const dReal* pos = dBodyGetPosition(mBody);
  896. const dReal* quat = dBodyGetQuaternion(mBody);
  897. Vector3 currentPosition(pos[0], pos[1], pos[2]);
  898. Quaternion currentRotation(quat[0], quat[1], quat[2], quat[3]);
  899. Node::setPosition(mPreviousPosition.lerp(currentPosition, t));
  900. Node::setRotation(mPreviousRotation.slerp(currentRotation, t));
  901. }
  902. void RigidBody::createBody()
  903. {
  904. if (!mBody)
  905. {
  906. mBody = dBodyCreate(mWorld->getWorld());
  907. dBodySetGyroscopicMode(mBody, 0);
  908. // Set the user data pointer
  909. dBodySetData(mBody, this);
  910. // Set rendering transform as the initial transform
  911. const Vector3& position = Node::getPosition();
  912. const Quaternion& rotation = Node::getRotation();
  913. dBodySetPosition(mBody, position.mX, position.mY, position.mZ);
  914. dBodySetQuaternion(mBody, rotation.getData());
  915. mPreviousPosition = position;
  916. mPreviousRotation = rotation;
  917. // Associate geometries with the body
  918. if (mCollisionShape)
  919. mCollisionShape->setBodyAndTransforms(mGeometries, mBody, Node::getPosition(), Node::getRotation(), Node::getScale());
  920. }
  921. if (mMode == PHYS_KINEMATIC)
  922. dBodySetKinematic(mBody);
  923. else
  924. dBodySetDynamic(mBody);
  925. }
  926. void RigidBody::removeBody()
  927. {
  928. if (!mBody)
  929. return;
  930. // Reset geometries' body association and transforms
  931. if (mCollisionShape)
  932. mCollisionShape->setBodyAndTransforms(mGeometries, 0, Node::getPosition(), Node::getRotation(), Node::getScale());
  933. if (mBody)
  934. {
  935. dBodyDestroy(mBody);
  936. mBody = 0;
  937. }
  938. }
  939. void RigidBody::removeGeometries()
  940. {
  941. for (unsigned i = 0; i < mGeometries.size(); ++i)
  942. dGeomDestroy(mGeometries[i]);
  943. mGeometries.clear();
  944. mUniqueGeometryDatas.clear();
  945. CollisionShape::cleanupCaches();
  946. }
  947. void RigidBody::updateGeometries()
  948. {
  949. removeGeometries();
  950. if (!mCollisionShape)
  951. return;
  952. mCollisionShape->createGeometries(mGeometries, mUniqueGeometryDatas, mWorld->getSpace(), Node::getScale());
  953. mCollisionShape->setBodyAndTransforms(mGeometries, mBody, Node::getPosition(), Node::getRotation(), Node::getScale());
  954. for (unsigned i = 0; i < mGeometries.size(); ++i)
  955. {
  956. // Set the user data pointer & collision bits
  957. dGeomSetData(mGeometries[i], this);
  958. dGeomSetCategoryBits(mGeometries[i], mCollisionGroup);
  959. dGeomSetCollideBits(mGeometries[i], mCollisionMask);
  960. if (mTempDisabled)
  961. dGeomDisable(mGeometries[i]);
  962. }
  963. updateMass();
  964. }
  965. void RigidBody::updateMass()
  966. {
  967. if ((!mBody) || (!mCollisionShape) || (mMode != PHYS_DYNAMIC))
  968. return;
  969. dMass mass;
  970. dMassSetZero(&mass);
  971. mCollisionShape->calculateMass(&mass, mGeometries, 1.0f, Node::getScale());
  972. dMassAdjust(&mass, mMass);
  973. dBodySetMass(mBody, &mass);
  974. }
  975. void RigidBody::setTempDisabled(bool disable)
  976. {
  977. if (disable == mTempDisabled)
  978. return;
  979. mTempDisabled = disable;
  980. if (!mTempDisabled)
  981. {
  982. for (unsigned i = 0; i < mGeometries.size(); ++i)
  983. dGeomEnable(mGeometries[i]);
  984. setActive(mSavedActiveFlag);
  985. setLinearVelocity(mSavedLinearVelocity);
  986. setAngularVelocity(mSavedAngularVelocity);
  987. resetForces();
  988. }
  989. else
  990. {
  991. for (unsigned i = 0; i < mGeometries.size(); ++i)
  992. dGeomDisable(mGeometries[i]);
  993. mSavedActiveFlag = isActive();
  994. mSavedLinearVelocity = getLinearVelocity();
  995. mSavedAngularVelocity = getAngularVelocity();
  996. setActive(false);
  997. }
  998. }