btRaycastVehicle.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*
  2. * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
  3. *
  4. * Permission to use, copy, modify, distribute and sell this software
  5. * and its documentation for any purpose is hereby granted without fee,
  6. * provided that the above copyright notice appear in all copies.
  7. * Erwin Coumans makes no representations about the suitability
  8. * of this software for any purpose.
  9. * It is provided "as is" without express or implied warranty.
  10. */
  11. #include "bullet/LinearMath/btVector3.h"
  12. #include "btRaycastVehicle.h"
  13. #include "bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
  14. #include "bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h"
  15. #include "bullet/LinearMath/btQuaternion.h"
  16. #include "bullet/BulletDynamics/Dynamics/btDynamicsWorld.h"
  17. #include "btVehicleRaycaster.h"
  18. #include "btWheelInfo.h"
  19. #include "bullet/LinearMath/btMinMax.h"
  20. #include "bullet/LinearMath/btIDebugDraw.h"
  21. #include "bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h"
  22. #define ROLLING_INFLUENCE_FIX
  23. btRigidBody& btActionInterface::getFixedBody()
  24. {
  25. static btRigidBody s_fixed(0, 0,0);
  26. s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
  27. return s_fixed;
  28. }
  29. btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster )
  30. :m_vehicleRaycaster(raycaster),
  31. m_pitchControl(btScalar(0.))
  32. {
  33. m_chassisBody = chassis;
  34. m_indexRightAxis = 0;
  35. m_indexUpAxis = 2;
  36. m_indexForwardAxis = 1;
  37. defaultInit(tuning);
  38. }
  39. void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
  40. {
  41. (void)tuning;
  42. m_currentVehicleSpeedKmHour = btScalar(0.);
  43. m_steeringValue = btScalar(0.);
  44. }
  45. btRaycastVehicle::~btRaycastVehicle()
  46. {
  47. }
  48. //
  49. // basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
  50. //
  51. btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel)
  52. {
  53. btWheelInfoConstructionInfo ci;
  54. ci.m_chassisConnectionCS = connectionPointCS;
  55. ci.m_wheelDirectionCS = wheelDirectionCS0;
  56. ci.m_wheelAxleCS = wheelAxleCS;
  57. ci.m_suspensionRestLength = suspensionRestLength;
  58. ci.m_wheelRadius = wheelRadius;
  59. ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
  60. ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
  61. ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
  62. ci.m_frictionSlip = tuning.m_frictionSlip;
  63. ci.m_bIsFrontWheel = isFrontWheel;
  64. ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
  65. ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
  66. m_wheelInfo.push_back( btWheelInfo(ci));
  67. btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
  68. updateWheelTransformsWS( wheel , false );
  69. updateWheelTransform(getNumWheels()-1,false);
  70. return wheel;
  71. }
  72. const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const
  73. {
  74. btAssert(wheelIndex < getNumWheels());
  75. const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
  76. return wheel.m_worldTransform;
  77. }
  78. void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform)
  79. {
  80. btWheelInfo& wheel = m_wheelInfo[ wheelIndex ];
  81. updateWheelTransformsWS(wheel,interpolatedTransform);
  82. btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
  83. const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
  84. btVector3 fwd = up.cross(right);
  85. fwd = fwd.normalize();
  86. // up = right.cross(fwd);
  87. // up.normalize();
  88. //rotate around steering over de wheelAxleWS
  89. btScalar steering = wheel.m_steering;
  90. btQuaternion steeringOrn(up,steering);//wheel.m_steering);
  91. btMatrix3x3 steeringMat(steeringOrn);
  92. btQuaternion rotatingOrn(right,-wheel.m_rotation);
  93. btMatrix3x3 rotatingMat(rotatingOrn);
  94. btMatrix3x3 basis2(
  95. right[0],fwd[0],up[0],
  96. right[1],fwd[1],up[1],
  97. right[2],fwd[2],up[2]
  98. );
  99. wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
  100. wheel.m_worldTransform.setOrigin(
  101. wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
  102. );
  103. }
  104. void btRaycastVehicle::resetSuspension()
  105. {
  106. int i;
  107. for (i=0;i<m_wheelInfo.size(); i++)
  108. {
  109. btWheelInfo& wheel = m_wheelInfo[i];
  110. wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
  111. wheel.m_suspensionRelativeVelocity = btScalar(0.0);
  112. wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
  113. //wheel_info.setContactFriction(btScalar(0.0));
  114. wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
  115. }
  116. }
  117. void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
  118. {
  119. wheel.m_raycastInfo.m_isInContact = false;
  120. btTransform chassisTrans = getChassisWorldTransform();
  121. if (interpolatedTransform && (getRigidBody()->getMotionState()))
  122. {
  123. getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
  124. }
  125. wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
  126. wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ;
  127. wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
  128. }
  129. btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
  130. {
  131. updateWheelTransformsWS( wheel,false);
  132. btScalar depth = -1;
  133. btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius;
  134. btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
  135. const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
  136. wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
  137. const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
  138. btScalar param = btScalar(0.);
  139. btVehicleRaycaster::btVehicleRaycasterResult rayResults;
  140. btAssert(m_vehicleRaycaster);
  141. void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
  142. wheel.m_raycastInfo.m_groundObject = 0;
  143. if (object)
  144. {
  145. param = rayResults.m_distFraction;
  146. depth = raylen * rayResults.m_distFraction;
  147. wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
  148. wheel.m_raycastInfo.m_isInContact = true;
  149. wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!;
  150. //wheel.m_raycastInfo.m_groundObject = object;
  151. btScalar hitDistance = param*raylen;
  152. wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
  153. //clamp on max suspension travel
  154. btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
  155. btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
  156. if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
  157. {
  158. wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
  159. }
  160. if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
  161. {
  162. wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
  163. }
  164. wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
  165. btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
  166. btVector3 chassis_velocity_at_contactPoint;
  167. btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
  168. chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
  169. btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
  170. if ( denominator >= btScalar(-0.1))
  171. {
  172. wheel.m_suspensionRelativeVelocity = btScalar(0.0);
  173. wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
  174. }
  175. else
  176. {
  177. btScalar inv = btScalar(-1.) / denominator;
  178. wheel.m_suspensionRelativeVelocity = projVel * inv;
  179. wheel.m_clippedInvContactDotSuspension = inv;
  180. }
  181. } else
  182. {
  183. //put wheel info as in rest position
  184. wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
  185. wheel.m_suspensionRelativeVelocity = btScalar(0.0);
  186. wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
  187. wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
  188. }
  189. return depth;
  190. }
  191. const btTransform& btRaycastVehicle::getChassisWorldTransform() const
  192. {
  193. /*if (getRigidBody()->getMotionState())
  194. {
  195. btTransform chassisWorldTrans;
  196. getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
  197. return chassisWorldTrans;
  198. }
  199. */
  200. return getRigidBody()->getCenterOfMassTransform();
  201. }
  202. void btRaycastVehicle::updateVehicle( btScalar step )
  203. {
  204. {
  205. for (int i=0;i<getNumWheels();i++)
  206. {
  207. updateWheelTransform(i,false);
  208. }
  209. }
  210. m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
  211. const btTransform& chassisTrans = getChassisWorldTransform();
  212. btVector3 forwardW (
  213. chassisTrans.getBasis()[0][m_indexForwardAxis],
  214. chassisTrans.getBasis()[1][m_indexForwardAxis],
  215. chassisTrans.getBasis()[2][m_indexForwardAxis]);
  216. if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
  217. {
  218. m_currentVehicleSpeedKmHour *= btScalar(-1.);
  219. }
  220. //
  221. // simulate suspension
  222. //
  223. int i=0;
  224. for (i=0;i<m_wheelInfo.size();i++)
  225. {
  226. btScalar depth;
  227. depth = rayCast( m_wheelInfo[i]);
  228. }
  229. updateSuspension(step);
  230. for (i=0;i<m_wheelInfo.size();i++)
  231. {
  232. //apply suspension force
  233. btWheelInfo& wheel = m_wheelInfo[i];
  234. btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
  235. if (suspensionForce > wheel.m_maxSuspensionForce)
  236. {
  237. suspensionForce = wheel.m_maxSuspensionForce;
  238. }
  239. btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
  240. btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
  241. getRigidBody()->applyImpulse(impulse, relpos);
  242. }
  243. updateFriction( step);
  244. for (i=0;i<m_wheelInfo.size();i++)
  245. {
  246. btWheelInfo& wheel = m_wheelInfo[i];
  247. btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
  248. btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
  249. if (wheel.m_raycastInfo.m_isInContact)
  250. {
  251. const btTransform& chassisWorldTransform = getChassisWorldTransform();
  252. btVector3 fwd (
  253. chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
  254. chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
  255. chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
  256. btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
  257. fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
  258. btScalar proj2 = fwd.dot(vel);
  259. wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
  260. wheel.m_rotation += wheel.m_deltaRotation;
  261. } else
  262. {
  263. wheel.m_rotation += wheel.m_deltaRotation;
  264. }
  265. wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
  266. }
  267. }
  268. void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel)
  269. {
  270. btAssert(wheel>=0 && wheel < getNumWheels());
  271. btWheelInfo& wheelInfo = getWheelInfo(wheel);
  272. wheelInfo.m_steering = steering;
  273. }
  274. btScalar btRaycastVehicle::getSteeringValue(int wheel) const
  275. {
  276. return getWheelInfo(wheel).m_steering;
  277. }
  278. void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
  279. {
  280. btAssert(wheel>=0 && wheel < getNumWheels());
  281. btWheelInfo& wheelInfo = getWheelInfo(wheel);
  282. wheelInfo.m_engineForce = force;
  283. }
  284. const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
  285. {
  286. btAssert((index >= 0) && (index < getNumWheels()));
  287. return m_wheelInfo[index];
  288. }
  289. btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
  290. {
  291. btAssert((index >= 0) && (index < getNumWheels()));
  292. return m_wheelInfo[index];
  293. }
  294. void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex)
  295. {
  296. btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
  297. getWheelInfo(wheelIndex).m_brake = brake;
  298. }
  299. void btRaycastVehicle::updateSuspension(btScalar deltaTime)
  300. {
  301. (void)deltaTime;
  302. btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
  303. for (int w_it=0; w_it<getNumWheels(); w_it++)
  304. {
  305. btWheelInfo &wheel_info = m_wheelInfo[w_it];
  306. if ( wheel_info.m_raycastInfo.m_isInContact )
  307. {
  308. btScalar force;
  309. // Spring
  310. {
  311. btScalar susp_length = wheel_info.getSuspensionRestLength();
  312. btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
  313. btScalar length_diff = (susp_length - current_length);
  314. force = wheel_info.m_suspensionStiffness
  315. * length_diff * wheel_info.m_clippedInvContactDotSuspension;
  316. }
  317. // Damper
  318. {
  319. btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
  320. {
  321. btScalar susp_damping;
  322. if ( projected_rel_vel < btScalar(0.0) )
  323. {
  324. susp_damping = wheel_info.m_wheelsDampingCompression;
  325. }
  326. else
  327. {
  328. susp_damping = wheel_info.m_wheelsDampingRelaxation;
  329. }
  330. force -= susp_damping * projected_rel_vel;
  331. }
  332. }
  333. // RESULT
  334. wheel_info.m_wheelsSuspensionForce = force * chassisMass;
  335. if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
  336. {
  337. wheel_info.m_wheelsSuspensionForce = btScalar(0.);
  338. }
  339. }
  340. else
  341. {
  342. wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
  343. }
  344. }
  345. }
  346. struct btWheelContactPoint
  347. {
  348. btRigidBody* m_body0;
  349. btRigidBody* m_body1;
  350. btVector3 m_frictionPositionWorld;
  351. btVector3 m_frictionDirectionWorld;
  352. btScalar m_jacDiagABInv;
  353. btScalar m_maxImpulse;
  354. btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse)
  355. :m_body0(body0),
  356. m_body1(body1),
  357. m_frictionPositionWorld(frictionPosWorld),
  358. m_frictionDirectionWorld(frictionDirectionWorld),
  359. m_maxImpulse(maxImpulse)
  360. {
  361. btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
  362. btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
  363. btScalar relaxation = 1.f;
  364. m_jacDiagABInv = relaxation/(denom0+denom1);
  365. }
  366. };
  367. btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
  368. btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
  369. {
  370. btScalar j1=0.f;
  371. const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
  372. btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
  373. btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
  374. btScalar maxImpulse = contactPoint.m_maxImpulse;
  375. btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
  376. btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
  377. btVector3 vel = vel1 - vel2;
  378. btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
  379. // calculate j that moves us to zero relative velocity
  380. j1 = -vrel * contactPoint.m_jacDiagABInv;
  381. btSetMin(j1, maxImpulse);
  382. btSetMax(j1, -maxImpulse);
  383. return j1;
  384. }
  385. btScalar sideFrictionStiffness2 = btScalar(1.0);
  386. void btRaycastVehicle::updateFriction(btScalar timeStep)
  387. {
  388. //calculate the impulse, so that the wheels don't move sidewards
  389. int numWheel = getNumWheels();
  390. if (!numWheel)
  391. return;
  392. m_forwardWS.resize(numWheel);
  393. m_axle.resize(numWheel);
  394. m_forwardImpulse.resize(numWheel);
  395. m_sideImpulse.resize(numWheel);
  396. int numWheelsOnGround = 0;
  397. //collapse all those loops into one!
  398. for (int i=0;i<getNumWheels();i++)
  399. {
  400. btWheelInfo& wheelInfo = m_wheelInfo[i];
  401. class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  402. if (groundObject)
  403. numWheelsOnGround++;
  404. m_sideImpulse[i] = btScalar(0.);
  405. m_forwardImpulse[i] = btScalar(0.);
  406. }
  407. {
  408. for (int i=0;i<getNumWheels();i++)
  409. {
  410. btWheelInfo& wheelInfo = m_wheelInfo[i];
  411. class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  412. if (groundObject)
  413. {
  414. const btTransform& wheelTrans = getWheelTransformWS( i );
  415. btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
  416. m_axle[i] = btVector3(
  417. wheelBasis0[0][m_indexRightAxis],
  418. wheelBasis0[1][m_indexRightAxis],
  419. wheelBasis0[2][m_indexRightAxis]);
  420. const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
  421. btScalar proj = m_axle[i].dot(surfNormalWS);
  422. m_axle[i] -= surfNormalWS * proj;
  423. m_axle[i] = m_axle[i].normalize();
  424. m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
  425. m_forwardWS[i].normalize();
  426. resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
  427. *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
  428. btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
  429. m_sideImpulse[i] *= sideFrictionStiffness2;
  430. }
  431. }
  432. }
  433. btScalar sideFactor = btScalar(1.);
  434. btScalar fwdFactor = 0.5;
  435. bool sliding = false;
  436. {
  437. for (int wheel =0;wheel <getNumWheels();wheel++)
  438. {
  439. btWheelInfo& wheelInfo = m_wheelInfo[wheel];
  440. class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  441. btScalar rollingFriction = 0.f;
  442. if (groundObject)
  443. {
  444. if (wheelInfo.m_engineForce != 0.f)
  445. {
  446. rollingFriction = wheelInfo.m_engineForce* timeStep;
  447. } else
  448. {
  449. btScalar defaultRollingFrictionImpulse = 0.f;
  450. btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
  451. btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
  452. rollingFriction = calcRollingFriction(contactPt);
  453. }
  454. }
  455. //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
  456. m_forwardImpulse[wheel] = btScalar(0.);
  457. m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
  458. if (groundObject)
  459. {
  460. m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
  461. btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
  462. btScalar maximpSide = maximp;
  463. btScalar maximpSquared = maximp * maximpSide;
  464. m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
  465. btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
  466. btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
  467. btScalar impulseSquared = (x*x + y*y);
  468. if (impulseSquared > maximpSquared)
  469. {
  470. sliding = true;
  471. btScalar factor = maximp / btSqrt(impulseSquared);
  472. m_wheelInfo[wheel].m_skidInfo *= factor;
  473. }
  474. }
  475. }
  476. }
  477. if (sliding)
  478. {
  479. for (int wheel = 0;wheel < getNumWheels(); wheel++)
  480. {
  481. if (m_sideImpulse[wheel] != btScalar(0.))
  482. {
  483. if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
  484. {
  485. m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
  486. m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
  487. }
  488. }
  489. }
  490. }
  491. // apply the impulses
  492. {
  493. for (int wheel = 0;wheel<getNumWheels() ; wheel++)
  494. {
  495. btWheelInfo& wheelInfo = m_wheelInfo[wheel];
  496. btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
  497. m_chassisBody->getCenterOfMassPosition();
  498. if (m_forwardImpulse[wheel] != btScalar(0.))
  499. {
  500. m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
  501. }
  502. if (m_sideImpulse[wheel] != btScalar(0.))
  503. {
  504. class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
  505. btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
  506. groundObject->getCenterOfMassPosition();
  507. btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
  508. #if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
  509. btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
  510. rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
  511. #else
  512. rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
  513. #endif
  514. m_chassisBody->applyImpulse(sideImp,rel_pos);
  515. //apply friction impulse on the ground
  516. groundObject->applyImpulse(-sideImp,rel_pos2);
  517. }
  518. }
  519. }
  520. }
  521. void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
  522. {
  523. for (int v=0;v<this->getNumWheels();v++)
  524. {
  525. btVector3 wheelColor(0,1,1);
  526. if (getWheelInfo(v).m_raycastInfo.m_isInContact)
  527. {
  528. wheelColor.setValue(0,0,1);
  529. } else
  530. {
  531. wheelColor.setValue(1,0,1);
  532. }
  533. btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
  534. btVector3 axle = btVector3(
  535. getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
  536. getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
  537. getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
  538. //debug wheels (cylinders)
  539. debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
  540. debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
  541. }
  542. }
  543. void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
  544. {
  545. // RayResultCallback& resultCallback;
  546. btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);
  547. m_dynamicsWorld->rayTest(from, to, rayCallback);
  548. if (rayCallback.hasHit())
  549. {
  550. const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
  551. if (body && body->hasContactResponse())
  552. {
  553. result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
  554. result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
  555. result.m_hitNormalInWorld.normalize();
  556. result.m_distFraction = rayCallback.m_closestHitFraction;
  557. return (void*)body;
  558. }
  559. }
  560. return 0;
  561. }