diff --git a/doc/base/classes.xml b/doc/base/classes.xml index a71b897e8c9..9f6daafdd42 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -24661,6 +24661,17 @@ This method controls whether the position between two cached points is interpola + + + + + + + + + Add a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. + + @@ -24948,13 +24959,15 @@ This method controls whether the position between two cached points is interpola - + - + - + - + + + @@ -30147,6 +30160,20 @@ This method controls whether the position between two cached points is interpola Return the body mass. + + + + + Return the body's moment of inertia. This is usually automatically computed from the mass and the shapes. Note that this doesn't seem to work in a [code]_ready[/code] function: it apparently has not been auto-computed yet. + + + + + + + Set the body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body. The moment of inertia is usually computed automatically from the mass and the shapes, but this function allows you to set a custom value. Set 0 (or negative) inertia to return to automatically computing it. + + @@ -30324,12 +30351,12 @@ This method controls whether the position between two cached points is interpola - + - Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. + Apply a positioned impulse (which will be affected by the body mass and shape). This is the equivalent of hitting a billiard ball with a cue: a force that is applied once, and only once. Both the impulse and the offset from the body origin are in global coordinates. @@ -30346,6 +30373,29 @@ This method controls whether the position between two cached points is interpola Return the applied force vector. + + + + + Set a constant torque which will be applied to this body. + + + + + + + Return the torque which is being applied to this body. + + + + + + + + + Add a positioned force to the applied force and torque. As with [method apply_impulse], both the force and the offset from the body origin are in global coordinates. + + diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index dc038f010c8..8f0474b7658 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -602,6 +602,17 @@ real_t RigidBody2D::get_mass() const{ return mass; } +void RigidBody2D::set_inertia(real_t p_inertia) { + + ERR_FAIL_COND(p_inertia<=0); + Physics2DServer::get_singleton()->body_set_param(get_rid(),Physics2DServer::BODY_PARAM_INERTIA,p_inertia); +} + +real_t RigidBody2D::get_inertia() const{ + + return Physics2DServer::get_singleton()->body_get_param(get_rid(),Physics2DServer::BODY_PARAM_INERTIA); +} + void RigidBody2D::set_weight(real_t p_weight){ set_mass(p_weight/9.8); @@ -767,9 +778,9 @@ int RigidBody2D::get_max_contacts_reported() const{ return max_contacts_reported; } -void RigidBody2D::apply_impulse(const Vector2& p_pos, const Vector2& p_impulse) { +void RigidBody2D::apply_impulse(const Vector2& p_offset, const Vector2& p_impulse) { - Physics2DServer::get_singleton()->body_apply_impulse(get_rid(),p_pos,p_impulse); + Physics2DServer::get_singleton()->body_apply_impulse(get_rid(),p_offset,p_impulse); } void RigidBody2D::set_applied_force(const Vector2& p_force) { @@ -782,6 +793,20 @@ Vector2 RigidBody2D::get_applied_force() const { return Physics2DServer::get_singleton()->body_get_applied_force(get_rid()); }; +void RigidBody2D::set_applied_torque(const float p_torque) { + + Physics2DServer::get_singleton()->body_set_applied_torque(get_rid(), p_torque); +}; + +float RigidBody2D::get_applied_torque() const { + + return Physics2DServer::get_singleton()->body_get_applied_torque(get_rid()); +}; + +void RigidBody2D::add_force(const Vector2& p_offset, const Vector2& p_force) { + + Physics2DServer::get_singleton()->body_add_force(get_rid(),p_offset,p_force); +} void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { @@ -858,6 +883,9 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_mass","mass"),&RigidBody2D::set_mass); ObjectTypeDB::bind_method(_MD("get_mass"),&RigidBody2D::get_mass); + ObjectTypeDB::bind_method(_MD("get_inertia"),&RigidBody2D::get_inertia); + ObjectTypeDB::bind_method(_MD("set_inertia","inertia"),&RigidBody2D::set_inertia); + ObjectTypeDB::bind_method(_MD("set_weight","weight"),&RigidBody2D::set_weight); ObjectTypeDB::bind_method(_MD("get_weight"),&RigidBody2D::get_weight); @@ -895,11 +923,16 @@ void RigidBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_continuous_collision_detection_mode"),&RigidBody2D::get_continuous_collision_detection_mode); ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity); - ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody2D::apply_impulse); + ObjectTypeDB::bind_method(_MD("apply_impulse","offset","impulse"),&RigidBody2D::apply_impulse); ObjectTypeDB::bind_method(_MD("set_applied_force","force"),&RigidBody2D::set_applied_force); ObjectTypeDB::bind_method(_MD("get_applied_force"),&RigidBody2D::get_applied_force); + ObjectTypeDB::bind_method(_MD("set_applied_torque","torque"),&RigidBody2D::set_applied_torque); + ObjectTypeDB::bind_method(_MD("get_applied_torque"),&RigidBody2D::get_applied_torque); + + ObjectTypeDB::bind_method(_MD("add_force","offset","force"),&RigidBody2D::add_force); + ObjectTypeDB::bind_method(_MD("set_sleeping","sleeping"),&RigidBody2D::set_sleeping); ObjectTypeDB::bind_method(_MD("is_sleeping"),&RigidBody2D::is_sleeping); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 999e63dd5d1..5af65bff33c 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -217,6 +217,9 @@ public: void set_mass(real_t p_mass); real_t get_mass() const; + void set_inertia(real_t p_inertia); + real_t get_inertia() const; + void set_weight(real_t p_weight); real_t get_weight() const; @@ -261,11 +264,16 @@ public: void set_continuous_collision_detection_mode(CCDMode p_mode); CCDMode get_continuous_collision_detection_mode() const; - void apply_impulse(const Vector2& p_pos, const Vector2& p_impulse); + void apply_impulse(const Vector2& p_offset, const Vector2& p_impulse); void set_applied_force(const Vector2& p_force); Vector2 get_applied_force() const; + void set_applied_torque(const float p_torque); + float get_applied_torque() const; + + void add_force(const Vector2& p_offset, const Vector2& p_force); + Array get_colliding_bodies() const; //function for script diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index ab1c7ef66fc..12ac0bd1caa 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -33,7 +33,7 @@ void Body2DSW::_update_inertia() { - if (get_space() && !inertia_update_list.in_list()) + if (!user_inertia && get_space() && !inertia_update_list.in_list()) get_space()->body_add_to_inertia_update_list(&inertia_update_list); } @@ -48,6 +48,8 @@ void Body2DSW::update_inertias() { case Physics2DServer::BODY_MODE_RIGID: { + if(user_inertia) break; + //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet) float total_area=0; @@ -157,6 +159,15 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) _update_inertia(); } break; + case Physics2DServer::BODY_PARAM_INERTIA: { + if(p_value<=0) { + user_inertia = false; + _update_inertia(); + } else { + user_inertia = true; + _inv_inertia = 1.0 / p_value; + } + } break; case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { gravity_scale=p_value; } break; @@ -186,6 +197,9 @@ float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { case Physics2DServer::BODY_PARAM_MASS: { return mass; } break; + case Physics2DServer::BODY_PARAM_INERTIA: { + return _inv_inertia==0 ? 0 : 1.0 / _inv_inertia; + } break; case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; } break; @@ -665,6 +679,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti angular_velocity=0; biased_angular_velocity=0; mass=1; + user_inertia=false; _inv_inertia=0; _inv_mass=1; bounce=0; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index b7f3ab01db4..ed980176290 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -57,6 +57,7 @@ class Body2DSW : public CollisionObject2DSW { real_t _inv_mass; real_t _inv_inertia; + bool user_inertia; Vector2 gravity; real_t area_linear_damp; @@ -204,10 +205,10 @@ public: _FORCE_INLINE_ real_t get_biased_angular_velocity() const { return biased_angular_velocity; } - _FORCE_INLINE_ void apply_impulse(const Vector2& p_pos, const Vector2& p_j) { + _FORCE_INLINE_ void apply_impulse(const Vector2& p_offset, const Vector2& p_impulse) { - linear_velocity += p_j * _inv_mass; - angular_velocity += _inv_inertia * p_pos.cross(p_j); + linear_velocity += p_impulse * _inv_mass; + angular_velocity += _inv_inertia * p_offset.cross(p_impulse); } _FORCE_INLINE_ void apply_bias_impulse(const Vector2& p_pos, const Vector2& p_j) { @@ -243,6 +244,11 @@ public: void set_applied_torque(real_t p_torque) { applied_torque=p_torque; } real_t get_applied_torque() const { return applied_torque; } + _FORCE_INLINE_ void add_force(const Vector2& p_force, const Vector2& p_offset) { + + applied_force += p_force; + applied_torque += p_offset.cross(p_force); + } _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; } _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index c571331498d..3796ddd961e 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -860,6 +860,15 @@ void Physics2DServerSW::body_apply_impulse(RID p_body, const Vector2& p_pos, con body->wakeup(); }; +void Physics2DServerSW::body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_force,p_offset); + body->wakeup(); +}; + void Physics2DServerSW::body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity) { Body2DSW *body = body_owner.get(p_body); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index cd4dfc1a8b6..6415786803d 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -205,6 +205,8 @@ public: virtual void body_set_applied_torque(RID p_body, float p_torque); virtual float body_get_applied_torque(RID p_body) const; + virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force); + virtual void body_apply_impulse(RID p_body, const Vector2& p_pos, const Vector2& p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 60f8a4c879f..891c45addfb 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -205,6 +205,7 @@ public: FUNC2(body_set_applied_torque,RID,float); FUNC1RC(float,body_get_applied_torque,RID); + FUNC3(body_add_force,RID,const Vector2&,const Vector2&); FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); FUNC2(body_set_axis_velocity,RID,const Vector2&); diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 2d267a5749c..a85fefe5ada 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -597,6 +597,7 @@ void Physics2DServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state); ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse); + ObjectTypeDB::bind_method(_MD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force); ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity); ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception); @@ -677,6 +678,7 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( BODY_PARAM_BOUNCE ); BIND_CONSTANT( BODY_PARAM_FRICTION ); BIND_CONSTANT( BODY_PARAM_MASS ); + BIND_CONSTANT( BODY_PARAM_INERTIA ); BIND_CONSTANT( BODY_PARAM_GRAVITY_SCALE ); BIND_CONSTANT( BODY_PARAM_LINEAR_DAMP); BIND_CONSTANT( BODY_PARAM_ANGULAR_DAMP); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 25875f16d37..dd04f0f6b88 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -421,6 +421,7 @@ public: BODY_PARAM_BOUNCE, BODY_PARAM_FRICTION, BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_INERTIA, // read-only: computed from mass & shapes BODY_PARAM_GRAVITY_SCALE, BODY_PARAM_LINEAR_DAMP, BODY_PARAM_ANGULAR_DAMP, @@ -450,7 +451,9 @@ public: virtual void body_set_applied_torque(RID p_body, float p_torque)=0; virtual float body_get_applied_torque(RID p_body) const=0; - virtual void body_apply_impulse(RID p_body, const Vector2& p_pos, const Vector2& p_impulse)=0; + virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force)=0; + + virtual void body_apply_impulse(RID p_body, const Vector2& p_offset, const Vector2& p_impulse)=0; virtual void body_set_axis_velocity(RID p_body, const Vector2& p_axis_velocity)=0; //fix