PhysicsVehicle.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #include "Base.h"
  2. #include "Game.h"
  3. #include "Node.h"
  4. #include "PhysicsVehicle.h"
  5. #include "PhysicsVehicleWheel.h"
  6. namespace gameplay
  7. {
  8. /**
  9. * The default vehicle raycaster in Bullet currently does not filter out the vehicle's own
  10. * rigid body from the ray test which can result in unexpected behavior. These implementations
  11. * are intended to fix that.
  12. *
  13. * @script{ignore}
  14. */
  15. class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
  16. {
  17. public:
  18. ClosestNotMeRayResultCallback(const btVector3& from, const btVector3& to, btCollisionObject* me)
  19. : btCollisionWorld::ClosestRayResultCallback(from, to), _me(me)
  20. {
  21. }
  22. btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
  23. {
  24. if (rayResult.m_collisionObject == _me)
  25. return 1.0f;
  26. return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
  27. }
  28. private:
  29. btCollisionObject* _me;
  30. };
  31. /**
  32. * @script{ignore}
  33. */
  34. class VehicleNotMeRaycaster : public btVehicleRaycaster
  35. {
  36. public:
  37. VehicleNotMeRaycaster(btDynamicsWorld* world, btCollisionObject* me)
  38. : _dynamicsWorld(world), _me(me)
  39. {
  40. }
  41. void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result)
  42. {
  43. ClosestNotMeRayResultCallback rayCallback(from, to, _me);
  44. _dynamicsWorld->rayTest(from, to, rayCallback);
  45. if (rayCallback.hasHit())
  46. {
  47. const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
  48. if (body && body->hasContactResponse())
  49. {
  50. result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
  51. result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
  52. result.m_hitNormalInWorld.normalize();
  53. result.m_distFraction = rayCallback.m_closestHitFraction;
  54. return (void*)body;
  55. }
  56. }
  57. return 0;
  58. }
  59. private:
  60. btDynamicsWorld* _dynamicsWorld;
  61. btCollisionObject* _me;
  62. };
  63. PhysicsVehicle::PhysicsVehicle(Node* node, const PhysicsCollisionShape::Definition& shape, const PhysicsRigidBody::Parameters& parameters)
  64. : PhysicsCollisionObject(node)
  65. {
  66. // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
  67. // that is where the rigid body gets added to the dynamics world.
  68. _rigidBody = new PhysicsRigidBody(node, shape, parameters);
  69. initialize();
  70. }
  71. PhysicsVehicle::PhysicsVehicle(Node* node, PhysicsRigidBody* rigidBody)
  72. : PhysicsCollisionObject(node)
  73. {
  74. _rigidBody = rigidBody;
  75. initialize();
  76. }
  77. PhysicsVehicle* PhysicsVehicle::create(Node* node, Properties* properties)
  78. {
  79. // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
  80. // that is where the rigid body gets added to the dynamics world.
  81. PhysicsRigidBody* rigidBody = PhysicsRigidBody::create(node, properties, "VEHICLE");
  82. PhysicsVehicle* vehicle = new PhysicsVehicle(node, rigidBody);
  83. // Load the defined vehicle parameters.
  84. properties->rewind();
  85. const char* name;
  86. while ((name = properties->getNextProperty()) != NULL)
  87. {
  88. if (strcmp(name, "steeringGain") == 0)
  89. {
  90. vehicle->setSteeringGain(properties->getFloat());
  91. }
  92. else if (strcmp(name, "brakingForce") == 0)
  93. {
  94. vehicle->setBrakingForce(properties->getFloat());
  95. }
  96. else if (strcmp(name, "drivingForce") == 0)
  97. {
  98. vehicle->setDrivingForce(properties->getFloat());
  99. }
  100. else
  101. {
  102. // Ignore this case (we've already parsed the rigid body parameters).
  103. }
  104. }
  105. return vehicle;
  106. }
  107. void PhysicsVehicle::initialize()
  108. {
  109. GP_ASSERT(getNode());
  110. // Safe default values
  111. setSteeringGain(0.5f);
  112. setBrakingForce(350.0f);
  113. setDrivingForce(2000.0f);
  114. // Create the vehicle and add it to world
  115. btRigidBody* body = static_cast<btRigidBody*>(_rigidBody->getCollisionObject());
  116. btDynamicsWorld* dynamicsWorld = Game::getInstance()->getPhysicsController()->_world;
  117. _vehicleRaycaster = new VehicleNotMeRaycaster(dynamicsWorld, body);
  118. _vehicle = new btRaycastVehicle(_vehicleTuning, body, _vehicleRaycaster);
  119. body->setActivationState(DISABLE_DEACTIVATION);
  120. dynamicsWorld->addVehicle(_vehicle);
  121. _vehicle->setCoordinateSystem(0, 1, 2);
  122. // Advertise self among ancestor nodes so that wheels can bind to self.
  123. // See PhysicsVehicleWheel and Node for more details.
  124. for (Node* n = getNode()->getParent(); n; n = n->getParent())
  125. {
  126. n->addAdvertisedDescendant(getNode());
  127. }
  128. }
  129. PhysicsVehicle::~PhysicsVehicle()
  130. {
  131. // Note that the destructor for PhysicsRigidBody calls removeCollisionObject and so
  132. // that is where the rigid body gets removed from the dynamics world. The vehicle
  133. // itself is just an action interface in the dynamics world.
  134. SAFE_DELETE(_vehicle);
  135. SAFE_DELETE(_vehicleRaycaster);
  136. SAFE_DELETE(_rigidBody);
  137. }
  138. btCollisionObject* PhysicsVehicle::getCollisionObject() const
  139. {
  140. GP_ASSERT(_rigidBody);
  141. return _rigidBody->getCollisionObject();
  142. }
  143. PhysicsCollisionObject::Type PhysicsVehicle::getType() const
  144. {
  145. return PhysicsCollisionObject::VEHICLE;
  146. }
  147. PhysicsRigidBody* PhysicsVehicle::getRigidBody() const
  148. {
  149. GP_ASSERT(_rigidBody);
  150. return _rigidBody;
  151. }
  152. unsigned int PhysicsVehicle::getNumWheels() const
  153. {
  154. return _wheels.size();
  155. }
  156. PhysicsVehicleWheel* PhysicsVehicle::getWheel(unsigned int i)
  157. {
  158. return _wheels.at(i);
  159. }
  160. void PhysicsVehicle::addWheel(PhysicsVehicleWheel* wheel)
  161. {
  162. unsigned int i = _wheels.size();
  163. _wheels.push_back(wheel);
  164. wheel->setHost(this, i);
  165. wheel->addToVehicle(_vehicle);
  166. }
  167. float PhysicsVehicle::getSpeedKph() const
  168. {
  169. return _vehicle->getCurrentSpeedKmHour();
  170. }
  171. void PhysicsVehicle::update(float elapsedTime, float steering, float braking, float driving)
  172. {
  173. PhysicsVehicleWheel* wheel;
  174. for (int i = 0; i < _vehicle->getNumWheels(); i++)
  175. {
  176. wheel = getWheel(i);
  177. if (wheel->isFront())
  178. {
  179. _vehicle->setSteeringValue(steering * _steeringGain, i);
  180. }
  181. else
  182. {
  183. // Allow braking to take precedence over driving.
  184. if (driving > 0 && braking > 0)
  185. {
  186. driving = 0;
  187. }
  188. _vehicle->applyEngineForce(driving * _drivingForce, i);
  189. _vehicle->setBrake(braking * _brakingForce, i);
  190. }
  191. wheel->update(elapsedTime);
  192. wheel->transform(wheel->getNode());
  193. }
  194. }
  195. float PhysicsVehicle::getSteeringGain() const
  196. {
  197. return _steeringGain;
  198. }
  199. void PhysicsVehicle::setSteeringGain(float steeringGain)
  200. {
  201. _steeringGain = steeringGain;
  202. }
  203. float PhysicsVehicle::getBrakingForce() const
  204. {
  205. return _brakingForce;
  206. }
  207. void PhysicsVehicle::setBrakingForce(float brakingForce)
  208. {
  209. _brakingForce = brakingForce;
  210. }
  211. float PhysicsVehicle::getDrivingForce() const
  212. {
  213. return _drivingForce;
  214. }
  215. void PhysicsVehicle::setDrivingForce(float drivingForce)
  216. {
  217. _drivingForce = drivingForce;
  218. }
  219. }