Path: blob/master/modules/godot_physics_3d/godot_body_3d.h
10279 views
/**************************************************************************/1/* godot_body_3d.h */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#pragma once3132#include "godot_area_3d.h"33#include "godot_collision_object_3d.h"3435#include "core/templates/vset.h"3637class GodotConstraint3D;38class GodotPhysicsDirectBodyState3D;3940class GodotBody3D : public GodotCollisionObject3D {41PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_RIGID;4243Vector3 linear_velocity;44Vector3 angular_velocity;4546Vector3 prev_linear_velocity;47Vector3 prev_angular_velocity;4849Vector3 constant_linear_velocity;50Vector3 constant_angular_velocity;5152Vector3 biased_linear_velocity;53Vector3 biased_angular_velocity;54real_t mass = 1.0;55real_t bounce = 0.0;56real_t friction = 1.0;57Vector3 inertia;5859PhysicsServer3D::BodyDampMode linear_damp_mode = PhysicsServer3D::BODY_DAMP_MODE_COMBINE;60PhysicsServer3D::BodyDampMode angular_damp_mode = PhysicsServer3D::BODY_DAMP_MODE_COMBINE;6162real_t linear_damp = 0.0;63real_t angular_damp = 0.0;6465real_t total_linear_damp = 0.0;66real_t total_angular_damp = 0.0;6768real_t gravity_scale = 1.0;6970uint16_t locked_axis = 0;7172real_t _inv_mass = 1.0;73Vector3 _inv_inertia; // Relative to the principal axes of inertia7475// Relative to the local frame of reference76Basis principal_inertia_axes_local;77Vector3 center_of_mass_local;7879// In world orientation with local origin80Basis _inv_inertia_tensor;81Basis principal_inertia_axes;82Vector3 center_of_mass;8384bool calculate_inertia = true;85bool calculate_center_of_mass = true;8687Vector3 gravity;8889real_t still_time = 0.0;9091Vector3 applied_force;92Vector3 applied_torque;9394Vector3 constant_force;95Vector3 constant_torque;9697SelfList<GodotBody3D> active_list;98SelfList<GodotBody3D> mass_properties_update_list;99SelfList<GodotBody3D> direct_state_query_list;100101VSet<RID> exceptions;102bool omit_force_integration = false;103bool active = true;104105bool continuous_cd = false;106bool can_sleep = true;107bool first_time_kinematic = false;108109void _mass_properties_changed();110virtual void _shapes_changed() override;111Transform3D new_transform;112113HashMap<GodotConstraint3D *, int> constraint_map;114115Vector<AreaCMP> areas;116117struct Contact {118Vector3 local_pos;119Vector3 local_normal;120Vector3 local_velocity_at_pos;121real_t depth = 0.0;122int local_shape = 0;123Vector3 collider_pos;124int collider_shape = 0;125ObjectID collider_instance_id;126RID collider;127Vector3 collider_velocity_at_pos;128Vector3 impulse;129};130131Vector<Contact> contacts; //no contacts by default132int contact_count = 0;133134Callable body_state_callback;135136struct ForceIntegrationCallbackData {137Callable callable;138Variant udata;139};140141ForceIntegrationCallbackData *fi_callback_data = nullptr;142143GodotPhysicsDirectBodyState3D *direct_state = nullptr;144145uint64_t island_step = 0;146147void _update_transform_dependent();148149friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose150151public:152void set_state_sync_callback(const Callable &p_callable);153void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());154155GodotPhysicsDirectBodyState3D *get_direct_state();156157_FORCE_INLINE_ void add_area(GodotArea3D *p_area) {158int index = areas.find(AreaCMP(p_area));159if (index > -1) {160areas.write[index].refCount += 1;161} else {162areas.ordered_insert(AreaCMP(p_area));163}164}165166_FORCE_INLINE_ void remove_area(GodotArea3D *p_area) {167int index = areas.find(AreaCMP(p_area));168if (index > -1) {169areas.write[index].refCount -= 1;170if (areas[index].refCount < 1) {171areas.remove_at(index);172}173}174}175176_FORCE_INLINE_ void set_max_contacts_reported(int p_size) {177ERR_FAIL_INDEX(p_size, MAX_CONTACTS_REPORTED_3D_MAX);178contacts.resize(p_size);179contact_count = 0;180if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && p_size) {181set_active(true);182}183}184_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }185186_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.is_empty(); }187_FORCE_INLINE_ void add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_local_velocity_at_pos, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos, const Vector3 &p_impulse);188189_FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); }190_FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); }191_FORCE_INLINE_ bool has_exception(const RID &p_exception) const { return exceptions.has(p_exception); }192_FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; }193194_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }195_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }196197_FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }198_FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); }199const HashMap<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; }200_FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }201202_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }203_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }204205_FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; }206_FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; }207_FORCE_INLINE_ Vector3 get_center_of_mass_local() const { return center_of_mass_local; }208_FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3 &p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); }209210_FORCE_INLINE_ void set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; }211_FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; }212213_FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; }214_FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; }215216_FORCE_INLINE_ Vector3 get_prev_linear_velocity() const { return prev_linear_velocity; }217_FORCE_INLINE_ Vector3 get_prev_angular_velocity() const { return prev_angular_velocity; }218219_FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; }220_FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; }221222_FORCE_INLINE_ void apply_central_impulse(const Vector3 &p_impulse) {223linear_velocity += p_impulse * _inv_mass;224}225226_FORCE_INLINE_ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) {227linear_velocity += p_impulse * _inv_mass;228angular_velocity += _inv_inertia_tensor.xform((p_position - center_of_mass).cross(p_impulse));229}230231_FORCE_INLINE_ void apply_torque_impulse(const Vector3 &p_impulse) {232angular_velocity += _inv_inertia_tensor.xform(p_impulse);233}234235_FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3(), real_t p_max_delta_av = -1.0) {236biased_linear_velocity += p_impulse * _inv_mass;237if (p_max_delta_av != 0.0) {238Vector3 delta_av = _inv_inertia_tensor.xform((p_position - center_of_mass).cross(p_impulse));239if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) {240delta_av = delta_av.normalized() * p_max_delta_av;241}242biased_angular_velocity += delta_av;243}244}245246_FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_impulse) {247biased_angular_velocity += _inv_inertia_tensor.xform(p_impulse);248}249250_FORCE_INLINE_ void apply_central_force(const Vector3 &p_force) {251applied_force += p_force;252}253254_FORCE_INLINE_ void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {255applied_force += p_force;256applied_torque += (p_position - center_of_mass).cross(p_force);257}258259_FORCE_INLINE_ void apply_torque(const Vector3 &p_torque) {260applied_torque += p_torque;261}262263_FORCE_INLINE_ void add_constant_central_force(const Vector3 &p_force) {264constant_force += p_force;265}266267_FORCE_INLINE_ void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {268constant_force += p_force;269constant_torque += (p_position - center_of_mass).cross(p_force);270}271272_FORCE_INLINE_ void add_constant_torque(const Vector3 &p_torque) {273constant_torque += p_torque;274}275276void set_constant_force(const Vector3 &p_force) { constant_force = p_force; }277Vector3 get_constant_force() const { return constant_force; }278279void set_constant_torque(const Vector3 &p_torque) { constant_torque = p_torque; }280Vector3 get_constant_torque() const { return constant_torque; }281282void set_active(bool p_active);283_FORCE_INLINE_ bool is_active() const { return active; }284285_FORCE_INLINE_ void wakeup() {286if ((!get_space()) || mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {287return;288}289set_active(true);290}291292void set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value);293Variant get_param(PhysicsServer3D::BodyParameter p_param) const;294295void set_mode(PhysicsServer3D::BodyMode p_mode);296PhysicsServer3D::BodyMode get_mode() const;297298void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant);299Variant get_state(PhysicsServer3D::BodyState p_state) const;300301_FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; }302_FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }303304void set_space(GodotSpace3D *p_space) override;305306void update_mass_properties();307void reset_mass_properties();308309_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }310_FORCE_INLINE_ const Vector3 &get_inv_inertia() const { return _inv_inertia; }311_FORCE_INLINE_ const Basis &get_inv_inertia_tensor() const { return _inv_inertia_tensor; }312_FORCE_INLINE_ real_t get_friction() const { return friction; }313_FORCE_INLINE_ real_t get_bounce() const { return bounce; }314315void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock);316bool is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const;317318void integrate_forces(real_t p_step);319void integrate_velocities(real_t p_step);320321_FORCE_INLINE_ Vector3 get_velocity_in_local_point(const Vector3 &rel_pos) const {322return linear_velocity + angular_velocity.cross(rel_pos - center_of_mass);323}324325_FORCE_INLINE_ real_t compute_impulse_denominator(const Vector3 &p_pos, const Vector3 &p_normal) const {326Vector3 r0 = p_pos - get_transform().origin - center_of_mass;327328Vector3 c0 = (r0).cross(p_normal);329330Vector3 vec = (_inv_inertia_tensor.xform_inv(c0)).cross(r0);331332return _inv_mass + p_normal.dot(vec);333}334335_FORCE_INLINE_ real_t compute_angular_impulse_denominator(const Vector3 &p_axis) const {336return p_axis.dot(_inv_inertia_tensor.xform_inv(p_axis));337}338339//void simulate_motion(const Transform3D& p_xform,real_t p_step);340void call_queries();341void wakeup_neighbours();342343bool sleep_test(real_t p_step);344345GodotBody3D();346~GodotBody3D();347};348349//add contact inline350351void GodotBody3D::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_local_velocity_at_pos, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos, const Vector3 &p_impulse) {352int c_max = contacts.size();353354if (c_max == 0) {355return;356}357358Contact *c = contacts.ptrw();359360int idx = -1;361362if (contact_count < c_max) {363idx = contact_count++;364} else {365real_t least_depth = 1e20;366int least_deep = -1;367for (int i = 0; i < c_max; i++) {368if (i == 0 || c[i].depth < least_depth) {369least_deep = i;370least_depth = c[i].depth;371}372}373374if (least_deep >= 0 && least_depth < p_depth) {375idx = least_deep;376}377if (idx == -1) {378return; //none least deepe than this379}380}381382c[idx].local_pos = p_local_pos;383c[idx].local_normal = p_local_normal;384c[idx].local_velocity_at_pos = p_local_velocity_at_pos;385c[idx].depth = p_depth;386c[idx].local_shape = p_local_shape;387c[idx].collider_pos = p_collider_pos;388c[idx].collider_shape = p_collider_shape;389c[idx].collider_instance_id = p_collider_instance_id;390c[idx].collider = p_collider;391c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;392c[idx].impulse = p_impulse;393}394395396