Path: blob/master/modules/jolt_physics/joints/jolt_joint_3d.cpp
21152 views
/**************************************************************************/1/* jolt_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_joint_3d.h"3132#include "../jolt_physics_server_3d.h"33#include "../jolt_project_settings.h"34#include "../misc/jolt_type_conversions.h"35#include "../objects/jolt_body_3d.h"36#include "../spaces/jolt_space_3d.h"3738namespace {3940constexpr int JOINT_DEFAULT_SOLVER_PRIORITY = 1;4142} // namespace4344void JoltJoint3D::_shift_reference_frames(const Vector3 &p_linear_shift, const Vector3 &p_angular_shift, Transform3D &r_shifted_ref_a, Transform3D &r_shifted_ref_b) {45Vector3 origin_a = local_ref_a.origin;46Vector3 origin_b = local_ref_b.origin;4748if (body_a != nullptr) {49origin_a *= body_a->get_scale();50origin_a -= to_godot(body_a->get_jolt_shape()->GetCenterOfMass());51}5253if (body_b != nullptr) {54origin_b *= body_b->get_scale();55origin_b -= to_godot(body_b->get_jolt_shape()->GetCenterOfMass());56}5758const Basis &basis_a = local_ref_a.basis;59const Basis &basis_b = local_ref_b.basis;6061const Basis shifted_basis_a = basis_a * Basis::from_euler(p_angular_shift, EulerOrder::ZYX);62const Vector3 shifted_origin_a = origin_a - basis_a.xform(p_linear_shift);6364r_shifted_ref_a = Transform3D(shifted_basis_a, shifted_origin_a);65r_shifted_ref_b = Transform3D(basis_b, origin_b);66}6768void JoltJoint3D::_wake_up_bodies() {69if (body_a != nullptr) {70body_a->wake_up();71}7273if (body_b != nullptr) {74body_b->wake_up();75}76}7778void JoltJoint3D::_update_enabled() {79if (jolt_ref != nullptr) {80jolt_ref->SetEnabled(enabled);81}82}8384void JoltJoint3D::_update_iterations() {85if (jolt_ref != nullptr) {86jolt_ref->SetNumVelocityStepsOverride((JPH::uint)velocity_iterations);87jolt_ref->SetNumPositionStepsOverride((JPH::uint)position_iterations);88}89}9091void JoltJoint3D::_enabled_changed() {92_update_enabled();93_wake_up_bodies();94}9596void JoltJoint3D::_iterations_changed() {97_update_iterations();98_wake_up_bodies();99}100101String JoltJoint3D::_bodies_to_string() const {102return vformat("'%s' and '%s'", body_a != nullptr ? body_a->to_string() : "<unknown>", body_b != nullptr ? body_b->to_string() : "<World>");103}104105JoltJoint3D::JoltJoint3D(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) :106enabled(p_old_joint.enabled),107collision_disabled(p_old_joint.collision_disabled),108body_a(p_body_a),109body_b(p_body_b),110rid(p_old_joint.rid),111local_ref_a(p_local_ref_a),112local_ref_b(p_local_ref_b) {113if (body_a != nullptr) {114body_a->add_joint(this);115}116117if (body_b != nullptr) {118body_b->add_joint(this);119}120121if (body_b == nullptr && JoltProjectSettings::joint_world_node == JOLT_JOINT_WORLD_NODE_A) {122// The joint scene nodes will, when omitting one of the two body nodes, always pass in a123// null `body_b` to indicate it being the "world node", regardless of which body node you124// leave blank. So we need to correct for that if we wish to use the arguably more intuitive125// alternative where `body_a` is the "world node" instead.126127SWAP(body_a, body_b);128SWAP(local_ref_a, local_ref_b);129}130}131132JoltJoint3D::~JoltJoint3D() {133if (body_a != nullptr) {134body_a->remove_joint(this);135}136137if (body_b != nullptr) {138body_b->remove_joint(this);139}140141destroy();142}143144JoltSpace3D *JoltJoint3D::get_space() const {145if (body_a != nullptr && body_b != nullptr) {146JoltSpace3D *space_a = body_a->get_space();147JoltSpace3D *space_b = body_b->get_space();148149if (space_a == nullptr || space_b == nullptr) {150return nullptr;151}152153ERR_FAIL_COND_V_MSG(space_a != space_b, nullptr, vformat("Joint was found to connect bodies in different physics spaces. This joint will effectively be disabled. This joint connects %s.", _bodies_to_string()));154155return space_a;156} else if (body_a != nullptr) {157return body_a->get_space();158} else if (body_b != nullptr) {159return body_b->get_space();160}161162return nullptr;163}164165void JoltJoint3D::set_enabled(bool p_enabled) {166if (enabled == p_enabled) {167return;168}169170enabled = p_enabled;171172_enabled_changed();173}174175int JoltJoint3D::get_solver_priority() const {176return JOINT_DEFAULT_SOLVER_PRIORITY;177}178179void JoltJoint3D::set_solver_priority(int p_priority) {180if (p_priority != JOINT_DEFAULT_SOLVER_PRIORITY) {181WARN_PRINT(vformat("Joint solver priority is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));182}183}184185void JoltJoint3D::set_solver_velocity_iterations(int p_iterations) {186if (velocity_iterations == p_iterations) {187return;188}189190velocity_iterations = p_iterations;191192_iterations_changed();193}194195void JoltJoint3D::set_solver_position_iterations(int p_iterations) {196if (position_iterations == p_iterations) {197return;198}199200position_iterations = p_iterations;201202_iterations_changed();203}204205void JoltJoint3D::set_collision_disabled(bool p_disabled) {206collision_disabled = p_disabled;207208if (body_a == nullptr || body_b == nullptr) {209return;210}211212JoltPhysicsServer3D *physics_server = JoltPhysicsServer3D::get_singleton();213214if (collision_disabled) {215physics_server->body_add_collision_exception(body_a->get_rid(), body_b->get_rid());216physics_server->body_add_collision_exception(body_b->get_rid(), body_a->get_rid());217} else {218physics_server->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid());219physics_server->body_remove_collision_exception(body_b->get_rid(), body_a->get_rid());220}221}222223void JoltJoint3D::destroy() {224if (jolt_ref == nullptr) {225return;226}227228JoltSpace3D *space = get_space();229230if (space != nullptr) {231space->remove_joint(this);232}233234jolt_ref = nullptr;235}236237238