vehicle_body.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. #include "vehicle_body.h"
  2. #define ROLLING_INFLUENCE_FIX
  3. class btVehicleJacobianEntry
  4. {
  5. public:
  6. Vector3 m_linearJointAxis;
  7. Vector3 m_aJ;
  8. Vector3 m_bJ;
  9. Vector3 m_0MinvJt;
  10. Vector3 m_1MinvJt;
  11. //Optimization: can be stored in the w/last component of one of the vectors
  12. real_t m_Adiag;
  13. real_t getDiagonal() const { return m_Adiag; }
  14. btVehicleJacobianEntry() {};
  15. //constraint between two different rigidbodies
  16. btVehicleJacobianEntry(
  17. const Matrix3& world2A,
  18. const Matrix3& world2B,
  19. const Vector3& rel_pos1,
  20. const Vector3& rel_pos2,
  21. const Vector3& jointAxis,
  22. const Vector3& inertiaInvA,
  23. const real_t massInvA,
  24. const Vector3& inertiaInvB,
  25. const real_t massInvB)
  26. :m_linearJointAxis(jointAxis)
  27. {
  28. m_aJ = world2A.xform(rel_pos1.cross(m_linearJointAxis));
  29. m_bJ = world2B.xform(rel_pos2.cross(-m_linearJointAxis));
  30. m_0MinvJt = inertiaInvA * m_aJ;
  31. m_1MinvJt = inertiaInvB * m_bJ;
  32. m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
  33. //btAssert(m_Adiag > real_t(0.0));
  34. }
  35. real_t getRelativeVelocity(const Vector3& linvelA,const Vector3& angvelA,const Vector3& linvelB,const Vector3& angvelB)
  36. {
  37. Vector3 linrel = linvelA - linvelB;
  38. Vector3 angvela = angvelA * m_aJ;
  39. Vector3 angvelb = angvelB * m_bJ;
  40. linrel *= m_linearJointAxis;
  41. angvela += angvelb;
  42. angvela += linrel;
  43. real_t rel_vel2 = angvela[0]+angvela[1]+angvela[2];
  44. return rel_vel2 + CMP_EPSILON;
  45. }
  46. };
  47. void VehicleWheel::_notification(int p_what) {
  48. if (p_what==NOTIFICATION_ENTER_SCENE) {
  49. if (!get_parent())
  50. return;
  51. VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
  52. if (!cb)
  53. return;
  54. body=cb;
  55. local_xform=get_transform();
  56. cb->wheels.push_back(this);
  57. m_chassisConnectionPointCS = get_transform().origin;
  58. m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
  59. m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
  60. }
  61. if (p_what==NOTIFICATION_EXIT_SCENE) {
  62. if (!get_parent())
  63. return;
  64. VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
  65. if (!cb)
  66. return;
  67. cb->wheels.erase(this);
  68. body=NULL;
  69. }
  70. }
  71. void VehicleWheel::_update(PhysicsDirectBodyState *s) {
  72. if (m_raycastInfo.m_isInContact)
  73. {
  74. real_t project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
  75. Vector3 chassis_velocity_at_contactPoint;
  76. Vector3 relpos = m_raycastInfo.m_contactPointWS - s->get_transform().origin;
  77. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  78. (s->get_angular_velocity()).cross(relpos);// * mPos);
  79. real_t projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
  80. if ( project >= real_t(-0.1))
  81. {
  82. m_suspensionRelativeVelocity = real_t(0.0);
  83. m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  84. }
  85. else
  86. {
  87. real_t inv = real_t(-1.) / project;
  88. m_suspensionRelativeVelocity = projVel * inv;
  89. m_clippedInvContactDotSuspension = inv;
  90. }
  91. }
  92. else // Not in contact : position wheel in a nice (rest length) position
  93. {
  94. m_raycastInfo.m_suspensionLength = m_suspensionRestLength;
  95. m_suspensionRelativeVelocity = real_t(0.0);
  96. m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
  97. m_clippedInvContactDotSuspension = real_t(1.0);
  98. }
  99. }
  100. void VehicleWheel::_bind_methods() {
  101. }
  102. VehicleWheel::VehicleWheel() {
  103. m_steering = real_t(0.);
  104. m_engineForce = real_t(0.);
  105. m_rotation = real_t(0.);
  106. m_deltaRotation = real_t(0.);
  107. m_brake = real_t(0.);
  108. m_rollInfluence = real_t(0.1);
  109. m_suspensionRestLength = 0.15;
  110. m_wheelRadius = 0.5;//0.28;
  111. m_suspensionStiffness = 5.88;
  112. m_wheelsDampingCompression = 0.83;
  113. m_wheelsDampingRelaxation = 0.88;
  114. m_frictionSlip = 10.5;
  115. m_bIsFrontWheel = false;
  116. m_maxSuspensionTravelCm = 500;
  117. m_maxSuspensionForce = 6000;
  118. m_suspensionRelativeVelocity=0;
  119. m_clippedInvContactDotSuspension=1.0;
  120. m_raycastInfo.m_isInContact=false;
  121. body=NULL;
  122. }
  123. void VehicleBody::_update_wheel_transform(VehicleWheel& wheel ,PhysicsDirectBodyState *s) {
  124. wheel.m_raycastInfo.m_isInContact = false;
  125. Transform chassisTrans = s->get_transform();
  126. //if (interpolatedTransform && (getRigidBody()->getMotionState()))
  127. //{
  128. // getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
  129. //}
  130. wheel.m_raycastInfo.m_hardPointWS = chassisTrans.xform( wheel.m_chassisConnectionPointCS );
  131. wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.get_basis().xform( wheel.m_wheelDirectionCS).normalized();
  132. wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform( wheel.m_wheelAxleCS ).normalized();
  133. }
  134. void VehicleBody::_update_wheel(int p_idx,PhysicsDirectBodyState *s) {
  135. VehicleWheel& wheel = *wheels[p_idx];
  136. _update_wheel_transform(wheel,s);
  137. Vector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
  138. const Vector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
  139. Vector3 fwd = up.cross(right);
  140. fwd = fwd.normalized();
  141. // up = right.cross(fwd);
  142. // up.normalize();
  143. //rotate around steering over de wheelAxleWS
  144. real_t steering = wheel.m_steering;
  145. Matrix3 steeringMat(up,steering);
  146. Matrix3 rotatingMat(right,-wheel.m_rotation);
  147. Matrix3 basis2(
  148. right[0],up[0],fwd[0],
  149. right[1],up[1],fwd[1],
  150. right[2],up[2],fwd[2]
  151. );
  152. wheel.m_worldTransform.set_basis(steeringMat * rotatingMat * basis2);
  153. wheel.m_worldTransform.set_origin(
  154. wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
  155. );
  156. }
  157. real_t VehicleBody::_ray_cast(int p_idx,PhysicsDirectBodyState *s) {
  158. VehicleWheel& wheel = *wheels[p_idx];
  159. _update_wheel_transform(wheel,s);
  160. real_t depth = -1;
  161. real_t raylen = wheel.m_suspensionRestLength+wheel.m_wheelRadius;
  162. Vector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
  163. const Vector3& source = wheel.m_raycastInfo.m_hardPointWS;
  164. wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
  165. const Vector3& target = wheel.m_raycastInfo.m_contactPointWS;
  166. real_t param = real_t(0.);
  167. PhysicsDirectSpaceState::RayResult rr;
  168. PhysicsDirectSpaceState *ss=s->get_space_state();
  169. bool col = ss->intersect_ray(source,target,rr,exclude);
  170. wheel.m_raycastInfo.m_groundObject = 0;
  171. if (col)
  172. {
  173. //print_line("WHEEL "+itos(p_idx)+" FROM "+source+" TO: "+target);
  174. //print_line("WHEEL "+itos(p_idx)+" COLLIDE? "+itos(col));
  175. param = source.distance_to(rr.position)/source.distance_to(target);
  176. depth = raylen * param;
  177. wheel.m_raycastInfo.m_contactNormalWS = rr.normal;
  178. wheel.m_raycastInfo.m_isInContact = true;
  179. if (rr.collider)
  180. wheel.m_raycastInfo.m_groundObject=rr.collider->cast_to<PhysicsBody>();
  181. real_t hitDistance = param*raylen;
  182. wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
  183. //clamp on max suspension travel
  184. real_t minSuspensionLength = wheel.m_suspensionRestLength - wheel.m_maxSuspensionTravelCm*real_t(0.01);
  185. real_t maxSuspensionLength = wheel.m_suspensionRestLength+ wheel.m_maxSuspensionTravelCm*real_t(0.01);
  186. if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
  187. {
  188. wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
  189. }
  190. if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
  191. {
  192. wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
  193. }
  194. wheel.m_raycastInfo.m_contactPointWS = rr.position;
  195. real_t denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
  196. Vector3 chassis_velocity_at_contactPoint;
  197. //Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
  198. //chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
  199. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  200. (s->get_angular_velocity()).cross(wheel.m_raycastInfo.m_contactPointWS-s->get_transform().origin);// * mPos);
  201. real_t projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
  202. if ( denominator >= real_t(-0.1))
  203. {
  204. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  205. wheel.m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  206. }
  207. else
  208. {
  209. real_t inv = real_t(-1.) / denominator;
  210. wheel.m_suspensionRelativeVelocity = projVel * inv;
  211. wheel.m_clippedInvContactDotSuspension = inv;
  212. }
  213. } else
  214. {
  215. wheel.m_raycastInfo.m_isInContact = false;
  216. //put wheel info as in rest position
  217. wheel.m_raycastInfo.m_suspensionLength = wheel.m_suspensionRestLength;
  218. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  219. wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
  220. wheel.m_clippedInvContactDotSuspension = real_t(1.0);
  221. }
  222. return depth;
  223. }
  224. void VehicleBody::_update_suspension(PhysicsDirectBodyState *s)
  225. {
  226. real_t deltaTime = s->get_step();
  227. real_t chassisMass = mass;
  228. for (int w_it=0; w_it<wheels.size(); w_it++)
  229. {
  230. VehicleWheel& wheel_info = *wheels[w_it];
  231. if ( wheel_info.m_raycastInfo.m_isInContact )
  232. {
  233. real_t force;
  234. // Spring
  235. {
  236. real_t susp_length = wheel_info.m_suspensionRestLength;
  237. real_t current_length = wheel_info.m_raycastInfo.m_suspensionLength;
  238. real_t length_diff = (susp_length - current_length);
  239. force = wheel_info.m_suspensionStiffness
  240. * length_diff * wheel_info.m_clippedInvContactDotSuspension;
  241. }
  242. // Damper
  243. {
  244. real_t projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
  245. {
  246. real_t susp_damping;
  247. if ( projected_rel_vel < real_t(0.0) )
  248. {
  249. susp_damping = wheel_info.m_wheelsDampingCompression;
  250. }
  251. else
  252. {
  253. susp_damping = wheel_info.m_wheelsDampingRelaxation;
  254. }
  255. force -= susp_damping * projected_rel_vel;
  256. }
  257. }
  258. // RESULT
  259. wheel_info.m_wheelsSuspensionForce = force * chassisMass;
  260. if (wheel_info.m_wheelsSuspensionForce < real_t(0.))
  261. {
  262. wheel_info.m_wheelsSuspensionForce = real_t(0.);
  263. }
  264. }
  265. else
  266. {
  267. wheel_info.m_wheelsSuspensionForce = real_t(0.0);
  268. }
  269. }
  270. }
  271. //bilateral constraint between two dynamic objects
  272. void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3& pos1,
  273. PhysicsBody* body2, const Vector3& pos2, const Vector3& normal,real_t& impulse)
  274. {
  275. real_t normalLenSqr = normal.length_squared();
  276. //ERR_FAIL_COND( normalLenSqr < real_t(1.1));
  277. if (normalLenSqr > real_t(1.1))
  278. {
  279. impulse = real_t(0.);
  280. return;
  281. }
  282. Vector3 rel_pos1 = pos1 - s->get_transform().origin;
  283. Vector3 rel_pos2;
  284. if (body2)
  285. rel_pos2 = pos2 - body2->get_global_transform().origin;
  286. //this jacobian entry could be re-used for all iterations
  287. Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1);// * mPos);
  288. Vector3 vel2;
  289. if (body2)
  290. vel2=body2->get_linear_velocity() + body2->get_angular_velocity().cross(rel_pos2);
  291. Vector3 vel = vel1 - vel2;
  292. Matrix3 b2trans;
  293. float b2invmass=0;
  294. Vector3 b2lv;
  295. Vector3 b2av;
  296. Vector3 b2invinertia; //todo
  297. if (body2) {
  298. b2trans = body2->get_global_transform().basis.transposed();
  299. b2invmass = body2->get_inverse_mass();
  300. b2lv = body2->get_linear_velocity();
  301. b2av = body2->get_angular_velocity();
  302. }
  303. btVehicleJacobianEntry jac(s->get_transform().basis.transposed(),
  304. b2trans,
  305. rel_pos1,
  306. rel_pos2,
  307. normal,
  308. s->get_inverse_inertia(),
  309. 1.0/mass,
  310. b2invinertia,
  311. b2invmass);
  312. real_t jacDiagAB = jac.getDiagonal();
  313. real_t jacDiagABInv = real_t(1.) / jacDiagAB;
  314. real_t rel_vel = jac.getRelativeVelocity(
  315. s->get_linear_velocity(),
  316. s->get_transform().basis.transposed().xform(s->get_angular_velocity()),
  317. b2lv,
  318. b2trans.xform(b2av));
  319. real_t a;
  320. a=jacDiagABInv;
  321. rel_vel = normal.dot(vel);
  322. //todo: move this into proper structure
  323. real_t contactDamping = real_t(0.4);
  324. #define ONLY_USE_LINEAR_MASS
  325. #ifdef ONLY_USE_LINEAR_MASS
  326. real_t massTerm = real_t(1.) / ((1.0/mass) + b2invmass);
  327. impulse = - contactDamping * rel_vel * massTerm;
  328. #else
  329. real_t velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
  330. impulse = velocityImpulse;
  331. #endif
  332. }
  333. VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s,PhysicsBody* body1,const Vector3& frictionPosWorld,const Vector3& frictionDirectionWorld, real_t maxImpulse)
  334. :m_s(s),
  335. m_body1(body1),
  336. m_frictionPositionWorld(frictionPosWorld),
  337. m_frictionDirectionWorld(frictionDirectionWorld),
  338. m_maxImpulse(maxImpulse)
  339. {
  340. float denom0=0;
  341. float denom1=0;
  342. {
  343. Vector3 r0 = frictionPosWorld - s->get_transform().origin;
  344. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  345. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  346. denom0= s->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  347. }
  348. if (body1) {
  349. Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin;
  350. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  351. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  352. //denom1= body1->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  353. denom1=0;
  354. }
  355. real_t relaxation = 1.f;
  356. m_jacDiagABInv = relaxation/(denom0+denom1);
  357. }
  358. real_t VehicleBody::_calc_rolling_friction(btVehicleWheelContactPoint& contactPoint) {
  359. real_t j1=0.f;
  360. const Vector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
  361. Vector3 rel_pos1 = contactPosWorld - contactPoint.m_s->get_transform().origin;
  362. Vector3 rel_pos2;
  363. if (contactPoint.m_body1)
  364. rel_pos2 = contactPosWorld - contactPoint.m_body1->get_global_transform().origin;
  365. real_t maxImpulse = contactPoint.m_maxImpulse;
  366. Vector3 vel1 = contactPoint.m_s->get_linear_velocity() + (contactPoint.m_s->get_angular_velocity()).cross(rel_pos1);// * mPos);
  367. Vector3 vel2;
  368. if (contactPoint.m_body1) {
  369. vel2=contactPoint.m_body1->get_linear_velocity() + contactPoint.m_body1->get_angular_velocity().cross(rel_pos2);
  370. }
  371. Vector3 vel = vel1 - vel2;
  372. real_t vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
  373. // calculate j that moves us to zero relative velocity
  374. j1 = -vrel * contactPoint.m_jacDiagABInv;
  375. return CLAMP(j1,-maxImpulse,maxImpulse);
  376. }
  377. static const real_t sideFrictionStiffness2 = real_t(1.0);
  378. void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
  379. //calculate the impulse, so that the wheels don't move sidewards
  380. int numWheel = wheels.size();
  381. if (!numWheel)
  382. return;
  383. m_forwardWS.resize(numWheel);
  384. m_axle.resize(numWheel);
  385. m_forwardImpulse.resize(numWheel);
  386. m_sideImpulse.resize(numWheel);
  387. int numWheelsOnGround = 0;
  388. //collapse all those loops into one!
  389. for (int i=0;i<wheels.size();i++)
  390. {
  391. VehicleWheel& wheelInfo = *wheels[i];
  392. if (wheelInfo.m_raycastInfo.m_isInContact)
  393. numWheelsOnGround++;
  394. m_sideImpulse[i] = real_t(0.);
  395. m_forwardImpulse[i] = real_t(0.);
  396. }
  397. {
  398. for (int i=0;i<wheels.size();i++)
  399. {
  400. VehicleWheel& wheelInfo = *wheels[i];
  401. if (wheelInfo.m_raycastInfo.m_isInContact)
  402. {
  403. //const btTransform& wheelTrans = getWheelTransformWS( i );
  404. Matrix3 wheelBasis0 = wheelInfo.get_global_transform().basis;
  405. m_axle[i] = wheelBasis0.get_axis(Vector3::AXIS_X);
  406. m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS;
  407. const Vector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
  408. real_t proj = m_axle[i].dot(surfNormalWS);
  409. m_axle[i] -= surfNormalWS * proj;
  410. m_axle[i] = m_axle[i].normalized();
  411. m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
  412. m_forwardWS[i].normalize();
  413. _resolve_single_bilateral(s, wheelInfo.m_raycastInfo.m_contactPointWS,
  414. wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
  415. m_axle[i],m_sideImpulse[i]);
  416. m_sideImpulse[i] *= sideFrictionStiffness2;
  417. }
  418. }
  419. }
  420. real_t sideFactor = real_t(1.);
  421. real_t fwdFactor = 0.5;
  422. bool sliding = false;
  423. {
  424. for (int wheel =0;wheel <wheels.size();wheel++)
  425. {
  426. VehicleWheel& wheelInfo = *wheels[wheel];
  427. //class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  428. real_t rollingFriction = 0.f;
  429. if (wheelInfo.m_raycastInfo.m_isInContact)
  430. {
  431. if (wheelInfo.m_engineForce != 0.f)
  432. {
  433. rollingFriction = wheelInfo.m_engineForce* s->get_step();
  434. } else
  435. {
  436. real_t defaultRollingFrictionImpulse = 0.f;
  437. real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
  438. btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
  439. rollingFriction = _calc_rolling_friction(contactPt);
  440. }
  441. }
  442. //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
  443. m_forwardImpulse[wheel] = real_t(0.);
  444. wheelInfo.m_skidInfo= real_t(1.);
  445. if (wheelInfo.m_raycastInfo.m_isInContact)
  446. {
  447. wheelInfo.m_skidInfo= real_t(1.);
  448. real_t maximp = wheelInfo.m_wheelsSuspensionForce * s->get_step() * wheelInfo.m_frictionSlip;
  449. real_t maximpSide = maximp;
  450. real_t maximpSquared = maximp * maximpSide;
  451. m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
  452. real_t x = (m_forwardImpulse[wheel] ) * fwdFactor;
  453. real_t y = (m_sideImpulse[wheel] ) * sideFactor;
  454. real_t impulseSquared = (x*x + y*y);
  455. if (impulseSquared > maximpSquared)
  456. {
  457. sliding = true;
  458. real_t factor = maximp / Math::sqrt(impulseSquared);
  459. wheelInfo.m_skidInfo *= factor;
  460. }
  461. }
  462. }
  463. }
  464. if (sliding)
  465. {
  466. for (int wheel = 0;wheel < wheels.size(); wheel++)
  467. {
  468. if (m_sideImpulse[wheel] != real_t(0.))
  469. {
  470. if (wheels[wheel]->m_skidInfo< real_t(1.))
  471. {
  472. m_forwardImpulse[wheel] *= wheels[wheel]->m_skidInfo;
  473. m_sideImpulse[wheel] *= wheels[wheel]->m_skidInfo;
  474. }
  475. }
  476. }
  477. }
  478. // apply the impulses
  479. {
  480. for (int wheel = 0;wheel<wheels.size(); wheel++)
  481. {
  482. VehicleWheel& wheelInfo = *wheels[wheel];
  483. Vector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
  484. s->get_transform().origin;
  485. if (m_forwardImpulse[wheel] != real_t(0.))
  486. {
  487. s->apply_impulse(rel_pos,m_forwardWS[wheel]*(m_forwardImpulse[wheel]));
  488. }
  489. if (m_sideImpulse[wheel] != real_t(0.))
  490. {
  491. PhysicsBody* groundObject = wheelInfo.m_raycastInfo.m_groundObject;
  492. Vector3 rel_pos2;
  493. if (groundObject) {
  494. rel_pos2=wheelInfo.m_raycastInfo.m_contactPointWS - groundObject->get_global_transform().origin;
  495. }
  496. Vector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
  497. #if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
  498. Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1];//getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
  499. rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
  500. #else
  501. rel_pos[1] *= wheelInfo.m_rollInfluence; //?
  502. #endif
  503. s->apply_impulse(rel_pos,sideImp);
  504. //apply friction impulse on the ground
  505. //todo
  506. //groundObject->applyImpulse(-sideImp,rel_pos2);
  507. }
  508. }
  509. }
  510. }
  511. void VehicleBody::_direct_state_changed(Object *p_state) {
  512. PhysicsDirectBodyState *s = p_state->cast_to<PhysicsDirectBodyState>();
  513. set_ignore_transform_notification(true);
  514. set_global_transform(s->get_transform());
  515. set_ignore_transform_notification(false);
  516. float step = s->get_step();
  517. for(int i=0;i<wheels.size();i++) {
  518. _update_wheel(i,s);
  519. }
  520. for(int i=0;i<wheels.size();i++) {
  521. _ray_cast(i,s);
  522. }
  523. _update_suspension(s);
  524. for(int i=0;i<wheels.size();i++) {
  525. //apply suspension force
  526. VehicleWheel& wheel = *wheels[i];
  527. real_t suspensionForce = wheel.m_wheelsSuspensionForce;
  528. if (suspensionForce > wheel.m_maxSuspensionForce)
  529. {
  530. suspensionForce = wheel.m_maxSuspensionForce;
  531. }
  532. Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
  533. Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin;
  534. s->apply_impulse(relpos,impulse);
  535. //getRigidBody()->applyImpulse(impulse, relpos);
  536. }
  537. _update_friction(s);
  538. for (int i=0;i<wheels.size();i++)
  539. {
  540. VehicleWheel& wheel = *wheels[i];
  541. Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - s->get_transform().origin;
  542. Vector3 vel = s->get_linear_velocity() + (s->get_angular_velocity()).cross(relpos);// * mPos);
  543. if (wheel.m_raycastInfo.m_isInContact)
  544. {
  545. const Transform& chassisWorldTransform = s->get_transform();
  546. Vector3 fwd (
  547. chassisWorldTransform.basis[0][Vector3::AXIS_Z],
  548. chassisWorldTransform.basis[1][Vector3::AXIS_Z],
  549. chassisWorldTransform.basis[2][Vector3::AXIS_Z]);
  550. real_t proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
  551. fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
  552. real_t proj2 = fwd.dot(vel);
  553. wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelRadius);
  554. wheel.m_rotation += wheel.m_deltaRotation;
  555. } else
  556. {
  557. wheel.m_rotation += wheel.m_deltaRotation;
  558. }
  559. wheel.m_deltaRotation *= real_t(0.99);//damping of rotation when not in contact
  560. }
  561. }
  562. void VehicleBody::set_mass(real_t p_mass) {
  563. mass=p_mass;
  564. PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass);
  565. }
  566. real_t VehicleBody::get_mass() const{
  567. return mass;
  568. }
  569. void VehicleBody::set_friction(real_t p_friction) {
  570. friction=p_friction;
  571. PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction);
  572. }
  573. real_t VehicleBody::get_friction() const{
  574. return friction;
  575. }
  576. void VehicleBody::_bind_methods(){
  577. ObjectTypeDB::bind_method(_MD("set_mass","mass"),&VehicleBody::set_mass);
  578. ObjectTypeDB::bind_method(_MD("get_mass"),&VehicleBody::get_mass);
  579. ObjectTypeDB::bind_method(_MD("set_friction","friction"),&VehicleBody::set_friction);
  580. ObjectTypeDB::bind_method(_MD("get_friction"),&VehicleBody::get_friction);
  581. ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
  582. ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
  583. ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
  584. }
  585. VehicleBody::VehicleBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
  586. m_pitchControl=0;
  587. m_currentVehicleSpeedKmHour = real_t(0.);
  588. m_steeringValue = real_t(0.);
  589. mass=1;
  590. friction=1;
  591. ccd=false;
  592. exclude.insert(get_rid());
  593. PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed");
  594. }