summaryrefslogtreecommitdiff
path: root/servers/physics_2d
diff options
context:
space:
mode:
Diffstat (limited to 'servers/physics_2d')
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp1
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp29
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h5
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp4
-rw-r--r--servers/physics_2d/constraint_2d_sw.h5
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp9
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp31
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h5
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h7
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp15
-rw-r--r--servers/physics_2d/shape_2d_sw.h2
-rw-r--r--servers/physics_2d/space_2d_sw.cpp24
-rw-r--r--servers/physics_2d/space_2d_sw.h2
13 files changed, 123 insertions, 16 deletions
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index f51882b5ee..61c0e0063f 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -62,6 +62,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vecto
contact.local_B = local_B;
contact.reused = true;
contact.normal = (p_point_A - p_point_B).normalized();
+ contact.mass_normal = 0; // will be computed in setup()
// attempt to determine if the contact will be reused
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 80cdd58aeb..23084a4241 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -73,6 +73,27 @@ void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_
_shapes_changed();
}
+void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) {
+ ERR_FAIL_INDEX(p_idx, shapes.size());
+
+ CollisionObject2DSW::Shape &shape = shapes[p_idx];
+ if (shape.disabled == p_disabled)
+ return;
+
+ shape.disabled = p_disabled;
+
+ if (!space)
+ return;
+
+ if (p_disabled && shape.bpid != 0) {
+ space->get_broadphase()->remove(shape.bpid);
+ shape.bpid = 0;
+ _update_shapes();
+ } else if (!p_disabled && shape.bpid == 0) {
+ _update_shapes(); // automatically adds shape with bpid == 0
+ }
+}
+
void CollisionObject2DSW::remove_shape(Shape2DSW *p_shape) {
//remove a shape, all the times it appears
@@ -100,6 +121,7 @@ void CollisionObject2DSW::remove_shape(int p_index) {
shapes[p_index].shape->remove_owner(this);
shapes.remove(p_index);
+ _update_shapes();
_shapes_changed();
}
@@ -138,6 +160,10 @@ void CollisionObject2DSW::_update_shapes() {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes[i];
+
+ if (s.disabled)
+ continue;
+
if (s.bpid == 0) {
s.bpid = space->get_broadphase()->create(this, i);
space->get_broadphase()->set_static(s.bpid, _static);
@@ -162,6 +188,9 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes[i];
+ if (s.disabled)
+ continue;
+
if (s.bpid == 0) {
s.bpid = space->get_broadphase()->create(this, i);
space->get_broadphase()->set_static(s.bpid, _static);
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 5f25c27158..ab3e219ac0 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -136,10 +136,7 @@ public:
_FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space2DSW *get_space() const { return space; }
- _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) {
- ERR_FAIL_INDEX(p_idx, shapes.size());
- shapes[p_idx].disabled = p_disabled;
- }
+ void set_shape_as_disabled(int p_idx, bool p_disabled);
_FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, shapes.size(), false);
return shapes[p_idx].disabled;
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index a6ef110149..efee98a35a 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -95,6 +95,10 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Transf
}
Vector2 support_B = p_transform_B.xform(p);
+ if (ray->get_slips_on_slope()) {
+ Vector2 global_n = invb.basis_xform_inv(n).normalized();
+ support_B = support_A + (support_B - support_A).length() * global_n;
+ }
if (p_result_callback) {
if (p_swap_result)
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index a08037bb37..c1954935d3 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -40,6 +40,7 @@ class Constraint2DSW : public RID_Data {
uint64_t island_step;
Constraint2DSW *island_next;
Constraint2DSW *island_list_next;
+ bool disabled_collisions_between_bodies;
RID self;
@@ -48,6 +49,7 @@ protected:
_body_ptr = p_body_ptr;
_body_count = p_body_count;
island_step = 0;
+ disabled_collisions_between_bodies = true;
}
public:
@@ -66,6 +68,9 @@ public:
_FORCE_INLINE_ Body2DSW **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
+ _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; }
+ _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; }
+
virtual bool setup(real_t p_step) = 0;
virtual void solve(real_t p_step) = 0;
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 7fba8acebd..d49c1b8376 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -146,14 +146,19 @@ bool PinJoint2DSW::setup(real_t p_step) {
return true;
}
+inline Vector2 custom_cross(const Vector2 &p_vec, real_t p_other) {
+
+ return Vector2(p_other * p_vec.y, -p_other * p_vec.x);
+}
+
void PinJoint2DSW::solve(real_t p_step) {
// compute relative velocity
- Vector2 vA = A->get_linear_velocity() - rA.cross(A->get_angular_velocity());
+ Vector2 vA = A->get_linear_velocity() - custom_cross(rA, A->get_angular_velocity());
Vector2 rel_vel;
if (B)
- rel_vel = B->get_linear_velocity() - rB.cross(B->get_angular_velocity()) - vA;
+ rel_vel = B->get_linear_velocity() - custom_cross(rB, B->get_angular_velocity()) - vA;
else
rel_vel = -vA;
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 7d7bbbebac..a14fed8184 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -962,14 +962,14 @@ void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
-bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result) {
+bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
}
Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) {
@@ -1015,6 +1015,33 @@ real_t Physics2DServerSW::joint_get_param(RID p_joint, JointParam p_param) const
return 0;
}
+void Physics2DServerSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
+ Joint2DSW *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+
+ joint->disable_collisions_between_bodies(p_disable);
+
+ if (2 == joint->get_body_count()) {
+ Body2DSW *body_a = *joint->get_body_ptr();
+ Body2DSW *body_b = *(joint->get_body_ptr() + 1);
+
+ if (p_disable) {
+ body_add_collision_exception(body_a->get_self(), body_b->get_self());
+ body_add_collision_exception(body_b->get_self(), body_a->get_self());
+ } else {
+ body_remove_collision_exception(body_a->get_self(), body_b->get_self());
+ body_remove_collision_exception(body_b->get_self(), body_a->get_self());
+ }
+ }
+}
+
+bool Physics2DServerSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
+ const Joint2DSW *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, true);
+
+ return joint->is_disabled_collisions_between_bodies();
+}
+
RID Physics2DServerSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
Body2DSW *A = body_owner.get(p_body_a);
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 97edb85582..036eb934e1 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -232,7 +232,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable);
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL);
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL);
// this function only works on physics process, errors and returns null otherwise
virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body);
@@ -242,6 +242,9 @@ public:
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
virtual real_t joint_get_param(RID p_joint, JointParam p_param) const;
+ virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled);
+ virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const;
+
virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID());
virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b);
virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID());
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 276c37c577..a15e8bde8b 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -245,10 +245,10 @@ public:
FUNC2(body_set_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL) {
+ bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL) {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result);
+ return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
}
// this function only works on physics process, errors and returns null otherwise
@@ -263,6 +263,9 @@ public:
FUNC3(joint_set_param, RID, JointParam, real_t);
FUNC2RC(real_t, joint_get_param, RID, JointParam);
+ FUNC2(joint_disable_collisions_between_bodies, RID, const bool);
+ FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID);
+
///FUNC3RID(pin_joint,const Vector2&,RID,RID);
///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID);
///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID);
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 4605516fe0..2b0eab5999 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -184,13 +184,18 @@ real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale)
void RayShape2DSW::set_data(const Variant &p_data) {
- length = p_data;
+ Dictionary d = p_data;
+ length = d["length"];
+ slips_on_slope = d["slips_on_slope"];
configure(Rect2(0, 0, 0.001, length));
}
Variant RayShape2DSW::get_data() const {
- return length;
+ Dictionary d;
+ d["length"] = length;
+ d["slips_on_slope"] = slips_on_slope;
+ return d;
}
/*********************************************************/
@@ -589,7 +594,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec
for (int i = 0; i < point_count; i++) {
- //hmm crap.. no can do..
+ //hmm.. no can do..
/*
if (d.dot(points[i].normal)>=0)
continue;
@@ -1006,6 +1011,10 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
stack[i]=0;
*/
+ if (segments.size() == 0 || points.size() == 0 || bvh.size() == 0) {
+ return;
+ }
+
int level = 0;
const Segment *segmentptr = &segments[0];
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index c4c267b368..d937301f3c 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -197,9 +197,11 @@ public:
class RayShape2DSW : public Shape2DSW {
real_t length;
+ bool slips_on_slope;
public:
_FORCE_INLINE_ real_t get_length() const { return length; }
+ _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; }
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; }
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index d3b81c627a..503ca0af4a 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -33,6 +33,7 @@
#include "collision_solver_2d_sw.h"
#include "pair.h"
#include "physics_2d_server_sw.h"
+
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask) {
return p_object->get_collision_layer() & p_collision_mask;
@@ -483,7 +484,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
@@ -550,6 +551,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
+ if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
@@ -638,6 +646,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
+ if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
@@ -768,6 +783,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
+ if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
+ const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
+ continue;
+ }
+ }
+
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
bool excluded = false;
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index a18bb2be2d..79349c46f3 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -182,7 +182,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }