diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/physics_2d/body_2d_sw.cpp | 1 | ||||
-rw-r--r-- | servers/physics_2d/body_2d_sw.h | 8 | ||||
-rw-r--r-- | servers/physics_2d/body_pair_2d_sw.cpp | 53 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.cpp | 67 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.h | 2 |
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: |