예제 #1
0
void Physics2DServerSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {

	Shape2DSW *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);
	shape->set_custom_bias(p_bias);

}
예제 #2
0
void Physics2DServerSW::shape_set_data(RID p_shape, const Variant& p_data) {

	Shape2DSW *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);
	shape->set_data(p_data);


};
예제 #3
0
파일: space_2d_sw.cpp 프로젝트: 9cat/godot
bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {


	Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,0);

	Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
	aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
	aabb=aabb.grow(p_margin);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	_RestCallbackData rcd;
	rcd.best_len=0;
	rcd.best_object=NULL;
	rcd.best_shape=0;

	for(int i=0;i<amount;i++) {


		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
			continue;

		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];

		if (p_exclude.has( col_obj->get_self() ))
			continue;

		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);
		if (!sc)
			continue;


	}

	if (rcd.best_len==0)
		return false;

	r_info->collider_id=rcd.best_object->get_instance_id();
	r_info->shape=rcd.best_shape;
	r_info->normal=rcd.best_normal;
	r_info->point=rcd.best_contact;
	r_info->rid=rcd.best_object->get_self();
	if (rcd.best_object->get_type()==CollisionObject2DSW::TYPE_BODY) {

		const Body2DSW *body = static_cast<const Body2DSW*>(rcd.best_object);
		Vector2 rel_vec = r_info->point-body->get_transform().get_origin();
		r_info->linear_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();

	} else {
		r_info->linear_velocity=Vector2();
	}

	return true;
}
예제 #4
0
RID Physics2DServerSW::area_get_shape(RID p_area, int p_shape_idx) const {

	Area2DSW *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, RID());

	Shape2DSW *shape = area->get_shape(p_shape_idx);
	ERR_FAIL_COND_V(!shape, RID());

	return shape->get_self();
}
예제 #5
0
RID Physics2DServerSW::body_get_shape(RID p_body, int p_shape_idx) const {

	Body2DSW *body = body_owner.get(p_body);
	ERR_FAIL_COND_V(!body, RID());

	Shape2DSW *shape = body->get_shape(p_shape_idx);
	ERR_FAIL_COND_V(!shape, RID());

	return shape->get_self();
}
예제 #6
0
void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {

	Body2DSW *body = body_owner.get(p_body);
	ERR_FAIL_COND(!body);

	Shape2DSW *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);
	ERR_FAIL_COND(!shape->is_configured());

	body->set_shape(p_shape_idx, shape);
}
예제 #7
0
void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {

	Area2DSW *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	Shape2DSW *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);
	ERR_FAIL_COND(!shape->is_configured());

	area->set_shape(p_shape_idx, shape);
}
예제 #8
0
파일: space_2d_sw.cpp 프로젝트: 9cat/godot
bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {


	if (p_result_max<=0)
		return 0;

	Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,0);

	Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
	aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
	aabb=aabb.grow(p_margin);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	bool collided=false;
	int cc=0;
	r_result_count=0;

	Physics2DServerSW::CollCbkData cbk;
	cbk.max=p_result_max;
	cbk.amount=0;
	cbk.ptr=r_results;
	CollisionSolver2DSW::CallbackResult cbkres=NULL;

	Physics2DServerSW::CollCbkData *cbkptr=NULL;
	if (p_result_max>0) {
		cbkptr=&cbk;
		cbkres=Physics2DServerSW::_shape_col_cbk;
	}


	for(int i=0;i<amount;i++) {

		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
			continue;

		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];

		if (p_exclude.has( col_obj->get_self() ))
			continue;


		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;
		}

	}

	r_result_count=cbk.amount;

	return collided;
}
예제 #9
0
int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,bool p_pick_point) {

	if (p_result_max<=0)
		return 0;

	Rect2 aabb;
	aabb.pos=p_point-Vector2(0.00001,0.00001);
	aabb.size=Vector2(0.00002,0.00002);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	int cc=0;

	for(int i=0;i<amount;i++) {

		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
			continue;

		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
			continue;

		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];

		if (p_pick_point && !col_obj->is_pickable())
			continue;

		int shape_idx=space->intersection_query_subindex_results[i];

		Shape2DSW * shape = col_obj->get_shape(shape_idx);

		Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point);

		if (!shape->contains_point(local_point))
			continue;

		if (cc>=p_result_max)
			continue;

		r_results[cc].collider_id=col_obj->get_instance_id();
		if (r_results[cc].collider_id!=0)
			r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id);
		r_results[cc].rid=col_obj->get_self();
		r_results[cc].shape=shape_idx;
		r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx);

		cc++;
	}

	return cc;


}
예제 #10
0
RID Physics2DServerSW::shape_create(ShapeType p_shape) {

	Shape2DSW *shape = NULL;
	switch (p_shape) {

		case SHAPE_LINE: {

			shape = memnew(LineShape2DSW);
		} break;
		case SHAPE_RAY: {

			shape = memnew(RayShape2DSW);
		} break;
		case SHAPE_SEGMENT: {

			shape = memnew(SegmentShape2DSW);
		} break;
		case SHAPE_CIRCLE: {

			shape = memnew(CircleShape2DSW);
		} break;
		case SHAPE_RECTANGLE: {

			shape = memnew(RectangleShape2DSW);
		} break;
		case SHAPE_CAPSULE: {

			shape = memnew(CapsuleShape2DSW);
		} break;
		case SHAPE_CONVEX_POLYGON: {

			shape = memnew(ConvexPolygonShape2DSW);
		} break;
		case SHAPE_CONCAVE_POLYGON: {

			shape = memnew(ConcavePolygonShape2DSW);
		} break;
		case SHAPE_CUSTOM: {

			ERR_FAIL_V(RID());

		} break;
	}

	RID id = shape_owner.make_rid(shape);
	shape->set_self(id);

	return id;
};
예제 #11
0
파일: space_2d_sw.cpp 프로젝트: Nr7/godot
int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_user_mask) {

	if (p_result_max<=0)
		return 0;

	Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,0);

	Rect2 aabb = p_xform.xform(shape->get_aabb());

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	bool collided=false;
	int cc=0;

	for(int i=0;i<amount;i++) {

		if (cc>=p_result_max)
			break;

		if (space->intersection_query_results[i]->get_type()==CollisionObject2DSW::TYPE_AREA)
			continue; //ignore area

		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
			continue;


		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];

		if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),NULL,NULL,NULL))
			continue;

		r_results[cc].collider_id=col_obj->get_instance_id();
		if (r_results[cc].collider_id!=0)
			r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id);
		r_results[cc].rid=col_obj->get_self();
		r_results[cc].shape=shape_idx;

		cc++;

	}

	return cc;

}
예제 #12
0
파일: space_2d_sw.cpp 프로젝트: Scrik/godot
int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {

	if (p_result_max<=0)
		return 0;

	Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,0);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb=aabb.grow(p_margin);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	bool collided=false;
	int cc=0;

	for(int i=0;i<amount;i++) {

		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
			continue;

		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
			continue;


		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];

		if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2(),NULL,NULL,NULL,p_margin))
			continue;

		r_results[cc].collider_id=col_obj->get_instance_id();
		if (r_results[cc].collider_id!=0)
			r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id);
		r_results[cc].rid=col_obj->get_self();
		r_results[cc].shape=shape_idx;
		r_results[cc].metadata=col_obj->get_shape_metadata(shape_idx);

		cc++;

	}

	return cc;

}
예제 #13
0
void Physics2DServerSW::free(RID p_rid) {

	if (shape_owner.owns(p_rid)) {

		Shape2DSW *shape = shape_owner.get(p_rid);

		while (shape->get_owners().size()) {
			ShapeOwner2DSW *so = shape->get_owners().front()->key();
			so->remove_shape(shape);
		}

		shape_owner.free(p_rid);
		memdelete(shape);
	} else if (body_owner.owns(p_rid)) {

		Body2DSW *body = body_owner.get(p_rid);

		/*
		if (body->get_state_query())
			_clear_query(body->get_state_query());

		if (body->get_direct_state_query())
			_clear_query(body->get_direct_state_query());
		*/

		body->set_space(NULL);

		while (body->get_shape_count()) {

			body->remove_shape(0);
		}

		while (body->get_constraint_map().size()) {
			RID self = body->get_constraint_map().front()->key()->get_self();
			ERR_FAIL_COND(!self.is_valid());
			free(self);
		}

		body_owner.free(p_rid);
		memdelete(body);

	} else if (area_owner.owns(p_rid)) {

		Area2DSW *area = area_owner.get(p_rid);

		/*
		if (area->get_monitor_query())
			_clear_query(area->get_monitor_query());
		*/

		area->set_space(NULL);

		while (area->get_shape_count()) {

			area->remove_shape(0);
		}

		area_owner.free(p_rid);
		memdelete(area);
	} else if (space_owner.owns(p_rid)) {

		Space2DSW *space = space_owner.get(p_rid);

		while (space->get_objects().size()) {
			CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get();
			co->set_space(NULL);
		}

		active_spaces.erase(space);
		free(space->get_default_area()->get_self());
		space_owner.free(p_rid);
		memdelete(space);
	} else if (joint_owner.owns(p_rid)) {

		Joint2DSW *joint = joint_owner.get(p_rid);

		joint_owner.free(p_rid);
		memdelete(joint);

	} else {

		ERR_EXPLAIN("Invalid ID");
		ERR_FAIL();
	}
};
예제 #14
0
bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) {

	Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape, false);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
	aabb = aabb.grow(p_margin);

	/*
	if (p_motion!=Vector2())
		print_line(p_motion);
	*/

	int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);

	real_t best_safe = 1;
	real_t best_unsafe = 1;

	for (int i = 0; i < amount; i++) {

		if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask))
			continue;

		if (p_exclude.has(space->intersection_query_results[i]->get_self()))
			continue; //ignore excluded

		const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
		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;
			}
		}*/

		Transform2D 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)) {
			continue;
		}

		//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)) {

			return false;
		}

		//just do kinematic solving
		real_t low = 0;
		real_t hi = 1;
		Vector2 mnormal = p_motion.normalized();

		for (int i = 0; i < 8; i++) { //steps should be customizable..

			real_t ofs = (low + hi) * 0.5;

			Vector2 sep = mnormal; //important optimization for this to work fast enough
			bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * ofs, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, &sep, p_margin);

			if (collided) {

				hi = ofs;
			} else {

				low = ofs;
			}
		}

		if (low < best_safe) {
			best_safe = low;
			best_unsafe = hi;
		}
	}

	p_closest_safe = best_safe;
	p_closest_unsafe = best_unsafe;

	return true;
}
예제 #15
0
파일: space_2d_sw.cpp 프로젝트: Nr7/godot
bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion, MotionCastCollision &r_result, const Set<RID>& p_exclude,uint32_t p_user_mask) {

	Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,0);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	bool collided=false;
	r_result.travel=1;

	MotionCallbackRayCastData best_normal;
	best_normal.best_len=1e20;
	for(int i=0;i<amount;i++) {


		if (space->intersection_query_results[i]->get_type()==CollisionObject2DSW::TYPE_AREA)
			continue; //ignore area

		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
			continue; //ignore excluded


		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];


		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)) {

			continue;
		}


		//test initial overlap
		if (CollisionSolver2DSW::solve(shape,p_xform,Vector2(),col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL)) {

			r_result.collider_id=col_obj->get_instance_id();
			r_result.collider=r_result.collider_id!=0 ? ObjectDB::get_instance(col_obj->get_instance_id()) : NULL;
			r_result.shape=shape_idx;
			r_result.rid=col_obj->get_self();
			r_result.travel=0;
			r_result.point=Vector2();
			r_result.normal=Vector2();
			return true;
		}

