Path: blob/master/modules/jolt_physics/joints/jolt_generic_6dof_joint_3d.cpp
10278 views
/**************************************************************************/1/* jolt_generic_6dof_joint_3d.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "jolt_generic_6dof_joint_3d.h"3132#include "../misc/jolt_type_conversions.h"33#include "../objects/jolt_body_3d.h"34#include "../spaces/jolt_space_3d.h"3536#include "Jolt/Physics/Constraints/SixDOFConstraint.h"3738namespace {3940constexpr double G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS = 0.7;41constexpr double G6DOF_DEFAULT_LINEAR_RESTITUTION = 0.5;42constexpr double G6DOF_DEFAULT_LINEAR_DAMPING = 1.0;4344constexpr double G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS = 0.5;45constexpr double G6DOF_DEFAULT_ANGULAR_DAMPING = 1.0;46constexpr double G6DOF_DEFAULT_ANGULAR_RESTITUTION = 0.0;47constexpr double G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT = 0.0;48constexpr double G6DOF_DEFAULT_ANGULAR_ERP = 0.5;4950} // namespace5152JPH::Constraint *JoltGeneric6DOFJoint3D::_build_6dof(JPH::Body *p_jolt_body_a, JPH::Body *p_jolt_body_b, const Transform3D &p_shifted_ref_a, const Transform3D &p_shifted_ref_b) const {53JPH::SixDOFConstraintSettings constraint_settings;5455for (int axis = 0; axis < AXIS_COUNT; ++axis) {56double lower = limit_lower[axis];57double upper = limit_upper[axis];5859if (axis >= AXIS_ANGULAR_X && axis <= AXIS_ANGULAR_Z) {60const double temp = lower;61lower = -upper;62upper = -temp;63}6465if (!limit_enabled[axis] || lower > upper) {66constraint_settings.MakeFreeAxis((JoltAxis)axis);67} else {68constraint_settings.SetLimitedAxis((JoltAxis)axis, (float)lower, (float)upper);69}70}7172constraint_settings.mSpace = JPH::EConstraintSpace::LocalToBodyCOM;73constraint_settings.mPosition1 = to_jolt_r(p_shifted_ref_a.origin);74constraint_settings.mAxisX1 = to_jolt(p_shifted_ref_a.basis.get_column(Vector3::AXIS_X));75constraint_settings.mAxisY1 = to_jolt(p_shifted_ref_a.basis.get_column(Vector3::AXIS_Y));76constraint_settings.mPosition2 = to_jolt_r(p_shifted_ref_b.origin);77constraint_settings.mAxisX2 = to_jolt(p_shifted_ref_b.basis.get_column(Vector3::AXIS_X));78constraint_settings.mAxisY2 = to_jolt(p_shifted_ref_b.basis.get_column(Vector3::AXIS_Y));79constraint_settings.mSwingType = JPH::ESwingType::Pyramid;8081if (p_jolt_body_a == nullptr) {82return constraint_settings.Create(JPH::Body::sFixedToWorld, *p_jolt_body_b);83} else if (p_jolt_body_b == nullptr) {84return constraint_settings.Create(*p_jolt_body_a, JPH::Body::sFixedToWorld);85} else {86return constraint_settings.Create(*p_jolt_body_a, *p_jolt_body_b);87}88}8990void JoltGeneric6DOFJoint3D::_update_limit_spring_parameters(int p_axis) {91JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());92if (unlikely(constraint == nullptr)) {93return;94}9596JPH::SpringSettings settings = constraint->GetLimitsSpringSettings((JoltAxis)p_axis);9798settings.mMode = JPH::ESpringMode::FrequencyAndDamping;99100if (limit_spring_enabled[p_axis]) {101settings.mFrequency = (float)limit_spring_frequency[p_axis];102settings.mDamping = (float)limit_spring_damping[p_axis];103} else {104settings.mFrequency = 0.0f;105settings.mDamping = 0.0f;106}107108constraint->SetLimitsSpringSettings((JoltAxis)p_axis, settings);109}110111void JoltGeneric6DOFJoint3D::_update_motor_state(int p_axis) {112if (JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr())) {113if (motor_enabled[p_axis]) {114constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Velocity);115} else if (spring_enabled[p_axis]) {116constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Position);117} else {118constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Off);119}120}121}122123void JoltGeneric6DOFJoint3D::_update_motor_velocity(int p_axis) {124JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());125if (unlikely(constraint == nullptr)) {126return;127}128129if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {130constraint->SetTargetVelocityCS(JPH::Vec3(131(float)motor_speed[AXIS_LINEAR_X],132(float)motor_speed[AXIS_LINEAR_Y],133(float)motor_speed[AXIS_LINEAR_Z]));134} else {135// We flip the direction since Jolt is CCW but Godot is CW.136constraint->SetTargetAngularVelocityCS(JPH::Vec3(137(float)-motor_speed[AXIS_ANGULAR_X],138(float)-motor_speed[AXIS_ANGULAR_Y],139(float)-motor_speed[AXIS_ANGULAR_Z]));140}141}142143void JoltGeneric6DOFJoint3D::_update_motor_limit(int p_axis) {144JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());145if (unlikely(constraint == nullptr)) {146return;147}148149JPH::MotorSettings &motor_settings = constraint->GetMotorSettings((JoltAxis)p_axis);150151float limit = FLT_MAX;152153if (motor_enabled[p_axis]) {154limit = (float)motor_limit[p_axis];155} else if (spring_enabled[p_axis]) {156limit = (float)spring_limit[p_axis];157}158159if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {160motor_settings.SetForceLimit(limit);161} else {162motor_settings.SetTorqueLimit(limit);163}164}165166void JoltGeneric6DOFJoint3D::_update_spring_parameters(int p_axis) {167JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());168if (unlikely(constraint == nullptr)) {169return;170}171172JPH::MotorSettings &motor_settings = constraint->GetMotorSettings((JoltAxis)p_axis);173174if (spring_use_frequency[p_axis]) {175motor_settings.mSpringSettings.mMode = JPH::ESpringMode::FrequencyAndDamping;176motor_settings.mSpringSettings.mFrequency = (float)spring_frequency[p_axis];177} else {178motor_settings.mSpringSettings.mMode = JPH::ESpringMode::StiffnessAndDamping;179motor_settings.mSpringSettings.mStiffness = (float)spring_stiffness[p_axis];180}181182motor_settings.mSpringSettings.mDamping = (float)spring_damping[p_axis];183}184185void JoltGeneric6DOFJoint3D::_update_spring_equilibrium(int p_axis) {186JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());187if (unlikely(constraint == nullptr)) {188return;189}190191if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {192const Vector3 target_position = Vector3(193(float)spring_equilibrium[AXIS_LINEAR_X],194(float)spring_equilibrium[AXIS_LINEAR_Y],195(float)spring_equilibrium[AXIS_LINEAR_Z]);196197constraint->SetTargetPositionCS(to_jolt(target_position));198} else {199// We flip the direction since Jolt is CCW but Godot is CW.200const Basis target_orientation = Basis::from_euler(201Vector3((float)-spring_equilibrium[AXIS_ANGULAR_X],202(float)-spring_equilibrium[AXIS_ANGULAR_Y],203(float)-spring_equilibrium[AXIS_ANGULAR_Z]),204EulerOrder::ZYX);205206constraint->SetTargetOrientationCS(to_jolt(target_orientation));207}208}209210void JoltGeneric6DOFJoint3D::_limits_changed() {211rebuild();212_wake_up_bodies();213}214215void JoltGeneric6DOFJoint3D::_limit_spring_parameters_changed(int p_axis) {216_update_limit_spring_parameters(p_axis);217_wake_up_bodies();218}219220void JoltGeneric6DOFJoint3D::_motor_state_changed(int p_axis) {221_update_motor_state(p_axis);222_update_motor_limit(p_axis);223_wake_up_bodies();224}225226void JoltGeneric6DOFJoint3D::_motor_speed_changed(int p_axis) {227_update_motor_velocity(p_axis);228_wake_up_bodies();229}230231void JoltGeneric6DOFJoint3D::_motor_limit_changed(int p_axis) {232_update_motor_limit(p_axis);233_wake_up_bodies();234}235236void JoltGeneric6DOFJoint3D::_spring_state_changed(int p_axis) {237_update_motor_state(p_axis);238_wake_up_bodies();239}240241void JoltGeneric6DOFJoint3D::_spring_parameters_changed(int p_axis) {242_update_spring_parameters(p_axis);243_wake_up_bodies();244}245246void JoltGeneric6DOFJoint3D::_spring_equilibrium_changed(int p_axis) {247_update_spring_equilibrium(p_axis);248_wake_up_bodies();249}250251void JoltGeneric6DOFJoint3D::_spring_limit_changed(int p_axis) {252_update_motor_limit(p_axis);253_wake_up_bodies();254}255256JoltGeneric6DOFJoint3D::JoltGeneric6DOFJoint3D(const JoltJoint3D &p_old_joint, JoltBody3D *p_body_a, JoltBody3D *p_body_b, const Transform3D &p_local_ref_a, const Transform3D &p_local_ref_b) :257JoltJoint3D(p_old_joint, p_body_a, p_body_b, p_local_ref_a, p_local_ref_b) {258rebuild();259}260261double JoltGeneric6DOFJoint3D::get_param(Axis p_axis, Param p_param) const {262const int axis_lin = AXES_LINEAR + (int)p_axis;263const int axis_ang = AXES_ANGULAR + (int)p_axis;264265switch ((int)p_param) {266case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {267return limit_lower[axis_lin];268}269case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: {270return limit_upper[axis_lin];271}272case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: {273return G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS;274}275case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: {276return G6DOF_DEFAULT_LINEAR_RESTITUTION;277}278case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: {279return G6DOF_DEFAULT_LINEAR_DAMPING;280}281case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {282return motor_speed[axis_lin];283}284case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {285return motor_limit[axis_lin];286}287case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {288return spring_stiffness[axis_lin];289}290case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {291return spring_damping[axis_lin];292}293case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {294return spring_equilibrium[axis_lin];295}296case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: {297return limit_lower[axis_ang];298}299case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: {300return limit_upper[axis_ang];301}302case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: {303return G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS;304}305case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: {306return G6DOF_DEFAULT_ANGULAR_DAMPING;307}308case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: {309return G6DOF_DEFAULT_ANGULAR_RESTITUTION;310}311case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: {312return G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT;313}314case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: {315return G6DOF_DEFAULT_ANGULAR_ERP;316}317case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: {318return motor_speed[axis_ang];319}320case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: {321return motor_limit[axis_ang];322}323case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {324return spring_stiffness[axis_ang];325}326case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {327return spring_damping[axis_ang];328}329case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {330return spring_equilibrium[axis_ang];331}332default: {333ERR_FAIL_V_MSG(0.0, vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));334}335}336}337338void JoltGeneric6DOFJoint3D::set_param(Axis p_axis, Param p_param, double p_value) {339const int axis_lin = AXES_LINEAR + (int)p_axis;340const int axis_ang = AXES_ANGULAR + (int)p_axis;341342switch ((int)p_param) {343case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {344limit_lower[axis_lin] = p_value;345_limits_changed();346} break;347case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: {348limit_upper[axis_lin] = p_value;349_limits_changed();350} break;351case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: {352if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS)) {353WARN_PRINT(vformat("6DOF joint linear limit softness is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));354}355} break;356case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: {357if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_RESTITUTION)) {358WARN_PRINT(vformat("6DOF joint linear restitution is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));359}360} break;361case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: {362if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_DAMPING)) {363WARN_PRINT(vformat("6DOF joint linear damping is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));364}365} break;366case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {367motor_speed[axis_lin] = p_value;368_motor_speed_changed(axis_lin);369} break;370case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {371motor_limit[axis_lin] = p_value;372_motor_limit_changed(axis_lin);373} break;374case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {375spring_stiffness[axis_lin] = p_value;376_spring_parameters_changed(axis_lin);377} break;378case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {379spring_damping[axis_lin] = p_value;380_spring_parameters_changed(axis_lin);381} break;382case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {383spring_equilibrium[axis_lin] = p_value;384_spring_equilibrium_changed(axis_lin);385} break;386case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: {387limit_lower[axis_ang] = p_value;388_limits_changed();389} break;390case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: {391limit_upper[axis_ang] = p_value;392_limits_changed();393} break;394case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: {395if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS)) {396WARN_PRINT(vformat("6DOF joint angular limit softness is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));397}398} break;399case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: {400if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_DAMPING)) {401WARN_PRINT(vformat("6DOF joint angular damping is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));402}403} break;404case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: {405if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_RESTITUTION)) {406WARN_PRINT(vformat("6DOF joint angular restitution is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));407}408} break;409case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: {410if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT)) {411WARN_PRINT(vformat("6DOF joint angular force limit is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));412}413} break;414case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: {415if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_ERP)) {416WARN_PRINT(vformat("6DOF joint angular ERP is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));417}418} break;419case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: {420motor_speed[axis_ang] = p_value;421_motor_speed_changed(axis_ang);422} break;423case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: {424motor_limit[axis_ang] = p_value;425_motor_limit_changed(axis_ang);426} break;427case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {428spring_stiffness[axis_ang] = p_value;429_spring_parameters_changed(axis_ang);430} break;431case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {432spring_damping[axis_ang] = p_value;433_spring_parameters_changed(axis_ang);434} break;435case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {436spring_equilibrium[axis_ang] = p_value;437_spring_equilibrium_changed(axis_ang);438} break;439default: {440ERR_FAIL_MSG(vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));441} break;442}443}444445bool JoltGeneric6DOFJoint3D::get_flag(Axis p_axis, Flag p_flag) const {446const int axis_lin = AXES_LINEAR + (int)p_axis;447const int axis_ang = AXES_ANGULAR + (int)p_axis;448449switch ((int)p_flag) {450case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: {451return limit_enabled[axis_lin];452}453case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: {454return limit_enabled[axis_ang];455}456case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {457return spring_enabled[axis_ang];458}459case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {460return spring_enabled[axis_lin];461}462case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: {463return motor_enabled[axis_ang];464}465case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {466return motor_enabled[axis_lin];467}468default: {469ERR_FAIL_V_MSG(false, vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));470}471}472}473474void JoltGeneric6DOFJoint3D::set_flag(Axis p_axis, Flag p_flag, bool p_enabled) {475const int axis_lin = AXES_LINEAR + (int)p_axis;476const int axis_ang = AXES_ANGULAR + (int)p_axis;477478switch ((int)p_flag) {479case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: {480limit_enabled[axis_lin] = p_enabled;481_limits_changed();482} break;483case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: {484limit_enabled[axis_ang] = p_enabled;485_limits_changed();486} break;487case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {488spring_enabled[axis_ang] = p_enabled;489_spring_state_changed(axis_ang);490} break;491case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {492spring_enabled[axis_lin] = p_enabled;493_spring_state_changed(axis_lin);494} break;495case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: {496motor_enabled[axis_ang] = p_enabled;497_motor_state_changed(axis_ang);498} break;499case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {500motor_enabled[axis_lin] = p_enabled;501_motor_state_changed(axis_lin);502} break;503default: {504ERR_FAIL_MSG(vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));505} break;506}507}508509double JoltGeneric6DOFJoint3D::get_jolt_param(Axis p_axis, JoltParam p_param) const {510const int axis_lin = AXES_LINEAR + (int)p_axis;511const int axis_ang = AXES_ANGULAR + (int)p_axis;512513switch ((int)p_param) {514case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_FREQUENCY: {515return spring_frequency[axis_lin];516}517case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_MAX_FORCE: {518return spring_limit[axis_lin];519}520case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_FREQUENCY: {521return limit_spring_frequency[axis_lin];522}523case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_DAMPING: {524return limit_spring_damping[axis_lin];525}526case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_FREQUENCY: {527return spring_frequency[axis_ang];528}529case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_MAX_TORQUE: {530return spring_limit[axis_ang];531}532default: {533ERR_FAIL_V_MSG(0.0, vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));534}535}536}537538void JoltGeneric6DOFJoint3D::set_jolt_param(Axis p_axis, JoltParam p_param, double p_value) {539const int axis_lin = AXES_LINEAR + (int)p_axis;540const int axis_ang = AXES_ANGULAR + (int)p_axis;541542switch ((int)p_param) {543case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_FREQUENCY: {544spring_frequency[axis_lin] = p_value;545_spring_parameters_changed(axis_lin);546} break;547case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_MAX_FORCE: {548spring_limit[axis_lin] = p_value;549_spring_limit_changed(axis_lin);550} break;551case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_FREQUENCY: {552limit_spring_frequency[axis_lin] = p_value;553_limit_spring_parameters_changed(axis_lin);554} break;555case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_DAMPING: {556limit_spring_damping[axis_lin] = p_value;557_limit_spring_parameters_changed(axis_lin);558} break;559case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_FREQUENCY: {560spring_frequency[axis_ang] = p_value;561_spring_parameters_changed(axis_ang);562} break;563case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_MAX_TORQUE: {564spring_limit[axis_ang] = p_value;565_spring_limit_changed(axis_ang);566} break;567default: {568ERR_FAIL_MSG(vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));569} break;570}571}572573bool JoltGeneric6DOFJoint3D::get_jolt_flag(Axis p_axis, JoltFlag p_flag) const {574const int axis_lin = AXES_LINEAR + (int)p_axis;575const int axis_ang = AXES_ANGULAR + (int)p_axis;576577switch ((int)p_flag) {578case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT_SPRING: {579return limit_spring_enabled[axis_lin];580}581case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING_FREQUENCY: {582return spring_use_frequency[axis_lin];583}584case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING_FREQUENCY: {585return spring_use_frequency[axis_ang];586}587default: {588ERR_FAIL_V_MSG(false, vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));589}590}591}592593void JoltGeneric6DOFJoint3D::set_jolt_flag(Axis p_axis, JoltFlag p_flag, bool p_enabled) {594const int axis_lin = AXES_LINEAR + (int)p_axis;595const int axis_ang = AXES_ANGULAR + (int)p_axis;596597switch ((int)p_flag) {598case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT_SPRING: {599limit_spring_enabled[axis_lin] = p_enabled;600_limit_spring_parameters_changed(axis_lin);601} break;602case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING_FREQUENCY: {603spring_use_frequency[axis_lin] = p_enabled;604_spring_parameters_changed(axis_lin);605} break;606case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING_FREQUENCY: {607spring_use_frequency[axis_ang] = p_enabled;608_spring_parameters_changed(axis_ang);609} break;610default: {611ERR_FAIL_MSG(vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));612} break;613}614}615616float JoltGeneric6DOFJoint3D::get_applied_force() const {617JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());618ERR_FAIL_NULL_V(constraint, 0.0f);619620JoltSpace3D *space = get_space();621ERR_FAIL_NULL_V(space, 0.0f);622623const float last_step = space->get_last_step();624if (unlikely(last_step == 0.0f)) {625return 0.0f;626}627628const JPH::Vec3 total_lambda = constraint->GetTotalLambdaPosition() + constraint->GetTotalLambdaMotorTranslation();629630return total_lambda.Length() / last_step;631}632633float JoltGeneric6DOFJoint3D::get_applied_torque() const {634JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());635ERR_FAIL_NULL_V(constraint, 0.0f);636637JoltSpace3D *space = get_space();638ERR_FAIL_NULL_V(space, 0.0f);639640const float last_step = space->get_last_step();641if (unlikely(last_step == 0.0f)) {642return 0.0f;643}644645const JPH::Vec3 total_lambda = constraint->GetTotalLambdaRotation() + constraint->GetTotalLambdaMotorRotation();646647return total_lambda.Length() / last_step;648}649650void JoltGeneric6DOFJoint3D::rebuild() {651destroy();652653JoltSpace3D *space = get_space();654if (space == nullptr) {655return;656}657658JPH::Body *jolt_body_a = body_a != nullptr ? body_a->get_jolt_body() : nullptr;659JPH::Body *jolt_body_b = body_b != nullptr ? body_b->get_jolt_body() : nullptr;660ERR_FAIL_COND(jolt_body_a == nullptr && jolt_body_b == nullptr);661662Transform3D shifted_ref_a;663Transform3D shifted_ref_b;664665_shift_reference_frames(Vector3(), Vector3(), shifted_ref_a, shifted_ref_b);666667jolt_ref = _build_6dof(jolt_body_a, jolt_body_b, shifted_ref_a, shifted_ref_b);668669space->add_joint(this);670671_update_enabled();672_update_iterations();673674_update_limit_spring_parameters(AXIS_LINEAR_X);675_update_limit_spring_parameters(AXIS_LINEAR_Y);676_update_limit_spring_parameters(AXIS_LINEAR_Z);677678for (int axis = 0; axis < AXIS_COUNT; ++axis) {679_update_motor_state(axis);680_update_motor_velocity(axis);681_update_motor_limit(axis);682_update_spring_parameters(axis);683_update_spring_equilibrium(axis);684}685}686687688