summaryrefslogtreecommitdiff
path: root/servers/physics_2d/space_2d_sw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/physics_2d/space_2d_sw.cpp')
-rw-r--r--servers/physics_2d/space_2d_sw.cpp81
1 files changed, 78 insertions, 3 deletions
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 76069de9a0..f2ed74ffbf 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -98,7 +98,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
- //print_line("inters sgment!");
+
Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);
@@ -217,6 +217,16 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
int shape_idx=space->intersection_query_subindex_results[i];
+ /*if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2() && p_motion.dot(body->get_one_way_collision_direction())<=CMP_EPSILON) {
+ print_line("failed in motion dir");
+ continue;
+ }
+ }*/
+
+
Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
@@ -227,6 +237,14 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
//test initial overlap
if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+ //if one way collision direction ignore initial overlap
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2()) {
+ continue;
+ }
+ }
+
return false;
}
@@ -253,6 +271,29 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
}
}
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ if (body->get_one_way_collision_direction()!=Vector2()) {
+
+ Vector2 cd[2];
+ Physics2DServerSW::CollCbkData cbk;
+ cbk.max=1;
+ cbk.amount=0;
+ cbk.ptr=cd;
+ cbk.valid_dir=body->get_one_way_collision_direction();
+ cbk.valid_depth=body->get_one_way_collision_max_depth();
+
+ Vector2 sep=mnormal; //important optimization for this to work fast enough
+ bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*(hi+space->contact_max_allowed_penetration),col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),Physics2DServerSW::_shape_col_cbk,&cbk,&sep,p_margin);
+ if (!collided || cbk.amount==0) {
+ continue;
+ }
+
+ }
+ }
+
+
if (low<best_safe) {
best_safe=low;
best_unsafe=hi;
@@ -311,14 +352,23 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_s
if (p_exclude.has( col_obj->get_self() ))
continue;
-
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ cbk.valid_dir=body->get_one_way_collision_direction();
+ cbk.valid_depth=body->get_one_way_collision_max_depth();
+ } else {
+ cbk.valid_dir=Vector2();
+ cbk.valid_depth=0;
+ }
if (CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),cbkres,cbkptr,NULL,p_margin)) {
- collided=true;
+ collided=p_result_max==0 || cbk.amount>0;
}
}
+
r_result_count=cbk.amount;
return collided;
@@ -334,6 +384,8 @@ struct _RestCallbackData2D {
Vector2 best_contact;
Vector2 best_normal;
float best_len;
+ Vector2 valid_dir;
+ float valid_depth;
};
static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) {
@@ -341,11 +393,23 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
_RestCallbackData2D *rd=(_RestCallbackData2D*)p_userdata;
+ if (rd->valid_dir!=Vector2()) {
+
+ if (rd->valid_dir!=Vector2()) {
+ if (p_point_A.distance_squared_to(p_point_B)>rd->valid_depth*rd->valid_depth)
+ return;
+ if (rd->valid_dir.dot((p_point_A-p_point_B).normalized())<Math_PI*0.25)
+ return;
+ }
+
+ }
+
Vector2 contact_rel = p_point_B - p_point_A;
float len = contact_rel.length();
if (len <= rd->best_len)
return;
+
rd->best_len=len;
rd->best_contact=p_point_B;
rd->best_normal=contact_rel/len;
@@ -385,6 +449,17 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape
if (p_exclude.has( col_obj->get_self() ))
continue;
+ if (col_obj->get_type()==CollisionObject2DSW::TYPE_BODY) {
+
+ const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
+ rcd.valid_dir=body->get_one_way_collision_direction();
+ rcd.valid_depth=body->get_one_way_collision_max_depth();
+ } else {
+ rcd.valid_dir=Vector2();
+ rcd.valid_depth=0;
+ }
+
+
rcd.object=col_obj;
rcd.shape=shape_idx;
bool sc = CollisionSolver2DSW::solve(shape,p_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_rest_cbk_result,&rcd,NULL,p_margin);