vehicle_body.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. /*************************************************************************/
  2. /* vehicle_body.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "vehicle_body.h"
  31. #define ROLLING_INFLUENCE_FIX
  32. class btVehicleJacobianEntry {
  33. public:
  34. Vector3 m_linearJointAxis;
  35. Vector3 m_aJ;
  36. Vector3 m_bJ;
  37. Vector3 m_0MinvJt;
  38. Vector3 m_1MinvJt;
  39. //Optimization: can be stored in the w/last component of one of the vectors
  40. real_t m_Adiag;
  41. real_t getDiagonal() const { return m_Adiag; }
  42. btVehicleJacobianEntry(){};
  43. //constraint between two different rigidbodies
  44. btVehicleJacobianEntry(
  45. const Matrix3 &world2A,
  46. const Matrix3 &world2B,
  47. const Vector3 &rel_pos1,
  48. const Vector3 &rel_pos2,
  49. const Vector3 &jointAxis,
  50. const Vector3 &inertiaInvA,
  51. const real_t massInvA,
  52. const Vector3 &inertiaInvB,
  53. const real_t massInvB) :
  54. m_linearJointAxis(jointAxis) {
  55. m_aJ = world2A.xform(rel_pos1.cross(m_linearJointAxis));
  56. m_bJ = world2B.xform(rel_pos2.cross(-m_linearJointAxis));
  57. m_0MinvJt = inertiaInvA * m_aJ;
  58. m_1MinvJt = inertiaInvB * m_bJ;
  59. m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
  60. //btAssert(m_Adiag > real_t(0.0));
  61. }
  62. real_t getRelativeVelocity(const Vector3 &linvelA, const Vector3 &angvelA, const Vector3 &linvelB, const Vector3 &angvelB) {
  63. Vector3 linrel = linvelA - linvelB;
  64. Vector3 angvela = angvelA * m_aJ;
  65. Vector3 angvelb = angvelB * m_bJ;
  66. linrel *= m_linearJointAxis;
  67. angvela += angvelb;
  68. angvela += linrel;
  69. real_t rel_vel2 = angvela[0] + angvela[1] + angvela[2];
  70. return rel_vel2 + CMP_EPSILON;
  71. }
  72. };
  73. void VehicleWheel::_notification(int p_what) {
  74. if (p_what == NOTIFICATION_ENTER_TREE) {
  75. if (!get_parent())
  76. return;
  77. VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
  78. if (!cb)
  79. return;
  80. body = cb;
  81. local_xform = get_transform();
  82. cb->wheels.push_back(this);
  83. m_chassisConnectionPointCS = get_transform().origin;
  84. m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
  85. m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
  86. }
  87. if (p_what == NOTIFICATION_EXIT_TREE) {
  88. if (!get_parent())
  89. return;
  90. VehicleBody *cb = get_parent()->cast_to<VehicleBody>();
  91. if (!cb)
  92. return;
  93. cb->wheels.erase(this);
  94. body = NULL;
  95. }
  96. }
  97. void VehicleWheel::_update(PhysicsDirectBodyState *s) {
  98. if (m_raycastInfo.m_isInContact)
  99. {
  100. real_t project = m_raycastInfo.m_contactNormalWS.dot(m_raycastInfo.m_wheelDirectionWS);
  101. Vector3 chassis_velocity_at_contactPoint;
  102. Vector3 relpos = m_raycastInfo.m_contactPointWS - s->get_transform().origin;
  103. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  104. (s->get_angular_velocity()).cross(relpos); // * mPos);
  105. real_t projVel = m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
  106. if (project >= real_t(-0.1)) {
  107. m_suspensionRelativeVelocity = real_t(0.0);
  108. m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  109. } else {
  110. real_t inv = real_t(-1.) / project;
  111. m_suspensionRelativeVelocity = projVel * inv;
  112. m_clippedInvContactDotSuspension = inv;
  113. }
  114. }
  115. else // Not in contact : position wheel in a nice (rest length) position
  116. {
  117. m_raycastInfo.m_suspensionLength = m_suspensionRestLength;
  118. m_suspensionRelativeVelocity = real_t(0.0);
  119. m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
  120. m_clippedInvContactDotSuspension = real_t(1.0);
  121. }
  122. }
  123. void VehicleWheel::set_radius(float p_radius) {
  124. m_wheelRadius = p_radius;
  125. update_gizmo();
  126. }
  127. float VehicleWheel::get_radius() const {
  128. return m_wheelRadius;
  129. }
  130. void VehicleWheel::set_suspension_rest_length(float p_length) {
  131. m_suspensionRestLength = p_length;
  132. update_gizmo();
  133. }
  134. float VehicleWheel::get_suspension_rest_length() const {
  135. return m_suspensionRestLength;
  136. }
  137. void VehicleWheel::set_suspension_travel(float p_length) {
  138. m_maxSuspensionTravelCm = p_length / 0.01;
  139. }
  140. float VehicleWheel::get_suspension_travel() const {
  141. return m_maxSuspensionTravelCm * 0.01;
  142. }
  143. void VehicleWheel::set_suspension_stiffness(float p_value) {
  144. m_suspensionStiffness = p_value;
  145. }
  146. float VehicleWheel::get_suspension_stiffness() const {
  147. return m_suspensionStiffness;
  148. }
  149. void VehicleWheel::set_suspension_max_force(float p_value) {
  150. m_maxSuspensionForce = p_value;
  151. }
  152. float VehicleWheel::get_suspension_max_force() const {
  153. return m_maxSuspensionForce;
  154. }
  155. void VehicleWheel::set_damping_compression(float p_value) {
  156. m_wheelsDampingCompression = p_value;
  157. }
  158. float VehicleWheel::get_damping_compression() const {
  159. return m_wheelsDampingCompression;
  160. }
  161. void VehicleWheel::set_damping_relaxation(float p_value) {
  162. m_wheelsDampingRelaxation = p_value;
  163. }
  164. float VehicleWheel::get_damping_relaxation() const {
  165. return m_wheelsDampingRelaxation;
  166. }
  167. void VehicleWheel::set_friction_slip(float p_value) {
  168. m_frictionSlip = p_value;
  169. }
  170. float VehicleWheel::get_friction_slip() const {
  171. return m_frictionSlip;
  172. }
  173. void VehicleWheel::set_roll_influence(float p_value) {
  174. m_rollInfluence = p_value;
  175. }
  176. float VehicleWheel::get_roll_influence() const {
  177. return m_rollInfluence;
  178. }
  179. bool VehicleWheel::is_in_contact() const {
  180. return m_raycastInfo.m_isInContact;
  181. }
  182. void VehicleWheel::_bind_methods() {
  183. ObjectTypeDB::bind_method(_MD("set_radius", "length"), &VehicleWheel::set_radius);
  184. ObjectTypeDB::bind_method(_MD("get_radius"), &VehicleWheel::get_radius);
  185. ObjectTypeDB::bind_method(_MD("set_suspension_rest_length", "length"), &VehicleWheel::set_suspension_rest_length);
  186. ObjectTypeDB::bind_method(_MD("get_suspension_rest_length"), &VehicleWheel::get_suspension_rest_length);
  187. ObjectTypeDB::bind_method(_MD("set_suspension_travel", "length"), &VehicleWheel::set_suspension_travel);
  188. ObjectTypeDB::bind_method(_MD("get_suspension_travel"), &VehicleWheel::get_suspension_travel);
  189. ObjectTypeDB::bind_method(_MD("set_suspension_stiffness", "length"), &VehicleWheel::set_suspension_stiffness);
  190. ObjectTypeDB::bind_method(_MD("get_suspension_stiffness"), &VehicleWheel::get_suspension_stiffness);
  191. ObjectTypeDB::bind_method(_MD("set_suspension_max_force", "length"), &VehicleWheel::set_suspension_max_force);
  192. ObjectTypeDB::bind_method(_MD("get_suspension_max_force"), &VehicleWheel::get_suspension_max_force);
  193. ObjectTypeDB::bind_method(_MD("set_damping_compression", "length"), &VehicleWheel::set_damping_compression);
  194. ObjectTypeDB::bind_method(_MD("get_damping_compression"), &VehicleWheel::get_damping_compression);
  195. ObjectTypeDB::bind_method(_MD("set_damping_relaxation", "length"), &VehicleWheel::set_damping_relaxation);
  196. ObjectTypeDB::bind_method(_MD("get_damping_relaxation"), &VehicleWheel::get_damping_relaxation);
  197. ObjectTypeDB::bind_method(_MD("set_use_as_traction", "enable"), &VehicleWheel::set_use_as_traction);
  198. ObjectTypeDB::bind_method(_MD("is_used_as_traction"), &VehicleWheel::is_used_as_traction);
  199. ObjectTypeDB::bind_method(_MD("set_use_as_steering", "enable"), &VehicleWheel::set_use_as_steering);
  200. ObjectTypeDB::bind_method(_MD("is_used_as_steering"), &VehicleWheel::is_used_as_steering);
  201. ObjectTypeDB::bind_method(_MD("set_friction_slip", "length"), &VehicleWheel::set_friction_slip);
  202. ObjectTypeDB::bind_method(_MD("get_friction_slip"), &VehicleWheel::get_friction_slip);
  203. ObjectTypeDB::bind_method(_MD("is_in_contact"), &VehicleWheel::is_in_contact);
  204. ObjectTypeDB::bind_method(_MD("set_roll_influence", "roll_influence"), &VehicleWheel::set_roll_influence);
  205. ObjectTypeDB::bind_method(_MD("get_roll_influence"), &VehicleWheel::get_roll_influence);
  206. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "type/traction"), _SCS("set_use_as_traction"), _SCS("is_used_as_traction"));
  207. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "type/steering"), _SCS("set_use_as_steering"), _SCS("is_used_as_steering"));
  208. ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel/roll_influence"), _SCS("set_roll_influence"), _SCS("get_roll_influence"));
  209. ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel/radius"), _SCS("set_radius"), _SCS("get_radius"));
  210. ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel/rest_length"), _SCS("set_suspension_rest_length"), _SCS("get_suspension_rest_length"));
  211. ADD_PROPERTY(PropertyInfo(Variant::REAL, "wheel/friction_slip"), _SCS("set_friction_slip"), _SCS("get_friction_slip"));
  212. ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension/travel"), _SCS("set_suspension_travel"), _SCS("get_suspension_travel"));
  213. ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension/stiffness"), _SCS("set_suspension_stiffness"), _SCS("get_suspension_stiffness"));
  214. ADD_PROPERTY(PropertyInfo(Variant::REAL, "suspension/max_force"), _SCS("set_suspension_max_force"), _SCS("get_suspension_max_force"));
  215. ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping/compression"), _SCS("set_damping_compression"), _SCS("get_damping_compression"));
  216. ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping/relaxation"), _SCS("set_damping_relaxation"), _SCS("get_damping_relaxation"));
  217. }
  218. void VehicleWheel::set_use_as_traction(bool p_enable) {
  219. engine_traction = p_enable;
  220. }
  221. bool VehicleWheel::is_used_as_traction() const {
  222. return engine_traction;
  223. }
  224. void VehicleWheel::set_use_as_steering(bool p_enabled) {
  225. steers = p_enabled;
  226. }
  227. bool VehicleWheel::is_used_as_steering() const {
  228. return steers;
  229. }
  230. VehicleWheel::VehicleWheel() {
  231. steers = false;
  232. engine_traction = false;
  233. m_steering = real_t(0.);
  234. //m_engineForce = real_t(0.);
  235. m_rotation = real_t(0.);
  236. m_deltaRotation = real_t(0.);
  237. m_brake = real_t(0.);
  238. m_rollInfluence = real_t(0.1);
  239. m_suspensionRestLength = 0.15;
  240. m_wheelRadius = 0.5; //0.28;
  241. m_suspensionStiffness = 5.88;
  242. m_wheelsDampingCompression = 0.83;
  243. m_wheelsDampingRelaxation = 0.88;
  244. m_frictionSlip = 10.5;
  245. m_bIsFrontWheel = false;
  246. m_maxSuspensionTravelCm = 500;
  247. m_maxSuspensionForce = 6000;
  248. m_suspensionRelativeVelocity = 0;
  249. m_clippedInvContactDotSuspension = 1.0;
  250. m_raycastInfo.m_isInContact = false;
  251. body = NULL;
  252. }
  253. void VehicleBody::_update_wheel_transform(VehicleWheel &wheel, PhysicsDirectBodyState *s) {
  254. wheel.m_raycastInfo.m_isInContact = false;
  255. Transform chassisTrans = s->get_transform();
  256. //if (interpolatedTransform && (getRigidBody()->getMotionState()))
  257. //{
  258. // getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
  259. //}
  260. wheel.m_raycastInfo.m_hardPointWS = chassisTrans.xform(wheel.m_chassisConnectionPointCS);
  261. //wheel.m_raycastInfo.m_hardPointWS+=s->get_linear_velocity()*s->get_step();
  262. wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.get_basis().xform(wheel.m_wheelDirectionCS).normalized();
  263. wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform(wheel.m_wheelAxleCS).normalized();
  264. }
  265. void VehicleBody::_update_wheel(int p_idx, PhysicsDirectBodyState *s) {
  266. VehicleWheel &wheel = *wheels[p_idx];
  267. _update_wheel_transform(wheel, s);
  268. Vector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
  269. const Vector3 &right = wheel.m_raycastInfo.m_wheelAxleWS;
  270. Vector3 fwd = up.cross(right);
  271. fwd = fwd.normalized();
  272. // up = right.cross(fwd);
  273. // up.normalize();
  274. //rotate around steering over de wheelAxleWS
  275. real_t steering = wheel.steers ? m_steeringValue : 0.0;
  276. //print_line(itos(p_idx)+": "+rtos(steering));
  277. Matrix3 steeringMat(up, steering);
  278. Matrix3 rotatingMat(right, -wheel.m_rotation);
  279. // if (p_idx==1)
  280. // print_line("steeringMat " +steeringMat);
  281. Matrix3 basis2(
  282. right[0], up[0], fwd[0],
  283. right[1], up[1], fwd[1],
  284. right[2], up[2], fwd[2]);
  285. wheel.m_worldTransform.set_basis(steeringMat * rotatingMat * basis2);
  286. //wheel.m_worldTransform.set_basis(basis2 * (steeringMat * rotatingMat));
  287. wheel.m_worldTransform.set_origin(
  288. wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength);
  289. }
  290. real_t VehicleBody::_ray_cast(int p_idx, PhysicsDirectBodyState *s) {
  291. VehicleWheel &wheel = *wheels[p_idx];
  292. _update_wheel_transform(wheel, s);
  293. real_t depth = -1;
  294. real_t raylen = wheel.m_suspensionRestLength + wheel.m_wheelRadius;
  295. Vector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
  296. Vector3 source = wheel.m_raycastInfo.m_hardPointWS;
  297. wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
  298. const Vector3 &target = wheel.m_raycastInfo.m_contactPointWS;
  299. source -= wheel.m_wheelRadius * wheel.m_raycastInfo.m_wheelDirectionWS;
  300. real_t param = real_t(0.);
  301. PhysicsDirectSpaceState::RayResult rr;
  302. PhysicsDirectSpaceState *ss = s->get_space_state();
  303. bool col = ss->intersect_ray(source, target, rr, exclude);
  304. wheel.m_raycastInfo.m_groundObject = 0;
  305. if (col) {
  306. //print_line("WHEEL "+itos(p_idx)+" FROM "+source+" TO: "+target);
  307. //print_line("WHEEL "+itos(p_idx)+" COLLIDE? "+itos(col));
  308. param = source.distance_to(rr.position) / source.distance_to(target);
  309. depth = raylen * param;
  310. wheel.m_raycastInfo.m_contactNormalWS = rr.normal;
  311. wheel.m_raycastInfo.m_isInContact = true;
  312. if (rr.collider)
  313. wheel.m_raycastInfo.m_groundObject = rr.collider->cast_to<PhysicsBody>();
  314. real_t hitDistance = param * raylen;
  315. wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
  316. //clamp on max suspension travel
  317. real_t minSuspensionLength = wheel.m_suspensionRestLength - wheel.m_maxSuspensionTravelCm * real_t(0.01);
  318. real_t maxSuspensionLength = wheel.m_suspensionRestLength + wheel.m_maxSuspensionTravelCm * real_t(0.01);
  319. if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) {
  320. wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
  321. }
  322. if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) {
  323. wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
  324. }
  325. wheel.m_raycastInfo.m_contactPointWS = rr.position;
  326. real_t denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(wheel.m_raycastInfo.m_wheelDirectionWS);
  327. Vector3 chassis_velocity_at_contactPoint;
  328. //Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
  329. //chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
  330. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  331. (s->get_angular_velocity()).cross(wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin); // * mPos);
  332. real_t projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
  333. if (denominator >= real_t(-0.1)) {
  334. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  335. wheel.m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  336. } else {
  337. real_t inv = real_t(-1.) / denominator;
  338. wheel.m_suspensionRelativeVelocity = projVel * inv;
  339. wheel.m_clippedInvContactDotSuspension = inv;
  340. }
  341. } else {
  342. wheel.m_raycastInfo.m_isInContact = false;
  343. //put wheel info as in rest position
  344. wheel.m_raycastInfo.m_suspensionLength = wheel.m_suspensionRestLength;
  345. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  346. wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
  347. wheel.m_clippedInvContactDotSuspension = real_t(1.0);
  348. }
  349. return depth;
  350. }
  351. void VehicleBody::_update_suspension(PhysicsDirectBodyState *s) {
  352. real_t chassisMass = mass;
  353. for (int w_it = 0; w_it < wheels.size(); w_it++) {
  354. VehicleWheel &wheel_info = *wheels[w_it];
  355. if (wheel_info.m_raycastInfo.m_isInContact) {
  356. real_t force;
  357. // Spring
  358. {
  359. real_t susp_length = wheel_info.m_suspensionRestLength;
  360. real_t current_length = wheel_info.m_raycastInfo.m_suspensionLength;
  361. real_t length_diff = (susp_length - current_length);
  362. force = wheel_info.m_suspensionStiffness * length_diff * wheel_info.m_clippedInvContactDotSuspension;
  363. }
  364. // Damper
  365. {
  366. real_t projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
  367. {
  368. real_t susp_damping;
  369. if (projected_rel_vel < real_t(0.0)) {
  370. susp_damping = wheel_info.m_wheelsDampingCompression;
  371. } else {
  372. susp_damping = wheel_info.m_wheelsDampingRelaxation;
  373. }
  374. force -= susp_damping * projected_rel_vel;
  375. }
  376. }
  377. // RESULT
  378. wheel_info.m_wheelsSuspensionForce = force * chassisMass;
  379. if (wheel_info.m_wheelsSuspensionForce < real_t(0.)) {
  380. wheel_info.m_wheelsSuspensionForce = real_t(0.);
  381. }
  382. } else {
  383. wheel_info.m_wheelsSuspensionForce = real_t(0.0);
  384. }
  385. }
  386. }
  387. //bilateral constraint between two dynamic objects
  388. void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1,
  389. PhysicsBody *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse) {
  390. real_t normalLenSqr = normal.length_squared();
  391. //ERR_FAIL_COND( normalLenSqr < real_t(1.1));
  392. if (normalLenSqr > real_t(1.1)) {
  393. impulse = real_t(0.);
  394. return;
  395. }
  396. Vector3 rel_pos1 = pos1 - s->get_transform().origin;
  397. Vector3 rel_pos2;
  398. if (body2)
  399. rel_pos2 = pos2 - body2->get_global_transform().origin;
  400. //this jacobian entry could be re-used for all iterations
  401. Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1); // * mPos);
  402. Vector3 vel2;
  403. if (body2)
  404. vel2 = body2->get_linear_velocity() + body2->get_angular_velocity().cross(rel_pos2);
  405. Vector3 vel = vel1 - vel2;
  406. Matrix3 b2trans;
  407. float b2invmass = 0;
  408. Vector3 b2lv;
  409. Vector3 b2av;
  410. Vector3 b2invinertia; //todo
  411. if (body2) {
  412. b2trans = body2->get_global_transform().basis.transposed();
  413. b2invmass = body2->get_inverse_mass();
  414. b2lv = body2->get_linear_velocity();
  415. b2av = body2->get_angular_velocity();
  416. }
  417. btVehicleJacobianEntry jac(s->get_transform().basis.transposed(),
  418. b2trans,
  419. rel_pos1,
  420. rel_pos2,
  421. normal,
  422. s->get_inverse_inertia(),
  423. 1.0 / mass,
  424. b2invinertia,
  425. b2invmass);
  426. real_t rel_vel = jac.getRelativeVelocity(
  427. s->get_linear_velocity(),
  428. s->get_transform().basis.transposed().xform(s->get_angular_velocity()),
  429. b2lv,
  430. b2trans.xform(b2av));
  431. rel_vel = normal.dot(vel);
  432. //TODO: move this into proper structure
  433. real_t contactDamping = real_t(0.4);
  434. #define ONLY_USE_LINEAR_MASS
  435. #ifdef ONLY_USE_LINEAR_MASS
  436. real_t massTerm = real_t(1.) / ((1.0 / mass) + b2invmass);
  437. impulse = -contactDamping * rel_vel * massTerm;
  438. #else
  439. real_t velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
  440. impulse = velocityImpulse;
  441. #endif
  442. }
  443. VehicleBody::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) :
  444. m_s(s),
  445. m_body1(body1),
  446. m_frictionPositionWorld(frictionPosWorld),
  447. m_frictionDirectionWorld(frictionDirectionWorld),
  448. m_maxImpulse(maxImpulse) {
  449. float denom0 = 0;
  450. float denom1 = 0;
  451. {
  452. Vector3 r0 = frictionPosWorld - s->get_transform().origin;
  453. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  454. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  455. denom0 = s->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  456. }
  457. /* TODO: Why is this code unused?
  458. if (body1) {
  459. Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin;
  460. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  461. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  462. //denom1= body1->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  463. }
  464. */
  465. real_t relaxation = 1.f;
  466. m_jacDiagABInv = relaxation / (denom0 + denom1);
  467. }
  468. real_t VehicleBody::_calc_rolling_friction(btVehicleWheelContactPoint &contactPoint) {
  469. real_t j1 = 0.f;
  470. const Vector3 &contactPosWorld = contactPoint.m_frictionPositionWorld;
  471. Vector3 rel_pos1 = contactPosWorld - contactPoint.m_s->get_transform().origin;
  472. Vector3 rel_pos2;
  473. if (contactPoint.m_body1)
  474. rel_pos2 = contactPosWorld - contactPoint.m_body1->get_global_transform().origin;
  475. real_t maxImpulse = contactPoint.m_maxImpulse;
  476. Vector3 vel1 = contactPoint.m_s->get_linear_velocity() + (contactPoint.m_s->get_angular_velocity()).cross(rel_pos1); // * mPos);
  477. Vector3 vel2;
  478. if (contactPoint.m_body1) {
  479. vel2 = contactPoint.m_body1->get_linear_velocity() + contactPoint.m_body1->get_angular_velocity().cross(rel_pos2);
  480. }
  481. Vector3 vel = vel1 - vel2;
  482. real_t vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
  483. // calculate j that moves us to zero relative velocity
  484. j1 = -vrel * contactPoint.m_jacDiagABInv;
  485. return CLAMP(j1, -maxImpulse, maxImpulse);
  486. }
  487. static const real_t sideFrictionStiffness2 = real_t(1.0);
  488. void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
  489. //calculate the impulse, so that the wheels don't move sidewards
  490. int numWheel = wheels.size();
  491. if (!numWheel)
  492. return;
  493. m_forwardWS.resize(numWheel);
  494. m_axle.resize(numWheel);
  495. m_forwardImpulse.resize(numWheel);
  496. m_sideImpulse.resize(numWheel);
  497. int numWheelsOnGround = 0;
  498. //collapse all those loops into one!
  499. for (int i = 0; i < wheels.size(); i++) {
  500. VehicleWheel &wheelInfo = *wheels[i];
  501. if (wheelInfo.m_raycastInfo.m_isInContact)
  502. numWheelsOnGround++;
  503. m_sideImpulse[i] = real_t(0.);
  504. m_forwardImpulse[i] = real_t(0.);
  505. }
  506. {
  507. for (int i = 0; i < wheels.size(); i++) {
  508. VehicleWheel &wheelInfo = *wheels[i];
  509. if (wheelInfo.m_raycastInfo.m_isInContact) {
  510. //const btTransform& wheelTrans = getWheelTransformWS( i );
  511. Matrix3 wheelBasis0 = wheelInfo.m_worldTransform.basis; //get_global_transform().basis;
  512. m_axle[i] = wheelBasis0.get_axis(Vector3::AXIS_X);
  513. //m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS;
  514. const Vector3 &surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
  515. real_t proj = m_axle[i].dot(surfNormalWS);
  516. m_axle[i] -= surfNormalWS * proj;
  517. m_axle[i] = m_axle[i].normalized();
  518. m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
  519. m_forwardWS[i].normalize();
  520. _resolve_single_bilateral(s, wheelInfo.m_raycastInfo.m_contactPointWS,
  521. wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
  522. m_axle[i], m_sideImpulse[i]);
  523. m_sideImpulse[i] *= sideFrictionStiffness2;
  524. }
  525. }
  526. }
  527. real_t sideFactor = real_t(1.);
  528. real_t fwdFactor = 0.5;
  529. bool sliding = false;
  530. {
  531. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  532. VehicleWheel &wheelInfo = *wheels[wheel];
  533. //class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  534. real_t rollingFriction = 0.f;
  535. if (wheelInfo.m_raycastInfo.m_isInContact) {
  536. if (engine_force != 0.f) {
  537. rollingFriction = -engine_force * s->get_step();
  538. } else {
  539. real_t defaultRollingFrictionImpulse = 0.f;
  540. float cbrake = MAX(wheelInfo.m_brake, brake);
  541. real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse;
  542. btVehicleWheelContactPoint contactPt(s, wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
  543. rollingFriction = _calc_rolling_friction(contactPt);
  544. }
  545. }
  546. //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
  547. m_forwardImpulse[wheel] = real_t(0.);
  548. wheelInfo.m_skidInfo = real_t(1.);
  549. if (wheelInfo.m_raycastInfo.m_isInContact) {
  550. wheelInfo.m_skidInfo = real_t(1.);
  551. real_t maximp = wheelInfo.m_wheelsSuspensionForce * s->get_step() * wheelInfo.m_frictionSlip;
  552. real_t maximpSide = maximp;
  553. real_t maximpSquared = maximp * maximpSide;
  554. m_forwardImpulse[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep;
  555. real_t x = (m_forwardImpulse[wheel]) * fwdFactor;
  556. real_t y = (m_sideImpulse[wheel]) * sideFactor;
  557. real_t impulseSquared = (x * x + y * y);
  558. if (impulseSquared > maximpSquared) {
  559. sliding = true;
  560. real_t factor = maximp / Math::sqrt(impulseSquared);
  561. wheelInfo.m_skidInfo *= factor;
  562. }
  563. }
  564. }
  565. }
  566. if (sliding) {
  567. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  568. if (m_sideImpulse[wheel] != real_t(0.)) {
  569. if (wheels[wheel]->m_skidInfo < real_t(1.)) {
  570. m_forwardImpulse[wheel] *= wheels[wheel]->m_skidInfo;
  571. m_sideImpulse[wheel] *= wheels[wheel]->m_skidInfo;
  572. }
  573. }
  574. }
  575. }
  576. // apply the impulses
  577. {
  578. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  579. VehicleWheel &wheelInfo = *wheels[wheel];
  580. Vector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
  581. s->get_transform().origin;
  582. if (m_forwardImpulse[wheel] != real_t(0.)) {
  583. s->apply_impulse(rel_pos, m_forwardWS[wheel] * (m_forwardImpulse[wheel]));
  584. }
  585. if (m_sideImpulse[wheel] != real_t(0.)) {
  586. PhysicsBody *groundObject = wheelInfo.m_raycastInfo.m_groundObject;
  587. Vector3 rel_pos2;
  588. if (groundObject) {
  589. rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - groundObject->get_global_transform().origin;
  590. }
  591. Vector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
  592. #if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
  593. Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1]; //getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
  594. rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
  595. #else
  596. rel_pos[1] *= wheelInfo.m_rollInfluence; //?
  597. #endif
  598. s->apply_impulse(rel_pos, sideImp);
  599. //apply friction impulse on the ground
  600. //todo
  601. //groundObject->applyImpulse(-sideImp,rel_pos2);
  602. }
  603. }
  604. }
  605. }
  606. void VehicleBody::_direct_state_changed(Object *p_state) {
  607. PhysicsDirectBodyState *s = p_state->cast_to<PhysicsDirectBodyState>();
  608. set_ignore_transform_notification(true);
  609. set_global_transform(s->get_transform());
  610. set_ignore_transform_notification(false);
  611. float step = s->get_step();
  612. for (int i = 0; i < wheels.size(); i++) {
  613. _update_wheel(i, s);
  614. }
  615. for (int i = 0; i < wheels.size(); i++) {
  616. _ray_cast(i, s);
  617. wheels[i]->set_transform(s->get_transform().inverse() * wheels[i]->m_worldTransform);
  618. }
  619. _update_suspension(s);
  620. for (int i = 0; i < wheels.size(); i++) {
  621. //apply suspension force
  622. VehicleWheel &wheel = *wheels[i];
  623. real_t suspensionForce = wheel.m_wheelsSuspensionForce;
  624. if (suspensionForce > wheel.m_maxSuspensionForce) {
  625. suspensionForce = wheel.m_maxSuspensionForce;
  626. }
  627. Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
  628. Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin;
  629. s->apply_impulse(relpos, impulse);
  630. //getRigidBody()->applyImpulse(impulse, relpos);
  631. }
  632. _update_friction(s);
  633. for (int i = 0; i < wheels.size(); i++) {
  634. VehicleWheel &wheel = *wheels[i];
  635. Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - s->get_transform().origin;
  636. Vector3 vel = s->get_linear_velocity() + (s->get_angular_velocity()).cross(relpos); // * mPos);
  637. if (wheel.m_raycastInfo.m_isInContact) {
  638. const Transform &chassisWorldTransform = s->get_transform();
  639. Vector3 fwd(
  640. chassisWorldTransform.basis[0][Vector3::AXIS_Z],
  641. chassisWorldTransform.basis[1][Vector3::AXIS_Z],
  642. chassisWorldTransform.basis[2][Vector3::AXIS_Z]);
  643. real_t proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
  644. fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
  645. real_t proj2 = fwd.dot(vel);
  646. wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelRadius);
  647. wheel.m_rotation += wheel.m_deltaRotation;
  648. } else {
  649. wheel.m_rotation += wheel.m_deltaRotation;
  650. }
  651. wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact
  652. }
  653. linear_velocity = s->get_linear_velocity();
  654. }
  655. void VehicleBody::set_mass(real_t p_mass) {
  656. mass = p_mass;
  657. PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass);
  658. }
  659. real_t VehicleBody::get_mass() const {
  660. return mass;
  661. }
  662. void VehicleBody::set_friction(real_t p_friction) {
  663. friction = p_friction;
  664. PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction);
  665. }
  666. real_t VehicleBody::get_friction() const {
  667. return friction;
  668. }
  669. void VehicleBody::set_engine_force(float p_force) {
  670. engine_force = p_force;
  671. }
  672. float VehicleBody::get_engine_force() const {
  673. return engine_force;
  674. }
  675. void VehicleBody::set_brake(float p_brake) {
  676. brake = p_brake;
  677. }
  678. float VehicleBody::get_brake() const {
  679. return brake;
  680. }
  681. void VehicleBody::set_steering(float p_steering) {
  682. m_steeringValue = p_steering;
  683. }
  684. float VehicleBody::get_steering() const {
  685. return m_steeringValue;
  686. }
  687. Vector3 VehicleBody::get_linear_velocity() const {
  688. return linear_velocity;
  689. }
  690. void VehicleBody::_bind_methods() {
  691. ObjectTypeDB::bind_method(_MD("set_mass", "mass"), &VehicleBody::set_mass);
  692. ObjectTypeDB::bind_method(_MD("get_mass"), &VehicleBody::get_mass);
  693. ObjectTypeDB::bind_method(_MD("set_friction", "friction"), &VehicleBody::set_friction);
  694. ObjectTypeDB::bind_method(_MD("get_friction"), &VehicleBody::get_friction);
  695. ObjectTypeDB::bind_method(_MD("set_engine_force", "engine_force"), &VehicleBody::set_engine_force);
  696. ObjectTypeDB::bind_method(_MD("get_engine_force"), &VehicleBody::get_engine_force);
  697. ObjectTypeDB::bind_method(_MD("set_brake", "brake"), &VehicleBody::set_brake);
  698. ObjectTypeDB::bind_method(_MD("get_brake"), &VehicleBody::get_brake);
  699. ObjectTypeDB::bind_method(_MD("set_steering", "steering"), &VehicleBody::set_steering);
  700. ObjectTypeDB::bind_method(_MD("get_steering"), &VehicleBody::get_steering);
  701. ObjectTypeDB::bind_method(_MD("get_linear_velocity"), &VehicleBody::get_linear_velocity);
  702. ObjectTypeDB::bind_method(_MD("_direct_state_changed"), &VehicleBody::_direct_state_changed);
  703. ADD_PROPERTY(PropertyInfo(Variant::REAL, "motion/engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01"), _SCS("set_engine_force"), _SCS("get_engine_force"));
  704. ADD_PROPERTY(PropertyInfo(Variant::REAL, "motion/brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), _SCS("set_brake"), _SCS("get_brake"));
  705. ADD_PROPERTY(PropertyInfo(Variant::REAL, "motion/steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), _SCS("set_steering"), _SCS("get_steering"));
  706. ADD_PROPERTY(PropertyInfo(Variant::REAL, "body/mass", PROPERTY_HINT_RANGE, "0.01,65536,0.01"), _SCS("set_mass"), _SCS("get_mass"));
  707. ADD_PROPERTY(PropertyInfo(Variant::REAL, "body/friction", PROPERTY_HINT_RANGE, "0.01,1,0.01"), _SCS("set_friction"), _SCS("get_friction"));
  708. }
  709. VehicleBody::VehicleBody() :
  710. PhysicsBody(PhysicsServer::BODY_MODE_RIGID) {
  711. m_pitchControl = 0;
  712. m_currentVehicleSpeedKmHour = real_t(0.);
  713. m_steeringValue = real_t(0.);
  714. engine_force = 0;
  715. brake = 0;
  716. friction = 1;
  717. ccd = false;
  718. exclude.insert(get_rid());
  719. PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
  720. set_mass(40);
  721. }