summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/physics_2d/body_2d_sw.cpp1
-rw-r--r--servers/physics_2d/body_2d_sw.h8
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp53
-rw-r--r--servers/physics_2d/space_2d_sw.cpp67
-rw-r--r--servers/physics_2d/space_2d_sw.h2
5 files changed, 100 insertions, 31 deletions
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 464b818384..0ba661b4c4 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -657,6 +657,7 @@ Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inerti
area_linear_damp=0;
contact_count=0;
gravity_scale=1.0;
+ using_one_way_cache=false;
one_way_collision_max_depth=0.1;
still_time=0;
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index ca4d80a15b..e34686f3ac 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -81,6 +81,7 @@ class Body2DSW : public CollisionObject2DSW {
bool active;
bool can_sleep;
bool first_time_kinematic;
+ bool using_one_way_cache;
void _update_inertia();
virtual void _shapes_changed();
Matrix32 new_transform;
@@ -229,12 +230,17 @@ public:
_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; }
- void set_one_way_collision_direction(const Vector2& p_dir) { one_way_collision_direction=p_dir; }
+ void set_one_way_collision_direction(const Vector2& p_dir) {
+ one_way_collision_direction=p_dir;
+ using_one_way_cache=one_way_collision_direction!=Vector2();
+ }
Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; }
void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; }
float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
+ _FORCE_INLINE_ bool is_using_one_way_collision() const { return using_one_way_cache; }
+
void set_space(Space2DSW *p_space);
void update_inertias();
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index 8913e396d2..e8d37d346a 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -265,6 +265,8 @@ bool BodyPair2DSW::setup(float p_step) {
}
//faster to set than to check..
+ bool prev_collided=collided;
+
collided = CollisionSolver2DSW::solve(shape_A_ptr,xform_A,motion_A,shape_B_ptr,xform_B,motion_B,_add_contact,this,&sep_axis);
if (!collided) {
@@ -285,6 +287,57 @@ bool BodyPair2DSW::setup(float p_step) {
}
+ if (!prev_collided) {
+
+ if (A->is_using_one_way_collision()) {
+ Vector2 direction = A->get_one_way_collision_direction();
+ bool valid=false;
+ for(int i=0;i<contact_count;i++) {
+ Contact& c = contacts[i];
+
+ if (c.normal.dot(direction)<0)
+ continue;
+ if (B->get_linear_velocity().dot(direction)<0)
+ continue;
+
+ if (!c.reused) {
+ continue;
+ }
+
+ valid=true;
+ }
+
+ if (!valid) {
+ collided=false;
+ return false;
+ }
+ }
+
+ if (B->is_using_one_way_collision()) {
+ Vector2 direction = B->get_one_way_collision_direction();
+ bool valid=false;
+ for(int i=0;i<contact_count;i++) {
+
+ Contact& c = contacts[i];
+
+ if (c.normal.dot(direction)<0)
+ continue;
+ if (A->get_linear_velocity().dot(direction)<0)
+ continue;
+
+ if (!c.reused) {
+ continue;
+ }
+
+ valid=true;
+ }
+ if (!valid) {
+ collided=false;
+ return false;
+ }
+ }
+ }
+
real_t max_penetration = space->get_contact_max_allowed_penetration();
float bias = 0.3f;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 40e7b19f6f..b38cf0c2df 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -555,38 +555,10 @@ Physics2DDirectSpaceStateSW::Physics2DDirectSpaceStateSW() {
+int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) {
-bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p_margin,Physics2DServer::MotionResult *r_result) {
-
- //give me back regular physics engine logic
- //this is madness
- //and most people using this function will think
- //what it does is simpler than using physics
- //this took about a week to get right..
- //but is it right? who knows at this point..
-
- Rect2 body_aabb;
-
- for(int i=0;i<p_body->get_shape_count();i++) {
-
- if (i==0)
- body_aabb=p_body->get_shape_aabb(i);
- else
- body_aabb=body_aabb.merge(p_body->get_shape_aabb(i));
- }
-
- body_aabb=body_aabb.grow(p_margin);
-
- {
- //add motion
- Rect2 motion_aabb=body_aabb;
- motion_aabb.pos+=p_motion;
- body_aabb=body_aabb.merge(motion_aabb);
- }
-
-
- int amount = broadphase->cull_aabb(body_aabb,intersection_query_results,INTERSECTION_QUERY_MAX,intersection_query_subindex_results);
+ int amount = broadphase->cull_aabb(p_aabb,intersection_query_results,INTERSECTION_QUERY_MAX,intersection_query_subindex_results);
for(int i=0;i<amount;i++) {
@@ -617,6 +589,31 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
}
}
+ return amount;
+}
+
+bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p_margin,Physics2DServer::MotionResult *r_result) {
+
+ //give me back regular physics engine logic
+ //this is madness
+ //and most people using this function will think
+ //what it does is simpler than using physics
+ //this took about a week to get right..
+ //but is it right? who knows at this point..
+
+ Rect2 body_aabb;
+
+ for(int i=0;i<p_body->get_shape_count();i++) {
+
+ if (i==0)
+ body_aabb=p_body->get_shape_aabb(i);
+ else
+ body_aabb=body_aabb.merge(p_body->get_shape_aabb(i));
+ }
+
+ body_aabb=body_aabb.grow(p_margin);
+
+
Matrix32 body_transform = p_body->get_transform();
{
@@ -642,6 +639,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
bool collided=false;
+ int amount = _cull_aabb_for_body(p_body,body_aabb);
for(int j=0;j<p_body->get_shape_count();j++) {
if (p_body->is_shape_set_as_trigger(j))
@@ -694,6 +692,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
}
body_transform.elements[2]+=recover_motion;
+ body_aabb.pos+=recover_motion;
recover_attempts--;
@@ -709,7 +708,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
{
// STEP 2 ATTEMPT MOTION
+ Rect2 motion_aabb=body_aabb;
+ motion_aabb.pos+=p_motion;
+ motion_aabb=motion_aabb.merge(body_aabb);
+ int amount = _cull_aabb_for_body(p_body,motion_aabb);
for(int j=0;j<p_body->get_shape_count();j++) {
@@ -847,6 +850,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body,const Vector2&p_motion,float p
Matrix32 body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
Shape2DSW *body_shape = p_body->get_shape(best_shape);
+ body_aabb.pos+=p_motion*unsafe;
+
+ int amount = _cull_aabb_for_body(p_body,body_aabb);
+
for(int i=0;i<amount;i++) {
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 95a576609e..abee8628fc 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -101,6 +101,8 @@ class Space2DSW {
int active_objects;
int collision_pairs;
+ int _cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb);
+
friend class Physics2DDirectSpaceStateSW;
public: