summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/physics/body_pair_sw.cpp42
-rw-r--r--servers/physics/body_sw.cpp16
-rw-r--r--servers/physics/body_sw.h8
-rw-r--r--servers/physics/physics_server_sw.cpp14
-rw-r--r--servers/physics/physics_server_sw.h4
-rw-r--r--servers/physics_2d/body_2d_sw.cpp16
-rw-r--r--servers/physics_2d/body_2d_sw.h8
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp42
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp16
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h4
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h3
-rw-r--r--servers/physics_2d_server.h13
-rw-r--r--servers/physics_server.h13
13 files changed, 195 insertions, 4 deletions
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 2a6a9e08ae..5a41b621eb 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -211,6 +211,44 @@ bool BodyPairSW::_test_ccd(real_t p_step, BodySW *p_A, int p_shape_A, const Tran
return true;
}
+real_t combine_bounce(BodySW *A, BodySW *B) {
+ const PhysicsServer::CombineMode cm = A->get_bounce_combine_mode();
+
+ switch (cm) {
+ case PhysicsServer::COMBINE_MODE_INHERIT:
+ if (B->get_bounce_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
+ return combine_bounce(B, A);
+ // else use MAX [This is used when the two bodies doesn't use physical material]
+ case PhysicsServer::COMBINE_MODE_MAX:
+ return MAX(A->get_bounce(), B->get_bounce());
+ case PhysicsServer::COMBINE_MODE_MIN:
+ return MIN(A->get_bounce(), B->get_bounce());
+ case PhysicsServer::COMBINE_MODE_MULTIPLY:
+ return A->get_bounce() * B->get_bounce();
+ default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
+ return (A->get_bounce() + B->get_bounce()) / 2;
+ }
+}
+
+real_t combine_friction(BodySW *A, BodySW *B) {
+ const PhysicsServer::CombineMode cm = A->get_friction_combine_mode();
+
+ switch (cm) {
+ case PhysicsServer::COMBINE_MODE_INHERIT:
+ if (B->get_friction_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
+ return combine_friction(B, A);
+ // else use Multiply [This is used when the two bodies doesn't use physical material]
+ case PhysicsServer::COMBINE_MODE_MULTIPLY:
+ return A->get_friction() * B->get_friction();
+ case PhysicsServer::COMBINE_MODE_MAX:
+ return MAX(A->get_friction(), B->get_friction());
+ case PhysicsServer::COMBINE_MODE_MIN:
+ return MIN(A->get_friction(), B->get_friction());
+ default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
+ return (A->get_friction() + B->get_friction()) / 2;
+ }
+}
+
bool BodyPairSW::setup(real_t p_step) {
//cannot collide
@@ -331,7 +369,7 @@ bool BodyPairSW::setup(real_t p_step) {
c.acc_bias_impulse = 0;
c.acc_bias_impulse_center_of_mass = 0;
- c.bounce = MAX(A->get_bounce(), B->get_bounce());
+ c.bounce = combine_bounce(A, B);
if (c.bounce) {
Vector3 crA = A->get_angular_velocity().cross(c.rA);
@@ -421,7 +459,7 @@ void BodyPairSW::solve(real_t p_step) {
//friction impulse
- real_t friction = A->get_friction() * B->get_friction();
+ real_t friction = combine_friction(A, B);
Vector3 lvA = A->get_linear_velocity() + A->get_angular_velocity().cross(c.rA);
Vector3 lvB = B->get_linear_velocity() + B->get_angular_velocity().cross(c.rB);
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index cc9681193c..59f987fc17 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -423,6 +423,22 @@ void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
+void BodySW::set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode) {
+ if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
+ bounce_combine_mode = p_mode;
+ } else {
+ friction_combine_mode = p_mode;
+ }
+}
+
+PhysicsServer::CombineMode BodySW::get_combine_mode(PhysicsServer::BodyParameter p_param) const {
+ if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
+ return bounce_combine_mode;
+ } else {
+ return friction_combine_mode;
+ }
+}
+
void BodySW::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) {
if (lock) {
locked_axis |= p_axis;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index fd2ab16b84..25eb20f5d8 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -49,6 +49,8 @@ class BodySW : public CollisionObjectSW {
real_t mass;
real_t bounce;
real_t friction;
+ PhysicsServer::CombineMode bounce_combine_mode;
+ PhysicsServer::CombineMode friction_combine_mode;
real_t linear_damp;
real_t angular_damp;
@@ -298,6 +300,12 @@ public:
_FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
+ void set_combine_mode(PhysicsServer::BodyParameter p_param, PhysicsServer::CombineMode p_mode);
+ PhysicsServer::CombineMode get_combine_mode(PhysicsServer::BodyParameter p_param) const;
+
+ _FORCE_INLINE_ PhysicsServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; }
+ _FORCE_INLINE_ PhysicsServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; }
+
void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock);
bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const;
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 593218dd5d..f1e0cbef29 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -701,6 +701,20 @@ real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const
return body->get_param(p_param);
};
+void PhysicsServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) {
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_combine_mode(p_param, p_mode);
+}
+
+PhysicsServer::CombineMode PhysicsServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const {
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT);
+
+ return body->get_combine_mode(p_param);
+}
+
void PhysicsServerSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 3f56ba26d0..d8c73abb16 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -188,6 +188,10 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
+ /// p_param accept only Bounce and Friction
+ virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode);
+ virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const;
+
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin);
virtual real_t body_get_kinematic_safe_margin(RID p_body) const;
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index aa063d6c1e..fcd2a65ee7 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -405,6 +405,22 @@ void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
+void Body2DSW::set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode) {
+ if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) {
+ bounce_combine_mode = p_mode;
+ } else {
+ friction_combine_mode = p_mode;
+ }
+}
+
+Physics2DServer::CombineMode Body2DSW::get_combine_mode(Physics2DServer::BodyParameter p_param) const {
+ if (p_param == Physics2DServer::BODY_PARAM_BOUNCE) {
+ return bounce_combine_mode;
+ } else {
+ return friction_combine_mode;
+ }
+}
+
void Body2DSW::integrate_forces(real_t p_step) {
if (mode == Physics2DServer::BODY_MODE_STATIC)
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 782adf3416..301bd6b299 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -54,6 +54,8 @@ class Body2DSW : public CollisionObject2DSW {
real_t mass;
real_t bounce;
real_t friction;
+ Physics2DServer::CombineMode bounce_combine_mode;
+ Physics2DServer::CombineMode friction_combine_mode;
real_t _inv_mass;
real_t _inv_inertia;
@@ -256,6 +258,12 @@ public:
_FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
_FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
+ void set_combine_mode(Physics2DServer::BodyParameter p_param, Physics2DServer::CombineMode p_mode);
+ Physics2DServer::CombineMode get_combine_mode(Physics2DServer::BodyParameter p_param) const;
+
+ _FORCE_INLINE_ Physics2DServer::CombineMode get_bounce_combine_mode() const { return bounce_combine_mode; }
+ _FORCE_INLINE_ Physics2DServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; }
+
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index 61c0e0063f..be8dcf6fa8 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -219,6 +219,44 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const
return true;
}
+real_t combine_bounce(Body2DSW *A, Body2DSW *B) {
+ const Physics2DServer::CombineMode cm = A->get_bounce_combine_mode();
+
+ switch (cm) {
+ case Physics2DServer::COMBINE_MODE_INHERIT:
+ if (B->get_bounce_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT)
+ return combine_bounce(B, A);
+ // else use MAX [This is used when the two bodies doesn't use physical material]
+ case Physics2DServer::COMBINE_MODE_MAX:
+ return MAX(A->get_bounce(), B->get_bounce());
+ case Physics2DServer::COMBINE_MODE_MIN:
+ return MIN(A->get_bounce(), B->get_bounce());
+ case Physics2DServer::COMBINE_MODE_MULTIPLY:
+ return A->get_bounce() * B->get_bounce();
+ default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE:
+ return (A->get_bounce() + B->get_bounce()) / 2;
+ }
+}
+
+real_t combine_friction(Body2DSW *A, Body2DSW *B) {
+ const Physics2DServer::CombineMode cm = A->get_friction_combine_mode();
+
+ switch (cm) {
+ case Physics2DServer::COMBINE_MODE_INHERIT:
+ if (B->get_friction_combine_mode() != Physics2DServer::COMBINE_MODE_INHERIT)
+ return combine_friction(B, A);
+ // else use Multiply [This is used when the two bodies doesn't use physical material]
+ case Physics2DServer::COMBINE_MODE_MULTIPLY:
+ return A->get_friction() * B->get_friction();
+ case Physics2DServer::COMBINE_MODE_MAX:
+ return MAX(A->get_friction(), B->get_friction());
+ case Physics2DServer::COMBINE_MODE_MIN:
+ return MIN(A->get_friction(), B->get_friction());
+ default: // Is always Physics2DServer::COMBINE_MODE_AVERAGE:
+ return (A->get_friction() + B->get_friction()) / 2;
+ }
+}
+
bool BodyPair2DSW::setup(real_t p_step) {
//cannot collide
@@ -432,7 +470,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
#endif
- c.bounce = MAX(A->get_bounce(), B->get_bounce());
+ c.bounce = combine_bounce(A, B);
if (c.bounce) {
Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
@@ -488,7 +526,7 @@ void BodyPair2DSW::solve(real_t p_step) {
real_t jnOld = c.acc_normal_impulse;
c.acc_normal_impulse = MAX(jnOld + jn, 0.0f);
- real_t friction = A->get_friction() * B->get_friction();
+ real_t friction = combine_friction(A, B);
real_t jtMax = friction * c.acc_normal_impulse;
real_t jt = -vt * c.mass_tangent;
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index a473e0beb2..cfcef8cb04 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -789,6 +789,22 @@ real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) cons
return body->get_param(p_param);
};
+void Physics2DServerSW::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_combine_mode(p_param, p_mode);
+}
+
+Physics2DServer::CombineMode Physics2DServerSW::body_get_combine_mode(RID p_body, BodyParameter p_param) const {
+
+ Body2DSW *body = body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT);
+
+ return body->get_combine_mode(p_param);
+}
+
void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
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 e5961b9011..bf00746063 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -200,6 +200,10 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
+ /// p_param accept only Bounce and Friction
+ virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode);
+ virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const;
+
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant);
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 3119b930d7..a85cd5ef8d 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -211,6 +211,9 @@ public:
FUNC3(body_set_param, RID, BodyParameter, real_t);
FUNC2RC(real_t, body_get_param, RID, BodyParameter);
+ FUNC3(body_set_combine_mode, RID, BodyParameter, CombineMode);
+ FUNC2RC(CombineMode, body_get_combine_mode, RID, BodyParameter);
+
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 1d04fbc5c6..89c649af49 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -416,6 +416,19 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ enum CombineMode {
+ COMBINE_MODE_MAX,
+ COMBINE_MODE_MIN,
+ COMBINE_MODE_MULTIPLY,
+ COMBINE_MODE_AVERAGE,
+
+ COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction)
+ };
+
+ /// p_param accept only Bounce and Friction
+ virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0;
+ virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0;
+
//state
enum BodyState {
BODY_STATE_TRANSFORM,
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 8ecf17c0e6..91e7f58319 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -399,6 +399,19 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ enum CombineMode {
+ COMBINE_MODE_MAX,
+ COMBINE_MODE_MIN,
+ COMBINE_MODE_MULTIPLY,
+ COMBINE_MODE_AVERAGE,
+
+ COMBINE_MODE_INHERIT /// Inherit from other body or use COMBINE_MODE_MAX (Restitution) COMBINE_MODE_MULTIPLY (Friction)
+ };
+
+ /// p_param accept only Bounce and Friction
+ virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) = 0;
+ virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const = 0;
+
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0;
virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0;