vehicle_body_3d.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /**************************************************************************/
  2. /* vehicle_body_3d.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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_3d.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 = 0.0;
  41. real_t getDiagonal() const { return m_Adiag; }
  42. btVehicleJacobianEntry() {}
  43. //constraint between two different rigidbodies
  44. btVehicleJacobianEntry(
  45. const Basis &world2A,
  46. const Basis &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 VehicleWheel3D::_notification(int p_what) {
  74. switch (p_what) {
  75. case NOTIFICATION_ENTER_TREE: {
  76. VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
  77. if (!cb) {
  78. return;
  79. }
  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_column(Vector3::AXIS_Y).normalized();
  85. m_wheelAxleCS = get_transform().basis.get_column(Vector3::AXIS_X).normalized();
  86. } break;
  87. case NOTIFICATION_EXIT_TREE: {
  88. VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
  89. if (!cb) {
  90. return;
  91. }
  92. cb->wheels.erase(this);
  93. body = nullptr;
  94. } break;
  95. }
  96. }
  97. PackedStringArray VehicleWheel3D::get_configuration_warnings() const {
  98. PackedStringArray warnings = Node3D::get_configuration_warnings();
  99. if (!Object::cast_to<VehicleBody3D>(get_parent())) {
  100. warnings.push_back(RTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D."));
  101. }
  102. return warnings;
  103. }
  104. void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) {
  105. if (m_raycastInfo.m_isInContact) {
  106. real_t project = m_raycastInfo.m_contactNormalWS.dot(m_raycastInfo.m_wheelDirectionWS);
  107. Vector3 chassis_velocity_at_contactPoint;
  108. Vector3 relpos = m_raycastInfo.m_contactPointWS - s->get_transform().origin;
  109. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  110. (s->get_angular_velocity()).cross(relpos); // * mPos);
  111. real_t projVel = m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
  112. if (project >= real_t(-0.1)) {
  113. m_suspensionRelativeVelocity = real_t(0.0);
  114. m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  115. } else {
  116. real_t inv = real_t(-1.) / project;
  117. m_suspensionRelativeVelocity = projVel * inv;
  118. m_clippedInvContactDotSuspension = inv;
  119. }
  120. } else { // Not in contact : position wheel in a nice (rest length) position
  121. m_raycastInfo.m_suspensionLength = m_suspensionRestLength;
  122. m_suspensionRelativeVelocity = real_t(0.0);
  123. m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
  124. m_clippedInvContactDotSuspension = real_t(1.0);
  125. }
  126. }
  127. void VehicleWheel3D::set_radius(real_t p_radius) {
  128. m_wheelRadius = p_radius;
  129. update_gizmos();
  130. }
  131. real_t VehicleWheel3D::get_radius() const {
  132. return m_wheelRadius;
  133. }
  134. void VehicleWheel3D::set_suspension_rest_length(real_t p_length) {
  135. m_suspensionRestLength = p_length;
  136. update_gizmos();
  137. }
  138. real_t VehicleWheel3D::get_suspension_rest_length() const {
  139. return m_suspensionRestLength;
  140. }
  141. void VehicleWheel3D::set_suspension_travel(real_t p_length) {
  142. m_maxSuspensionTravel = p_length;
  143. }
  144. real_t VehicleWheel3D::get_suspension_travel() const {
  145. return m_maxSuspensionTravel;
  146. }
  147. void VehicleWheel3D::set_suspension_stiffness(real_t p_value) {
  148. m_suspensionStiffness = p_value;
  149. }
  150. real_t VehicleWheel3D::get_suspension_stiffness() const {
  151. return m_suspensionStiffness;
  152. }
  153. void VehicleWheel3D::set_suspension_max_force(real_t p_value) {
  154. m_maxSuspensionForce = p_value;
  155. }
  156. real_t VehicleWheel3D::get_suspension_max_force() const {
  157. return m_maxSuspensionForce;
  158. }
  159. void VehicleWheel3D::set_damping_compression(real_t p_value) {
  160. m_wheelsDampingCompression = p_value;
  161. }
  162. real_t VehicleWheel3D::get_damping_compression() const {
  163. return m_wheelsDampingCompression;
  164. }
  165. void VehicleWheel3D::set_damping_relaxation(real_t p_value) {
  166. m_wheelsDampingRelaxation = p_value;
  167. }
  168. real_t VehicleWheel3D::get_damping_relaxation() const {
  169. return m_wheelsDampingRelaxation;
  170. }
  171. void VehicleWheel3D::set_friction_slip(real_t p_value) {
  172. m_frictionSlip = p_value;
  173. }
  174. real_t VehicleWheel3D::get_friction_slip() const {
  175. return m_frictionSlip;
  176. }
  177. void VehicleWheel3D::set_roll_influence(real_t p_value) {
  178. m_rollInfluence = p_value;
  179. }
  180. real_t VehicleWheel3D::get_roll_influence() const {
  181. return m_rollInfluence;
  182. }
  183. bool VehicleWheel3D::is_in_contact() const {
  184. return m_raycastInfo.m_isInContact;
  185. }
  186. Vector3 VehicleWheel3D::get_contact_point() const {
  187. return m_raycastInfo.m_contactPointWS;
  188. }
  189. Vector3 VehicleWheel3D::get_contact_normal() const {
  190. return m_raycastInfo.m_contactNormalWS;
  191. }
  192. Node3D *VehicleWheel3D::get_contact_body() const {
  193. return m_raycastInfo.m_groundObject;
  194. }
  195. void VehicleWheel3D::_bind_methods() {
  196. ClassDB::bind_method(D_METHOD("set_radius", "length"), &VehicleWheel3D::set_radius);
  197. ClassDB::bind_method(D_METHOD("get_radius"), &VehicleWheel3D::get_radius);
  198. ClassDB::bind_method(D_METHOD("set_suspension_rest_length", "length"), &VehicleWheel3D::set_suspension_rest_length);
  199. ClassDB::bind_method(D_METHOD("get_suspension_rest_length"), &VehicleWheel3D::get_suspension_rest_length);
  200. ClassDB::bind_method(D_METHOD("set_suspension_travel", "length"), &VehicleWheel3D::set_suspension_travel);
  201. ClassDB::bind_method(D_METHOD("get_suspension_travel"), &VehicleWheel3D::get_suspension_travel);
  202. ClassDB::bind_method(D_METHOD("set_suspension_stiffness", "length"), &VehicleWheel3D::set_suspension_stiffness);
  203. ClassDB::bind_method(D_METHOD("get_suspension_stiffness"), &VehicleWheel3D::get_suspension_stiffness);
  204. ClassDB::bind_method(D_METHOD("set_suspension_max_force", "length"), &VehicleWheel3D::set_suspension_max_force);
  205. ClassDB::bind_method(D_METHOD("get_suspension_max_force"), &VehicleWheel3D::get_suspension_max_force);
  206. ClassDB::bind_method(D_METHOD("set_damping_compression", "length"), &VehicleWheel3D::set_damping_compression);
  207. ClassDB::bind_method(D_METHOD("get_damping_compression"), &VehicleWheel3D::get_damping_compression);
  208. ClassDB::bind_method(D_METHOD("set_damping_relaxation", "length"), &VehicleWheel3D::set_damping_relaxation);
  209. ClassDB::bind_method(D_METHOD("get_damping_relaxation"), &VehicleWheel3D::get_damping_relaxation);
  210. ClassDB::bind_method(D_METHOD("set_use_as_traction", "enable"), &VehicleWheel3D::set_use_as_traction);
  211. ClassDB::bind_method(D_METHOD("is_used_as_traction"), &VehicleWheel3D::is_used_as_traction);
  212. ClassDB::bind_method(D_METHOD("set_use_as_steering", "enable"), &VehicleWheel3D::set_use_as_steering);
  213. ClassDB::bind_method(D_METHOD("is_used_as_steering"), &VehicleWheel3D::is_used_as_steering);
  214. ClassDB::bind_method(D_METHOD("set_friction_slip", "length"), &VehicleWheel3D::set_friction_slip);
  215. ClassDB::bind_method(D_METHOD("get_friction_slip"), &VehicleWheel3D::get_friction_slip);
  216. ClassDB::bind_method(D_METHOD("is_in_contact"), &VehicleWheel3D::is_in_contact);
  217. ClassDB::bind_method(D_METHOD("get_contact_body"), &VehicleWheel3D::get_contact_body);
  218. ClassDB::bind_method(D_METHOD("get_contact_point"), &VehicleWheel3D::get_contact_point);
  219. ClassDB::bind_method(D_METHOD("get_contact_normal"), &VehicleWheel3D::get_contact_normal);
  220. ClassDB::bind_method(D_METHOD("set_roll_influence", "roll_influence"), &VehicleWheel3D::set_roll_influence);
  221. ClassDB::bind_method(D_METHOD("get_roll_influence"), &VehicleWheel3D::get_roll_influence);
  222. ClassDB::bind_method(D_METHOD("get_skidinfo"), &VehicleWheel3D::get_skidinfo);
  223. ClassDB::bind_method(D_METHOD("get_rpm"), &VehicleWheel3D::get_rpm);
  224. ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleWheel3D::set_engine_force);
  225. ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleWheel3D::get_engine_force);
  226. ClassDB::bind_method(D_METHOD("set_brake", "brake"), &VehicleWheel3D::set_brake);
  227. ClassDB::bind_method(D_METHOD("get_brake"), &VehicleWheel3D::get_brake);
  228. ClassDB::bind_method(D_METHOD("set_steering", "steering"), &VehicleWheel3D::set_steering);
  229. ClassDB::bind_method(D_METHOD("get_steering"), &VehicleWheel3D::get_steering);
  230. ADD_GROUP("Per-Wheel Motion", "");
  231. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "engine_force", PROPERTY_HINT_RANGE, U"-1024,1024,0.01,or_less,or_greater,suffix:kg\u22C5m/s\u00B2 (N)"), "set_engine_force", "get_engine_force");
  232. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "brake", PROPERTY_HINT_RANGE, U"-128,128,0.01,or_less,or_greater,suffix:kg\u22C5m/s\u00B2 (N)"), "set_brake", "get_brake");
  233. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "steering", PROPERTY_HINT_RANGE, "-180,180,0.01,radians_as_degrees"), "set_steering", "get_steering");
  234. ADD_GROUP("VehicleBody3D Motion", "");
  235. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction");
  236. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering");
  237. ADD_GROUP("Wheel", "wheel_");
  238. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_roll_influence"), "set_roll_influence", "get_roll_influence");
  239. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_radius", PROPERTY_HINT_NONE, "suffix:m"), "set_radius", "get_radius");
  240. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_rest_length", PROPERTY_HINT_NONE, "suffix:m"), "set_suspension_rest_length", "get_suspension_rest_length");
  241. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_friction_slip"), "set_friction_slip", "get_friction_slip");
  242. ADD_GROUP("Suspension", "suspension_");
  243. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_travel", PROPERTY_HINT_NONE, "suffix:m"), "set_suspension_travel", "get_suspension_travel");
  244. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_stiffness", PROPERTY_HINT_NONE, U"suffix:N/mm"), "set_suspension_stiffness", "get_suspension_stiffness");
  245. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_max_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m/s\u00B2 (N)"), "set_suspension_max_force", "get_suspension_max_force");
  246. ADD_GROUP("Damping", "damping_");
  247. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_compression", PROPERTY_HINT_NONE, U"suffix:N\u22C5s/mm"), "set_damping_compression", "get_damping_compression");
  248. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_relaxation", PROPERTY_HINT_NONE, U"suffix:N\u22C5s/mm"), "set_damping_relaxation", "get_damping_relaxation");
  249. }
  250. void VehicleWheel3D::set_engine_force(real_t p_engine_force) {
  251. m_engineForce = p_engine_force;
  252. }
  253. real_t VehicleWheel3D::get_engine_force() const {
  254. return m_engineForce;
  255. }
  256. void VehicleWheel3D::set_brake(real_t p_brake) {
  257. m_brake = p_brake;
  258. }
  259. real_t VehicleWheel3D::get_brake() const {
  260. return m_brake;
  261. }
  262. void VehicleWheel3D::set_steering(real_t p_steering) {
  263. m_steering = p_steering;
  264. }
  265. real_t VehicleWheel3D::get_steering() const {
  266. return m_steering;
  267. }
  268. void VehicleWheel3D::set_use_as_traction(bool p_enable) {
  269. engine_traction = p_enable;
  270. }
  271. bool VehicleWheel3D::is_used_as_traction() const {
  272. return engine_traction;
  273. }
  274. void VehicleWheel3D::set_use_as_steering(bool p_enabled) {
  275. steers = p_enabled;
  276. }
  277. bool VehicleWheel3D::is_used_as_steering() const {
  278. return steers;
  279. }
  280. real_t VehicleWheel3D::get_skidinfo() const {
  281. return m_skidInfo;
  282. }
  283. real_t VehicleWheel3D::get_rpm() const {
  284. return m_rpm;
  285. }
  286. VehicleWheel3D::VehicleWheel3D() {
  287. }
  288. void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) {
  289. wheel.m_raycastInfo.m_isInContact = false;
  290. Transform3D chassisTrans = s->get_transform();
  291. /*
  292. if (interpolatedTransform && (getRigidBody()->getMotionState())) {
  293. getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
  294. }
  295. */
  296. wheel.m_raycastInfo.m_hardPointWS = chassisTrans.xform(wheel.m_chassisConnectionPointCS);
  297. //wheel.m_raycastInfo.m_hardPointWS+=s->get_linear_velocity()*s->get_step();
  298. wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.get_basis().xform(wheel.m_wheelDirectionCS).normalized();
  299. wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform(wheel.m_wheelAxleCS).normalized();
  300. }
  301. void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState3D *s) {
  302. VehicleWheel3D &wheel = *wheels[p_idx];
  303. _update_wheel_transform(wheel, s);
  304. Vector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
  305. const Vector3 &right = wheel.m_raycastInfo.m_wheelAxleWS;
  306. Vector3 fwd = up.cross(right);
  307. fwd = fwd.normalized();
  308. Basis steeringMat(up, wheel.m_steering);
  309. Basis rotatingMat(right, wheel.m_rotation);
  310. Basis basis2(
  311. right[0], up[0], fwd[0],
  312. right[1], up[1], fwd[1],
  313. right[2], up[2], fwd[2]);
  314. wheel.m_worldTransform.set_basis(steeringMat * rotatingMat * basis2);
  315. //wheel.m_worldTransform.set_basis(basis2 * (steeringMat * rotatingMat));
  316. wheel.m_worldTransform.set_origin(
  317. wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength);
  318. }
  319. real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) {
  320. VehicleWheel3D &wheel = *wheels[p_idx];
  321. _update_wheel_transform(wheel, s);
  322. real_t depth = -1;
  323. real_t raylen = wheel.m_suspensionRestLength + wheel.m_wheelRadius;
  324. Vector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
  325. Vector3 source = wheel.m_raycastInfo.m_hardPointWS;
  326. wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
  327. const Vector3 &target = wheel.m_raycastInfo.m_contactPointWS;
  328. source -= wheel.m_wheelRadius * wheel.m_raycastInfo.m_wheelDirectionWS;
  329. real_t param = real_t(0.);
  330. PhysicsDirectSpaceState3D::RayResult rr;
  331. PhysicsDirectSpaceState3D *ss = s->get_space_state();
  332. PhysicsDirectSpaceState3D::RayParameters ray_params;
  333. ray_params.from = source;
  334. ray_params.to = target;
  335. ray_params.exclude = exclude;
  336. ray_params.collision_mask = get_collision_mask();
  337. wheel.m_raycastInfo.m_groundObject = nullptr;
  338. bool col = ss->intersect_ray(ray_params, rr);
  339. if (col) {
  340. param = source.distance_to(rr.position) / source.distance_to(target);
  341. depth = raylen * param;
  342. wheel.m_raycastInfo.m_contactNormalWS = rr.normal;
  343. wheel.m_raycastInfo.m_isInContact = true;
  344. if (rr.collider) {
  345. wheel.m_raycastInfo.m_groundObject = Object::cast_to<PhysicsBody3D>(rr.collider);
  346. }
  347. real_t hitDistance = param * raylen;
  348. wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelRadius;
  349. //clamp on max suspension travel
  350. real_t minSuspensionLength = wheel.m_suspensionRestLength - wheel.m_maxSuspensionTravel;
  351. real_t maxSuspensionLength = wheel.m_suspensionRestLength + wheel.m_maxSuspensionTravel;
  352. if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) {
  353. wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
  354. }
  355. if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) {
  356. wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
  357. }
  358. wheel.m_raycastInfo.m_contactPointWS = rr.position;
  359. real_t denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(wheel.m_raycastInfo.m_wheelDirectionWS);
  360. Vector3 chassis_velocity_at_contactPoint;
  361. //Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
  362. //chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
  363. chassis_velocity_at_contactPoint = s->get_linear_velocity() +
  364. (s->get_angular_velocity()).cross(wheel.m_raycastInfo.m_contactPointWS - s->get_transform().origin); // * mPos);
  365. real_t projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
  366. if (denominator >= real_t(-0.1)) {
  367. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  368. wheel.m_clippedInvContactDotSuspension = real_t(1.0) / real_t(0.1);
  369. } else {
  370. real_t inv = real_t(-1.) / denominator;
  371. wheel.m_suspensionRelativeVelocity = projVel * inv;
  372. wheel.m_clippedInvContactDotSuspension = inv;
  373. }
  374. } else {
  375. wheel.m_raycastInfo.m_isInContact = false;
  376. //put wheel info as in rest position
  377. wheel.m_raycastInfo.m_suspensionLength = wheel.m_suspensionRestLength;
  378. wheel.m_suspensionRelativeVelocity = real_t(0.0);
  379. wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
  380. wheel.m_clippedInvContactDotSuspension = real_t(1.0);
  381. }
  382. return depth;
  383. }
  384. void VehicleBody3D::_update_suspension(PhysicsDirectBodyState3D *s) {
  385. real_t chassisMass = get_mass();
  386. for (int w_it = 0; w_it < wheels.size(); w_it++) {
  387. VehicleWheel3D &wheel_info = *wheels[w_it];
  388. if (wheel_info.m_raycastInfo.m_isInContact) {
  389. real_t force;
  390. //Spring
  391. {
  392. real_t susp_length = wheel_info.m_suspensionRestLength;
  393. real_t current_length = wheel_info.m_raycastInfo.m_suspensionLength;
  394. real_t length_diff = (susp_length - current_length);
  395. force = wheel_info.m_suspensionStiffness * length_diff * wheel_info.m_clippedInvContactDotSuspension;
  396. }
  397. // Damper
  398. {
  399. real_t projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
  400. {
  401. real_t susp_damping;
  402. if (projected_rel_vel < real_t(0.0)) {
  403. susp_damping = wheel_info.m_wheelsDampingCompression;
  404. } else {
  405. susp_damping = wheel_info.m_wheelsDampingRelaxation;
  406. }
  407. force -= susp_damping * projected_rel_vel;
  408. }
  409. }
  410. // RESULT
  411. wheel_info.m_wheelsSuspensionForce = force * chassisMass;
  412. if (wheel_info.m_wheelsSuspensionForce < real_t(0.)) {
  413. wheel_info.m_wheelsSuspensionForce = real_t(0.);
  414. }
  415. } else {
  416. wheel_info.m_wheelsSuspensionForce = real_t(0.0);
  417. }
  418. }
  419. }
  420. //bilateral constraint between two dynamic objects
  421. void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const Vector3 &pos1,
  422. PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) {
  423. real_t normalLenSqr = normal.length_squared();
  424. //ERR_FAIL_COND( normalLenSqr < real_t(1.1));
  425. if (normalLenSqr > real_t(1.1)) {
  426. impulse = real_t(0.);
  427. return;
  428. }
  429. Vector3 rel_pos1 = pos1 - s->get_transform().origin;
  430. Vector3 rel_pos2;
  431. if (body2) {
  432. rel_pos2 = pos2 - body2->get_global_transform().origin;
  433. }
  434. //this jacobian entry could be re-used for all iterations
  435. Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1); // * mPos);
  436. Vector3 vel2;
  437. if (body2) {
  438. vel2 = body2->get_linear_velocity() + body2->get_angular_velocity().cross(rel_pos2);
  439. }
  440. Vector3 vel = vel1 - vel2;
  441. Basis b2trans;
  442. real_t b2invmass = 0;
  443. Vector3 b2lv;
  444. Vector3 b2av;
  445. Vector3 b2invinertia; //todo
  446. if (body2) {
  447. b2trans = body2->get_global_transform().basis.transposed();
  448. b2invmass = body2->get_inverse_mass();
  449. b2lv = body2->get_linear_velocity();
  450. b2av = body2->get_angular_velocity();
  451. }
  452. btVehicleJacobianEntry jac(s->get_transform().basis.transposed(),
  453. b2trans,
  454. rel_pos1,
  455. rel_pos2,
  456. normal,
  457. s->get_inverse_inertia_tensor().get_main_diagonal(),
  458. 1.0 / get_mass(),
  459. b2invinertia,
  460. b2invmass);
  461. // FIXME: rel_vel assignment here is overwritten by the following assignment.
  462. // What seems to be intended in the next assignment is: rel_vel = normal.dot(rel_vel);
  463. // Investigate why.
  464. real_t rel_vel = jac.getRelativeVelocity(
  465. s->get_linear_velocity(),
  466. s->get_transform().basis.transposed().xform(s->get_angular_velocity()),
  467. b2lv,
  468. b2trans.xform(b2av));
  469. rel_vel = normal.dot(vel);
  470. // !BAS! We had this set to 0.4, in bullet its 0.2
  471. real_t contactDamping = real_t(0.2);
  472. if (p_rollInfluence > 0.0) {
  473. // !BAS! But seeing we apply this frame by frame, makes more sense to me to make this time based
  474. // keeping in mind our anti roll factor if it is set
  475. contactDamping = MIN(contactDamping, s->get_step() / p_rollInfluence);
  476. }
  477. #define ONLY_USE_LINEAR_MASS
  478. #ifdef ONLY_USE_LINEAR_MASS
  479. real_t massTerm = real_t(1.) / ((1.0 / get_mass()) + b2invmass);
  480. impulse = -contactDamping * rel_vel * massTerm;
  481. #else
  482. real_t velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
  483. impulse = velocityImpulse;
  484. #endif
  485. }
  486. VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState3D *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) :
  487. m_s(s),
  488. m_body1(body1),
  489. m_frictionPositionWorld(frictionPosWorld),
  490. m_frictionDirectionWorld(frictionDirectionWorld),
  491. m_maxImpulse(maxImpulse) {
  492. real_t denom0 = 0;
  493. real_t denom1 = 0;
  494. {
  495. Vector3 r0 = frictionPosWorld - s->get_transform().origin;
  496. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  497. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  498. denom0 = s->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  499. }
  500. /* TODO: Why is this code unused?
  501. if (body1) {
  502. Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin;
  503. Vector3 c0 = (r0).cross(frictionDirectionWorld);
  504. Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0);
  505. //denom1= body1->get_inverse_mass() + frictionDirectionWorld.dot(vec);
  506. }
  507. */
  508. real_t relaxation = 1.f;
  509. m_jacDiagABInv = relaxation / (denom0 + denom1);
  510. }
  511. real_t VehicleBody3D::_calc_rolling_friction(btVehicleWheelContactPoint &contactPoint) {
  512. real_t j1 = 0.f;
  513. const Vector3 &contactPosWorld = contactPoint.m_frictionPositionWorld;
  514. Vector3 rel_pos1 = contactPosWorld - contactPoint.m_s->get_transform().origin;
  515. Vector3 rel_pos2;
  516. if (contactPoint.m_body1) {
  517. rel_pos2 = contactPosWorld - contactPoint.m_body1->get_global_transform().origin;
  518. }
  519. real_t maxImpulse = contactPoint.m_maxImpulse;
  520. Vector3 vel1 = contactPoint.m_s->get_linear_velocity() + (contactPoint.m_s->get_angular_velocity()).cross(rel_pos1); // * mPos);
  521. Vector3 vel2;
  522. if (contactPoint.m_body1) {
  523. vel2 = contactPoint.m_body1->get_linear_velocity() + contactPoint.m_body1->get_angular_velocity().cross(rel_pos2);
  524. }
  525. Vector3 vel = vel1 - vel2;
  526. real_t vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
  527. // calculate j that moves us to zero relative velocity
  528. j1 = -vrel * contactPoint.m_jacDiagABInv;
  529. return CLAMP(j1, -maxImpulse, maxImpulse);
  530. }
  531. static const real_t sideFrictionStiffness2 = real_t(1.0);
  532. void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) {
  533. //calculate the impulse, so that the wheels don't move sidewards
  534. int numWheel = wheels.size();
  535. if (!numWheel) {
  536. return;
  537. }
  538. m_forwardWS.resize(numWheel);
  539. m_axle.resize(numWheel);
  540. m_forwardImpulse.resize(numWheel);
  541. m_sideImpulse.resize(numWheel);
  542. //collapse all those loops into one!
  543. for (int i = 0; i < wheels.size(); i++) {
  544. m_sideImpulse.write[i] = real_t(0.);
  545. m_forwardImpulse.write[i] = real_t(0.);
  546. }
  547. {
  548. for (int i = 0; i < wheels.size(); i++) {
  549. VehicleWheel3D &wheelInfo = *wheels[i];
  550. if (wheelInfo.m_raycastInfo.m_isInContact) {
  551. //const btTransform& wheelTrans = getWheelTransformWS( i );
  552. Basis wheelBasis0 = wheelInfo.m_worldTransform.basis; //get_global_transform().basis;
  553. m_axle.write[i] = wheelBasis0.get_column(Vector3::AXIS_X);
  554. //m_axle[i] = wheelInfo.m_raycastInfo.m_wheelAxleWS;
  555. const Vector3 &surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
  556. real_t proj = m_axle[i].dot(surfNormalWS);
  557. m_axle.write[i] -= surfNormalWS * proj;
  558. m_axle.write[i] = m_axle[i].normalized();
  559. m_forwardWS.write[i] = surfNormalWS.cross(m_axle[i]);
  560. m_forwardWS.write[i].normalize();
  561. _resolve_single_bilateral(s, wheelInfo.m_raycastInfo.m_contactPointWS,
  562. wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
  563. m_axle[i], m_sideImpulse.write[i], wheelInfo.m_rollInfluence);
  564. m_sideImpulse.write[i] *= sideFrictionStiffness2;
  565. }
  566. }
  567. }
  568. real_t sideFactor = real_t(1.);
  569. real_t fwdFactor = 0.5;
  570. bool sliding = false;
  571. {
  572. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  573. VehicleWheel3D &wheelInfo = *wheels[wheel];
  574. //class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
  575. real_t rollingFriction = 0.f;
  576. if (wheelInfo.m_raycastInfo.m_isInContact) {
  577. if (wheelInfo.m_engineForce != 0.f) {
  578. rollingFriction = -wheelInfo.m_engineForce * s->get_step();
  579. } else {
  580. real_t defaultRollingFrictionImpulse = 0.f;
  581. real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
  582. btVehicleWheelContactPoint contactPt(s, wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
  583. rollingFriction = _calc_rolling_friction(contactPt);
  584. }
  585. }
  586. //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
  587. m_forwardImpulse.write[wheel] = real_t(0.);
  588. wheelInfo.m_skidInfo = real_t(1.);
  589. if (wheelInfo.m_raycastInfo.m_isInContact) {
  590. wheelInfo.m_skidInfo = real_t(1.);
  591. real_t maximp = wheelInfo.m_wheelsSuspensionForce * s->get_step() * wheelInfo.m_frictionSlip;
  592. real_t maximpSide = maximp;
  593. real_t maximpSquared = maximp * maximpSide;
  594. m_forwardImpulse.write[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep;
  595. real_t x = (m_forwardImpulse[wheel]) * fwdFactor;
  596. real_t y = (m_sideImpulse[wheel]) * sideFactor;
  597. real_t impulseSquared = (x * x + y * y);
  598. if (impulseSquared > maximpSquared) {
  599. sliding = true;
  600. real_t factor = maximp / Math::sqrt(impulseSquared);
  601. wheelInfo.m_skidInfo *= factor;
  602. }
  603. }
  604. }
  605. }
  606. if (sliding) {
  607. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  608. if (m_sideImpulse[wheel] != real_t(0.)) {
  609. if (wheels[wheel]->m_skidInfo < real_t(1.)) {
  610. m_forwardImpulse.write[wheel] *= wheels[wheel]->m_skidInfo;
  611. m_sideImpulse.write[wheel] *= wheels[wheel]->m_skidInfo;
  612. }
  613. }
  614. }
  615. }
  616. // apply the impulses
  617. {
  618. for (int wheel = 0; wheel < wheels.size(); wheel++) {
  619. VehicleWheel3D &wheelInfo = *wheels[wheel];
  620. Vector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
  621. s->get_transform().origin;
  622. if (m_forwardImpulse[wheel] != real_t(0.)) {
  623. s->apply_impulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos);
  624. }
  625. if (m_sideImpulse[wheel] != real_t(0.)) {
  626. PhysicsBody3D *groundObject = wheelInfo.m_raycastInfo.m_groundObject;
  627. Vector3 rel_pos2;
  628. if (groundObject) {
  629. rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - groundObject->get_global_transform().origin;
  630. }
  631. Vector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
  632. #if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
  633. Vector3 vChassisWorldUp = s->get_transform().basis.transposed()[1]; //getRigidBody()->getCenterOfMassTransform3D().getBasis().getColumn(m_indexUpAxis);
  634. rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
  635. #else
  636. rel_pos[1] *= wheelInfo.m_rollInfluence; //?
  637. #endif
  638. s->apply_impulse(sideImp, rel_pos);
  639. //apply friction impulse on the ground
  640. //todo
  641. //groundObject->applyImpulse(-sideImp,rel_pos2);
  642. }
  643. }
  644. }
  645. }
  646. void VehicleBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
  647. RigidBody3D::_body_state_changed(p_state);
  648. real_t step = p_state->get_step();
  649. for (int i = 0; i < wheels.size(); i++) {
  650. _update_wheel(i, p_state);
  651. }
  652. for (int i = 0; i < wheels.size(); i++) {
  653. _ray_cast(i, p_state);
  654. wheels[i]->set_transform(p_state->get_transform().inverse() * wheels[i]->m_worldTransform);
  655. }
  656. _update_suspension(p_state);
  657. for (int i = 0; i < wheels.size(); i++) {
  658. //apply suspension force
  659. VehicleWheel3D &wheel = *wheels[i];
  660. real_t suspensionForce = wheel.m_wheelsSuspensionForce;
  661. if (suspensionForce > wheel.m_maxSuspensionForce) {
  662. suspensionForce = wheel.m_maxSuspensionForce;
  663. }
  664. Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
  665. Vector3 relative_position = wheel.m_raycastInfo.m_contactPointWS - p_state->get_transform().origin;
  666. p_state->apply_impulse(impulse, relative_position);
  667. }
  668. _update_friction(p_state);
  669. for (int i = 0; i < wheels.size(); i++) {
  670. VehicleWheel3D &wheel = *wheels[i];
  671. Vector3 relpos = wheel.m_raycastInfo.m_hardPointWS - p_state->get_transform().origin;
  672. Vector3 vel = p_state->get_linear_velocity() + (p_state->get_angular_velocity()).cross(relpos); // * mPos);
  673. if (wheel.m_raycastInfo.m_isInContact) {
  674. const Transform3D &chassisWorldTransform = p_state->get_transform();
  675. Vector3 fwd(
  676. chassisWorldTransform.basis[0][Vector3::AXIS_Z],
  677. chassisWorldTransform.basis[1][Vector3::AXIS_Z],
  678. chassisWorldTransform.basis[2][Vector3::AXIS_Z]);
  679. real_t proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
  680. fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
  681. real_t proj2 = fwd.dot(vel);
  682. wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelRadius);
  683. }
  684. wheel.m_rotation += wheel.m_deltaRotation;
  685. wheel.m_rpm = ((wheel.m_deltaRotation / step) * 60) / Math_TAU;
  686. wheel.m_deltaRotation *= real_t(0.99); //damping of rotation when not in contact
  687. }
  688. }
  689. void VehicleBody3D::set_engine_force(real_t p_engine_force) {
  690. engine_force = p_engine_force;
  691. for (int i = 0; i < wheels.size(); i++) {
  692. VehicleWheel3D &wheelInfo = *wheels[i];
  693. if (wheelInfo.engine_traction) {
  694. wheelInfo.m_engineForce = p_engine_force;
  695. }
  696. }
  697. }
  698. real_t VehicleBody3D::get_engine_force() const {
  699. return engine_force;
  700. }
  701. void VehicleBody3D::set_brake(real_t p_brake) {
  702. brake = p_brake;
  703. for (int i = 0; i < wheels.size(); i++) {
  704. VehicleWheel3D &wheelInfo = *wheels[i];
  705. wheelInfo.m_brake = p_brake;
  706. }
  707. }
  708. real_t VehicleBody3D::get_brake() const {
  709. return brake;
  710. }
  711. void VehicleBody3D::set_steering(real_t p_steering) {
  712. m_steeringValue = p_steering;
  713. for (int i = 0; i < wheels.size(); i++) {
  714. VehicleWheel3D &wheelInfo = *wheels[i];
  715. if (wheelInfo.steers) {
  716. wheelInfo.m_steering = p_steering;
  717. }
  718. }
  719. }
  720. real_t VehicleBody3D::get_steering() const {
  721. return m_steeringValue;
  722. }
  723. void VehicleBody3D::_bind_methods() {
  724. ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleBody3D::set_engine_force);
  725. ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleBody3D::get_engine_force);
  726. ClassDB::bind_method(D_METHOD("set_brake", "brake"), &VehicleBody3D::set_brake);
  727. ClassDB::bind_method(D_METHOD("get_brake"), &VehicleBody3D::get_brake);
  728. ClassDB::bind_method(D_METHOD("set_steering", "steering"), &VehicleBody3D::set_steering);
  729. ClassDB::bind_method(D_METHOD("get_steering"), &VehicleBody3D::get_steering);
  730. ADD_GROUP("Motion", "");
  731. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "engine_force", PROPERTY_HINT_RANGE, U"-1024,1024,0.01,or_less,or_greater,suffix:kg\u22C5m/s\u00B2 (N)"), "set_engine_force", "get_engine_force");
  732. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "brake", PROPERTY_HINT_RANGE, U"-128,128,0.01,or_less,or_greater,suffix:kg\u22C5m/s\u00B2 (N)"), "set_brake", "get_brake");
  733. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "steering", PROPERTY_HINT_RANGE, "-180,180,0.01,radians_as_degrees"), "set_steering", "get_steering");
  734. }
  735. VehicleBody3D::VehicleBody3D() {
  736. exclude.insert(get_rid());
  737. set_mass(40);
  738. }