Esempio n. 1
0
void RayCast2D::_update_raycast_state() {
	Ref<World2D> w2d = get_world_2d();
	ERR_FAIL_COND( w2d.is_null() );

	Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space());
	ERR_FAIL_COND( !dss );

	Matrix32 gt = get_global_transform();

	Vector2 to = cast_to;
	if (to==Vector2())
		to=Vector2(0,0.01);

	Physics2DDirectSpaceState::RayResult rr;

	if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) {

		collided=true;
		against=rr.collider_id;
		collision_point=rr.position;
		collision_normal=rr.normal;
		against_shape=rr.shape;
	} else {
		collided=false;
	}
}
Esempio n. 2
0
static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {

	const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
	const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);


	SeparatorAxisTest2D<CapsuleShape2DSW,CapsuleShape2DSW,castA,castB,withMargin> separator(capsule_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	//capsule axis

	if (!separator.test_axis(p_transform_b.elements[0].normalized()))
		return;

	if (!separator.test_axis(p_transform_a.elements[0].normalized()))
		return;

	//capsule endpoints

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

		Vector2 capsule_endpoint_A = p_transform_a.get_origin()+p_transform_a.elements[1]*capsule_A->get_height()*(i==0?0.5:-0.5);

		for(int j=0;j<2;j++) {

			Vector2 capsule_endpoint_B = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(j==0?0.5:-0.5);

			if (TEST_POINT(capsule_endpoint_A,capsule_endpoint_B) )
				return;

		}
	}

	separator.generate_contacts();

}
Esempio n. 3
0
static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {

	const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
	const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);


	SeparatorAxisTest2D<CircleShape2DSW,CircleShape2DSW,castA,castB,withMargin> separator(circle_A,p_transform_a,circle_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	if (TEST_POINT(p_transform_a.get_origin(),p_transform_b.get_origin()))
		return;


	separator.generate_contacts();

}
Esempio n. 4
0
static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {

	const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
	const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);


	SeparatorAxisTest2D<CapsuleShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(capsule_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	//capsule axis

	if (!separator.test_axis(p_transform_a.elements[0].normalized()))
		return;


	//poly vs capsule
	for(int i=0;i<convex_B->get_point_count();i++) {

		Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));

		for(int j=0;j<2;j++) {

			Vector2 capsule_endpoint_A = p_transform_a.get_origin()+p_transform_a.elements[1]*capsule_A->get_height()*(j==0?0.5:-0.5);

			if (TEST_POINT(capsule_endpoint_A,cpoint ))
				return;

		}

		if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
			return;
	}

	separator.generate_contacts();
}
Esempio n. 5
0
bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {



	const RayShape2DSW *ray = static_cast<const RayShape2DSW*>(p_shape_A);
	if (p_shape_B->get_type()==Physics2DServer::SHAPE_RAY)
		return false;

	Vector2 from = p_transform_A.get_origin();
	Vector2 to = from+p_transform_A[1]*ray->get_length();
	Vector2 support_A=to;

	Matrix32 invb = p_transform_B.affine_inverse();
	from = invb.xform(from);
	to = invb.xform(to);

	Vector2 p,n;
	if (!p_shape_B->intersect_segment(from,to,p,n)) {

		if (sep_axis)
			*sep_axis=p_transform_A[1].normalized();
		return false;
	}


	Vector2 support_B=p_transform_B.xform(p);

	if (p_result_callback) {
		if (p_swap_result)
			p_result_callback(support_B,support_A,p_userdata);
		else
			p_result_callback(support_A,support_B,p_userdata);
	}
	return true;

}
Esempio n. 6
0
void RayCast2D::_notification(int p_what) {

	switch(p_what) {

		case NOTIFICATION_ENTER_TREE: {

			if (enabled && !get_tree()->is_editor_hint())
				set_fixed_process(true);
			else
				set_fixed_process(false);

		} break;
		case NOTIFICATION_EXIT_TREE: {

			if (enabled)
				set_fixed_process(false);

		} break;
#ifdef TOOLS_ENABLED
		case NOTIFICATION_DRAW: {

			if (!get_tree()->is_editor_hint())
				break;
			Matrix32 xf;
			xf.rotate(cast_to.atan2());
			xf.translate(Vector2(0,cast_to.length()));

			//Vector2 tip = Vector2(0,s->get_length());
			Color dcol(0.9,0.2,0.2,0.4);
			draw_line(Vector2(),cast_to,dcol,3);
			Vector<Vector2> pts;
			float tsize=4;
			pts.push_back(xf.xform(Vector2(0,tsize)));
			pts.push_back(xf.xform(Vector2(0.707*tsize,0)));
			pts.push_back(xf.xform(Vector2(-0.707*tsize,0)));
			Vector<Color> cols;
			for(int i=0;i<3;i++)
				cols.push_back(dcol);

			draw_primitive(pts,cols,Vector<Vector2>()); //small arrow

		} break;
#endif

		case NOTIFICATION_FIXED_PROCESS: {

			if (!enabled)
				break;



			Ref<World2D> w2d = get_world_2d();
			ERR_BREAK( w2d.is_null() );

			Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space());
			ERR_BREAK( !dss );

			Matrix32 gt = get_global_transform();

			Vector2 to = cast_to;
			if (to==Vector2())
				to=Vector2(0,0.01);

			Physics2DDirectSpaceState::RayResult rr;

			if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask)) {

				collided=true;
				against=rr.collider_id;
				collision_point=rr.position;
				collision_normal=rr.normal;
				against_shape=rr.shape;
			} else {
				collided=false;
			}



		} break;
	}
}
Esempio n. 7
0
void Body2DSW::update_inertias() {

	//update shapes and motions

	switch(mode) {

		case Physics2DServer::BODY_MODE_RIGID: {

			//update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
			float total_area=0;

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

				total_area+=get_shape_aabb(i).get_area();
			}

			real_t _inertia=0;

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

				const Shape2DSW* shape=get_shape(i);

				float area=get_shape_aabb(i).get_area();

				float mass = area * this->mass / total_area;

				Matrix32 mtx = get_shape_transform(i);
				Vector2 scale = mtx.get_scale();
				_inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared();
				//Rect2 ab = get_shape_aabb(i);
				//_inertia+=mass*ab.size.dot(ab.size)/12.0f;



			}

			if (_inertia!=0)
				_inv_inertia=1.0/_inertia;
			else
				_inv_inertia=0.0; //wathever

			if (mass)
				_inv_mass=1.0/mass;
			else
				_inv_mass=0;

		} break;
		case Physics2DServer::BODY_MODE_KINEMATIC:
		case Physics2DServer::BODY_MODE_STATIC: {

			_inv_inertia=0;
			_inv_mass=0;
		} break;
		case Physics2DServer::BODY_MODE_CHARACTER: {

			_inv_inertia=0;
			_inv_mass=1.0/mass;

		} break;
	}
	//_update_inertia_tensor();

	//_update_shapes();

}
Esempio n. 8
0
static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {

	const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
	const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);


	SeparatorAxisTest2D<RectangleShape2DSW,CapsuleShape2DSW,castA,castB,withMargin> separator(rectangle_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	//box faces
	if (!separator.test_axis(p_transform_a.elements[0].normalized()))
		return;

	if (!separator.test_axis(p_transform_a.elements[1].normalized()))
		return;

	//capsule axis
	if (!separator.test_axis(p_transform_b.elements[0].normalized()))
		return;


	//box endpoints to capsule circles

	Matrix32 boxinv = p_transform_a.affine_inverse();

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

		{
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);

			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a,boxinv,capsule_endpoint)))
				return;
		}


		if (castA) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint-=p_motion_a;

			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a,boxinv,capsule_endpoint)))
				return;
		}

		if (castB) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint+=p_motion_b;

			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a,boxinv,capsule_endpoint)))
				return;
		}

		if (castA && castB) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint-=p_motion_a;
			capsule_endpoint+=p_motion_b;


			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a,boxinv,capsule_endpoint)))
				return;
		}

	}


	separator.generate_contacts();
}
Esempio n. 9
0
static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {

	const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
	const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);


	SeparatorAxisTest2D<RectangleShape2DSW,CapsuleShape2DSW,castA,castB> separator(rectangle_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	//box faces
	if (!separator.test_axis(p_transform_a.elements[0].normalized()))
		return;

	if (!separator.test_axis(p_transform_a.elements[1].normalized()))
		return;

	//capsule axis
	if (!separator.test_axis(p_transform_b.elements[0].normalized()))
		return;


	//box endpoints to capsule circles

	Matrix32 boxinv = p_transform_a.affine_inverse();

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

		{
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);

			const Vector2& half_extents = rectangle_A->get_half_extents();
			Vector2 local_v = boxinv.xform(capsule_endpoint);

			Vector2 he(
				(local_v.x<0) ? -half_extents.x : half_extents.x,
				(local_v.y<0) ? -half_extents.y : half_extents.y
			);

			if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
				return;
		}


		if (castA) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint-=p_motion_a;


			const Vector2& half_extents = rectangle_A->get_half_extents();
			Vector2 local_v = boxinv.xform(capsule_endpoint);

			Vector2 he(
				(local_v.x<0) ? -half_extents.x : half_extents.x,
				(local_v.y<0) ? -half_extents.y : half_extents.y
			);

			if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
				return;
		}

		if (castB) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint+=p_motion_b;


			const Vector2& half_extents = rectangle_A->get_half_extents();
			Vector2 local_v = boxinv.xform(capsule_endpoint);

			Vector2 he(
				(local_v.x<0) ? -half_extents.x : half_extents.x,
				(local_v.y<0) ? -half_extents.y : half_extents.y
			);

			if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
				return;
		}

		if (castA && castB) {
			Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
			capsule_endpoint-=p_motion_a;
			capsule_endpoint+=p_motion_b;


			const Vector2& half_extents = rectangle_A->get_half_extents();
			Vector2 local_v = boxinv.xform(capsule_endpoint);

			Vector2 he(
				(local_v.x<0) ? -half_extents.x : half_extents.x,
				(local_v.y<0) ? -half_extents.y : half_extents.y
			);

			if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
				return;
		}

	}


	separator.generate_contacts();
}
Esempio n. 10
0
static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {

	const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
	const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);


	SeparatorAxisTest2D<CircleShape2DSW,RectangleShape2DSW,castA,castB> separator(circle_A,p_transform_a,rectangle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);

	if (!separator.test_previous_axis())
		return;

	if (!separator.test_cast())
		return;

	const Vector2 &sphere=p_transform_a.elements[2];
	const Vector2 *axis=&p_transform_b.elements[0];
	const Vector2& half_extents = rectangle_B->get_half_extents();

	if (!separator.test_axis(axis[0].normalized()))
		return;

	if (!separator.test_axis(axis[1].normalized()))
		return;

	{
		Vector2 local_v = p_transform_b.affine_inverse().xform(p_transform_a.get_origin());

		Vector2 he(
			(local_v.x<0) ? -half_extents.x : half_extents.x,
			(local_v.y<0) ? -half_extents.y : half_extents.y
		);


		if (!separator.test_axis((p_transform_b.xform(he)-sphere).normalized()))
			return;
	}

	if (castA) {

		Vector2 sphereofs = sphere + p_motion_a;
		Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);

		Vector2 he(
			(local_v.x<0) ? -half_extents.x : half_extents.x,
			(local_v.y<0) ? -half_extents.y : half_extents.y
		);


		if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
			return;
	}

	if (castB) {

		Vector2 sphereofs = sphere - p_motion_b;
		Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);

		Vector2 he(
			(local_v.x<0) ? -half_extents.x : half_extents.x,
			(local_v.y<0) ? -half_extents.y : half_extents.y
		);


		if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
			return;
	}

	if (castA && castB) {

		Vector2 sphereofs = sphere - p_motion_b + p_motion_a;
		Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);

		Vector2 he(
			(local_v.x<0) ? -half_extents.x : half_extents.x,
			(local_v.y<0) ? -half_extents.y : half_extents.y
		);


		if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
			return;
	}

	separator.generate_contacts();
}