#if 0
		Vector2 mnormal=p_motion.normalized();
		Matrix32 col_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
		ShapeSW *col_shape = col_obj->get_shape(shape_idx);

		real_t min,max;
		col_shape->project_rangev(mnormal,col_shape_xform,min,max);
		real_t width = max-min;

		int a;
		Vector2 s[2];
		col_shape->get_supports(col_shape_xform.basis_xform(mnormal).normalized(),s,a);
		Vector2 from = col_shape_xform.xform(s[0]);
		Vector2 to = from + p_motion;

		Matrix32 from_inv = col_shape_xform.affine_inverse();

		Vector2 local_from = from_inv.xform(from-mnormal*width*0.1); //start from a little inside the bounding box
		Vector2 local_to = from_inv.xform(to);

		Vector2 rpos,rnorm;
		if (!col_shape->intersect_segment(local_from,local_to,rpos,rnorm))
			return false;

		//ray hit something


		Vector2 hitpos = p_xform_B.xform(rpos);
#endif

		//just do kinematic solving
		float low=0;
		float hi=1;
		Vector2 mnormal=p_motion.normalized();

		for(int i=0;i<8;i++) { //steps should be customizable..

			Matrix32 xfa = p_xform;
			float ofs = (low+hi)*0.5;

			Vector2 sep=mnormal; //important optimization for this to work fast enough
			bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep);

			if (collided) {

				hi=ofs;
			} else {

				low=ofs;
			}
		}


		best_normal.shape_B=col_obj->get_shape(shape_idx);
		best_normal.motion=p_motion*hi;
		best_normal.b_xform=col_obj_xform;
		best_normal.b_xform_inv=col_obj_xform.affine_inverse();

		bool sc = CollisionSolver2DSW::solve(shape,p_xform,p_motion*hi,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),Vector2() ,_motion_cbk_result,&best_normal);
		print_line("CLD: "+itos(sc));


		if (collided && low>=r_result.travel)
			continue;

		collided=true;
		r_result.travel=low;

		r_result.collider_id=col_obj->get_instance_id();
		r_result.collider=r_result.collider_id!=0 ? ObjectDB::get_instance(col_obj->get_instance_id()) : NULL;
		r_result.shape=shape_idx;
		r_result.rid=col_obj->get_self();

	}

	if (collided) {
		ERR_FAIL_COND_V(best_normal.best_normal==Vector2(),false);
		r_result.normal=best_normal.best_normal;
		r_result.point=best_normal.best_contact;
	}

	return collided;


}
예제 #16
0
bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {



    Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
    ERR_FAIL_COND_V(!shape,false);

    Rect2 aabb = p_xform.xform(shape->get_aabb());
    aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
    aabb=aabb.grow(p_margin);

    //if (p_motion!=Vector2())
    //	print_line(p_motion);

    int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

    float best_safe=1;
    float best_unsafe=1;

    for(int i=0; i<amount; i++) {


        if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
            continue;

        if (p_exclude.has( space->intersection_query_results[i]->get_self()))
            continue; //ignore excluded


        const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
        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)) {
            continue;
        }


        //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;
        }


        //just do kinematic solving
        float low=0;
        float hi=1;
        Vector2 mnormal=p_motion.normalized();

        for(int i=0; i<8; i++) { //steps should be customizable..

            Matrix32 xfa = p_xform;
            float ofs = (low+hi)*0.5;

            Vector2 sep=mnormal; //important optimization for this to work fast enough
            bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);

            if (collided) {

                hi=ofs;
            } else {

                low=ofs;
            }
        }

        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;
        }

    }

    p_closest_safe=best_safe;
    p_closest_unsafe=best_unsafe;

    return true;


}
예제 #17
0
파일: space_2d_sw.cpp 프로젝트: 9cat/godot
bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {



	Shape2DSW *shape = static_cast<Physics2DServerSW*>(Physics2DServer::get_singleton())->shape_owner.get(p_shape);
	ERR_FAIL_COND_V(!shape,false);

	Rect2 aabb = p_xform.xform(shape->get_aabb());
	aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
	aabb=aabb.grow(p_margin);

	//if (p_motion!=Vector2())
	//	print_line(p_motion);

	int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);

	float best_safe=1;
	float best_unsafe=1;

	for(int i=0;i<amount;i++) {


		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
			continue;

		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
			continue; //ignore excluded


		const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
		int shape_idx=space->intersection_query_subindex_results[i];


		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)) {
			continue;
		}


		//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)) {

			return false;
		}


		//just do kinematic solving
		float low=0;
		float hi=1;
		Vector2 mnormal=p_motion.normalized();

		for(int i=0;i<8;i++) { //steps should be customizable..

			Matrix32 xfa = p_xform;
			float ofs = (low+hi)*0.5;

			Vector2 sep=mnormal; //important optimization for this to work fast enough
			bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);

			if (collided) {

				hi=ofs;
			} else {

				low=ofs;
			}
		}

		if (low<best_safe) {
			best_safe=low;
			best_unsafe=hi;
		}

	}

	p_closest_safe=best_safe;
	p_closest_unsafe=best_unsafe;

	return true;


}