PhysicsVehicleWheel.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #include "Base.h"
  2. #include "Node.h"
  3. #include "PhysicsVehicle.h"
  4. #include "PhysicsVehicleWheel.h"
  5. namespace gameplay
  6. {
  7. PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, const PhysicsCollisionShape::Definition& shape, const PhysicsRigidBody::Parameters& parameters)
  8. : PhysicsCollisionObject(node), _host(NULL), _indexInHost(0)
  9. {
  10. findAncestorAndBind();
  11. }
  12. PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node)
  13. : PhysicsCollisionObject(node), _host(NULL), _indexInHost(0)
  14. {
  15. findAncestorAndBind();
  16. }
  17. PhysicsVehicleWheel* PhysicsVehicleWheel::create(Node* node, Properties* properties)
  18. {
  19. PhysicsVehicleWheel* wheel = new PhysicsVehicleWheel(node);
  20. // Load the defined wheel parameters.
  21. properties->rewind();
  22. Vector3 v;
  23. const char* name;
  24. while ((name = properties->getNextProperty()) != NULL)
  25. {
  26. if (strcmp(name, "steerable") == 0)
  27. {
  28. wheel->setSteerable(properties->getBool(name));
  29. }
  30. else if (strcmp(name, "wheelDirection") == 0 && properties->getVector3(name, &v))
  31. {
  32. wheel->setWheelDirection(v);
  33. }
  34. else if (strcmp(name, "wheelAxle") == 0 && properties->getVector3(name, &v))
  35. {
  36. wheel->setWheelAxle(v);
  37. }
  38. else if (strcmp(name, "strutConnectionOffset") == 0 && properties->getVector3(name, &v))
  39. {
  40. wheel->setStrutConnectionOffset(v);
  41. }
  42. else if (strcmp(name, "strutRestLength") == 0)
  43. {
  44. wheel->setStrutRestLength(properties->getFloat(name));
  45. }
  46. else if (strcmp(name, "strutTravelMax") == 0)
  47. {
  48. wheel->setStrutTravelMax(properties->getFloat(name));
  49. }
  50. else if (strcmp(name, "strutStiffness") == 0)
  51. {
  52. wheel->setStrutStiffness(properties->getFloat(name));
  53. }
  54. else if (strcmp(name, "strutDampingCompression") == 0)
  55. {
  56. wheel->setStrutDampingCompression(properties->getFloat(name));
  57. }
  58. else if (strcmp(name, "strutDampingRelaxation") == 0)
  59. {
  60. wheel->setStrutDampingRelaxation(properties->getFloat(name));
  61. }
  62. else if (strcmp(name, "strutForceMax") == 0)
  63. {
  64. wheel->setStrutForceMax(properties->getFloat(name));
  65. }
  66. else if (strcmp(name, "frictionBreakout") == 0)
  67. {
  68. wheel->setFrictionBreakout(properties->getFloat(name));
  69. }
  70. else if (strcmp(name, "wheelRadius") == 0)
  71. {
  72. wheel->setWheelRadius(properties->getFloat(name));
  73. }
  74. else if (strcmp(name, "rollInfluence") == 0)
  75. {
  76. wheel->setRollInfluence(properties->getFloat(name));
  77. }
  78. else
  79. {
  80. // Ignore this case (we've already parsed the rigid body parameters).
  81. }
  82. }
  83. return wheel;
  84. }
  85. PhysicsVehicleWheel::~PhysicsVehicleWheel()
  86. {
  87. }
  88. btCollisionObject* PhysicsVehicleWheel::getCollisionObject() const
  89. {
  90. GP_ASSERT(_host);
  91. return _host->getCollisionObject();
  92. }
  93. PhysicsCollisionObject::Type PhysicsVehicleWheel::getType() const
  94. {
  95. return PhysicsCollisionObject::VEHICLE_WHEEL;
  96. }
  97. void PhysicsVehicleWheel::setEnabled(bool enable)
  98. {
  99. GP_ERROR("Operation not supported (PhysicsVehicleWheel::setEnabled(bool)). Use host vehicle instead.");
  100. }
  101. void PhysicsVehicleWheel::findAncestorAndBind()
  102. {
  103. GP_ASSERT(getNode());
  104. // Search for the first PhysicsVehicle that shares a common ancestor, and
  105. // bind with it. The following code performs a naive search; nothing more
  106. // sophisticated is deemed necessary because:
  107. // (a) The root of the scene is NOT a node
  108. // (b) Scene graphs tend to be relatively flat.
  109. //
  110. // The search ends when a vehicle is found or n is null:
  111. // 1: Let n = this node
  112. // 2: Visit each sibling of n and perform a breadth-first search of its descendants
  113. // 3: Let n = the parent of n
  114. // 4: Go to 2.
  115. PhysicsVehicle* host = NULL;
  116. Node* m;
  117. for (Node* n = getNode(); n && !host; n = n->getParent())
  118. {
  119. // Visit siblings before n
  120. for (m = n->getPreviousSibling(); m && !host; m = m->getPreviousSibling())
  121. {
  122. host = findVehicle(m);
  123. }
  124. // Visit siblings after n
  125. for (m = n->getNextSibling(); m && !host; m = m->getNextSibling())
  126. {
  127. host = findVehicle(m);
  128. }
  129. }
  130. // Note: Currently this method is silent on failure to find a host.
  131. if (host)
  132. {
  133. host->addWheel(this);
  134. _initialOffset = _node->getTranslation() - host->_node->getTranslation();
  135. }
  136. }
  137. PhysicsVehicle* PhysicsVehicleWheel::findVehicle(Node* node)
  138. {
  139. PhysicsCollisionObject* collisionObject = node->getCollisionObject();
  140. if (collisionObject && collisionObject->getType() == PhysicsCollisionObject::VEHICLE)
  141. {
  142. return static_cast<PhysicsVehicle*>(collisionObject);
  143. }
  144. PhysicsVehicle* result = NULL;
  145. for (Node* p = node->getFirstChild(); p && !result; p = p->getNextSibling())
  146. {
  147. result = findVehicle(p);
  148. }
  149. return result;
  150. }
  151. void PhysicsVehicleWheel::setHost(PhysicsVehicle* host, unsigned int indexInHost)
  152. {
  153. _host = host;
  154. _indexInHost = indexInHost;
  155. }
  156. void PhysicsVehicleWheel::addToVehicle(btRaycastVehicle* vehicle)
  157. {
  158. GP_ASSERT(_host);
  159. GP_ASSERT(_host->getNumWheels() == vehicle->getNumWheels() + 1);
  160. // Use safe defaults for now. Properties are assigned elsewhere.
  161. btRaycastVehicle::btVehicleTuning tuning;
  162. vehicle->addWheel(
  163. btVector3(0, 0, 0),
  164. btVector3(0, -1, 0),
  165. btVector3(-1, 0, 0),
  166. 0.6f,
  167. 0.5f,
  168. tuning,
  169. false);
  170. }
  171. void PhysicsVehicleWheel::transform(Node* node) const
  172. {
  173. GP_ASSERT(_host);
  174. GP_ASSERT(_host->_node);
  175. node->setRotation(_orientation);
  176. // Use only the component parallel to the defined strut line
  177. Vector3 strutLine;
  178. getWheelDirection(&strutLine);
  179. _host->_node->getMatrix().transformVector(&strutLine);
  180. Vector3 wheelPos;
  181. getWheelPos(&wheelPos);
  182. node->setTranslation(wheelPos + strutLine*(strutLine.dot(_positionDelta) / strutLine.lengthSquared()));
  183. }
  184. void PhysicsVehicleWheel::update(float elapsedTime)
  185. {
  186. GP_ASSERT(_host);
  187. GP_ASSERT(_host->_vehicle);
  188. const btTransform& trans = _host->_vehicle->getWheelInfo(_indexInHost).m_worldTransform;
  189. const btQuaternion& rot = trans.getRotation();
  190. const btVector3& pos = trans.getOrigin();
  191. _orientation.set(rot.x(), rot.y(), rot.z(), rot.w());
  192. Vector3 commandedPosition(pos.x(), pos.y(), pos.z());
  193. Vector3 wheelPos;
  194. getWheelPos(&wheelPos);
  195. commandedPosition -= wheelPos;
  196. // Filter out noise from Bullet
  197. Vector3 delta(_positionDelta, commandedPosition);
  198. float threshold = getStrutRestLength() * 2.0f;
  199. float responseTime = (delta.lengthSquared() > threshold*threshold) ? 0 : 60;
  200. _positionDelta.smooth(commandedPosition, elapsedTime, responseTime);
  201. }
  202. void PhysicsVehicleWheel::getConnectionDefault(Vector3* result) const
  203. {
  204. // projected strut length
  205. getWheelDirection(result);
  206. result->normalize();
  207. float length = 0.58f * getStrutRestLength();
  208. *result *= -length;
  209. // nudge wheel contact point to outer edge of tire for stability
  210. Vector3 nudge;
  211. getWheelAxle(&nudge);
  212. nudge *= nudge.dot(_initialOffset);
  213. nudge.normalize();
  214. *result += nudge * 0.068f * getWheelRadius(); // rough-in for tire width
  215. // offset at bind time
  216. *result += _initialOffset;
  217. }
  218. void PhysicsVehicleWheel::getWheelPos(Vector3* result) const
  219. {
  220. GP_ASSERT(_host);
  221. GP_ASSERT(_host->_node);
  222. *result = _initialOffset;
  223. _host->_node->getMatrix().transformPoint(result);
  224. }
  225. bool PhysicsVehicleWheel::isSteerable() const
  226. {
  227. GP_ASSERT(_host);
  228. GP_ASSERT(_host->_vehicle);
  229. return _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel;
  230. }
  231. void PhysicsVehicleWheel::setSteerable(bool steerable)
  232. {
  233. GP_ASSERT(_host);
  234. GP_ASSERT(_host->_vehicle);
  235. _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel = steerable;
  236. }
  237. void PhysicsVehicleWheel::getWheelDirection(Vector3* wheelDirection) const
  238. {
  239. GP_ASSERT(_host);
  240. GP_ASSERT(_host->_vehicle);
  241. const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_wheelDirectionCS;
  242. wheelDirection->set(v.x(), v.y(), v.z());
  243. }
  244. void PhysicsVehicleWheel::setWheelDirection(const Vector3& wheelDirection)
  245. {
  246. GP_ASSERT(_host);
  247. GP_ASSERT(_host->_vehicle);
  248. _host->_vehicle->getWheelInfo(_indexInHost).m_wheelDirectionCS.setValue(wheelDirection.x, wheelDirection.y, wheelDirection.z);
  249. }
  250. void PhysicsVehicleWheel::getWheelAxle(Vector3* wheelAxle) const
  251. {
  252. GP_ASSERT(_host);
  253. GP_ASSERT(_host->_vehicle);
  254. const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_wheelAxleCS;
  255. wheelAxle->set(v.x(), v.y(), v.z());
  256. }
  257. void PhysicsVehicleWheel::setWheelAxle(const Vector3& wheelAxle)
  258. {
  259. GP_ASSERT(_host);
  260. GP_ASSERT(_host->_vehicle);
  261. _host->_vehicle->getWheelInfo(_indexInHost).m_wheelAxleCS.setValue( wheelAxle.x, wheelAxle.y, wheelAxle.z);
  262. }
  263. void PhysicsVehicleWheel::getStrutConnectionOffset(Vector3* strutConnectionOffset) const
  264. {
  265. GP_ASSERT(_host);
  266. GP_ASSERT(_host->_vehicle);
  267. const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS;
  268. strutConnectionOffset->set(v.x(), v.y(), v.z());
  269. Vector3 strutConnectionDefault;
  270. getConnectionDefault(&strutConnectionDefault);
  271. *strutConnectionOffset -= strutConnectionDefault;
  272. }
  273. void PhysicsVehicleWheel::setStrutConnectionOffset(const Vector3& strutConnectionOffset)
  274. {
  275. GP_ASSERT(_host);
  276. GP_ASSERT(_host->_vehicle);
  277. Vector3 strutConnectionPoint;
  278. getConnectionDefault(&strutConnectionPoint);
  279. strutConnectionPoint += strutConnectionOffset;
  280. _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS.setValue(strutConnectionPoint.x,
  281. strutConnectionPoint.y,
  282. strutConnectionPoint.z);
  283. }
  284. float PhysicsVehicleWheel::getStrutRestLength() const
  285. {
  286. GP_ASSERT(_host);
  287. GP_ASSERT(_host->_vehicle);
  288. return _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionRestLength1;
  289. }
  290. void PhysicsVehicleWheel::setStrutRestLength(float strutRestLength)
  291. {
  292. GP_ASSERT(_host);
  293. GP_ASSERT(_host->_vehicle);
  294. _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionRestLength1 = strutRestLength;
  295. }
  296. float PhysicsVehicleWheel::getStrutTravelMax() const
  297. {
  298. GP_ASSERT(_host);
  299. GP_ASSERT(_host->_vehicle);
  300. return _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionTravelCm / 100.0f;
  301. }
  302. void PhysicsVehicleWheel::setStrutTravelMax(float strutTravelMax)
  303. {
  304. GP_ASSERT(_host);
  305. GP_ASSERT(_host->_vehicle);
  306. _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionTravelCm = strutTravelMax * 100.0f;
  307. }
  308. float PhysicsVehicleWheel::getStrutStiffness() const
  309. {
  310. GP_ASSERT(_host);
  311. GP_ASSERT(_host->_vehicle);
  312. return _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionStiffness;
  313. }
  314. void PhysicsVehicleWheel::setStrutStiffness(float strutStiffness)
  315. {
  316. GP_ASSERT(_host);
  317. GP_ASSERT(_host->_vehicle);
  318. _host->_vehicle->getWheelInfo(_indexInHost).m_suspensionStiffness = strutStiffness;
  319. }
  320. float PhysicsVehicleWheel::getStrutDampingCompression() const
  321. {
  322. GP_ASSERT(_host);
  323. GP_ASSERT(_host->_vehicle);
  324. return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingCompression;
  325. }
  326. void PhysicsVehicleWheel::setStrutDampingCompression(float strutDampingCompression)
  327. {
  328. GP_ASSERT(_host);
  329. GP_ASSERT(_host->_vehicle);
  330. _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingCompression = strutDampingCompression;
  331. }
  332. float PhysicsVehicleWheel::getStrutDampingRelaxation() const
  333. {
  334. GP_ASSERT(_host);
  335. GP_ASSERT(_host->_vehicle);
  336. return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingRelaxation;
  337. }
  338. void PhysicsVehicleWheel::setStrutDampingRelaxation(float strutDampingRelaxation)
  339. {
  340. GP_ASSERT(_host);
  341. GP_ASSERT(_host->_vehicle);
  342. _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsDampingRelaxation = strutDampingRelaxation;
  343. }
  344. float PhysicsVehicleWheel::getStrutForceMax() const
  345. {
  346. GP_ASSERT(_host);
  347. GP_ASSERT(_host->_vehicle);
  348. return _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionForce;
  349. }
  350. void PhysicsVehicleWheel::setStrutForceMax(float strutForceMax)
  351. {
  352. GP_ASSERT(_host);
  353. GP_ASSERT(_host->_vehicle);
  354. _host->_vehicle->getWheelInfo(_indexInHost).m_maxSuspensionForce = strutForceMax;
  355. }
  356. float PhysicsVehicleWheel::getFrictionBreakout() const
  357. {
  358. GP_ASSERT(_host);
  359. GP_ASSERT(_host->_vehicle);
  360. return _host->_vehicle->getWheelInfo(_indexInHost).m_frictionSlip;
  361. }
  362. void PhysicsVehicleWheel::setFrictionBreakout(float frictionBreakout)
  363. {
  364. GP_ASSERT(_host);
  365. GP_ASSERT(_host->_vehicle);
  366. _host->_vehicle->getWheelInfo(_indexInHost).m_frictionSlip = frictionBreakout;
  367. }
  368. float PhysicsVehicleWheel::getWheelRadius() const
  369. {
  370. GP_ASSERT(_host);
  371. GP_ASSERT(_host->_vehicle);
  372. return _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsRadius;
  373. }
  374. void PhysicsVehicleWheel::setWheelRadius(float wheelRadius)
  375. {
  376. GP_ASSERT(_host);
  377. GP_ASSERT(_host->_vehicle);
  378. _host->_vehicle->getWheelInfo(_indexInHost).m_wheelsRadius = wheelRadius;
  379. }
  380. float PhysicsVehicleWheel::getRollInfluence() const
  381. {
  382. GP_ASSERT(_host);
  383. GP_ASSERT(_host->_vehicle);
  384. return _host->_vehicle->getWheelInfo(_indexInHost).m_rollInfluence;
  385. }
  386. void PhysicsVehicleWheel::setRollInfluence(float rollInfluence)
  387. {
  388. GP_ASSERT(_host);
  389. GP_ASSERT(_host->_vehicle);
  390. _host->_vehicle->getWheelInfo(_indexInHost).m_rollInfluence = rollInfluence;
  391. }
  392. }