Browse Source

Merge pull request #41634 from KoBeWi/the_independence

Rémi Verschelde 4 years ago
parent
commit
e30be92ce8

+ 1 - 1
doc/classes/CapsuleShape2D.xml

@@ -11,7 +11,7 @@
 	<methods>
 	<methods>
 	</methods>
 	</methods>
 	<members>
 	<members>
-		<member name="height" type="float" setter="set_height" getter="get_height" default="20.0">
+		<member name="height" type="float" setter="set_height" getter="get_height" default="30.0">
 			The capsule's height.
 			The capsule's height.
 		</member>
 		</member>
 		<member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0">
 		<member name="radius" type="float" setter="set_radius" getter="get_radius" default="10.0">

+ 3 - 3
editor/plugins/collision_shape_2d_editor_plugin.cpp

@@ -120,7 +120,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
 				if (idx == 0) {
 				if (idx == 0) {
 					capsule->set_radius(parameter);
 					capsule->set_radius(parameter);
 				} else if (idx == 1) {
 				} else if (idx == 1) {
-					capsule->set_height(parameter * 2 - capsule->get_radius() * 2);
+					capsule->set_height(parameter * 2);
 				}
 				}
 
 
 				canvas_item_editor->update_viewport();
 				canvas_item_editor->update_viewport();
@@ -440,8 +440,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
 			float radius = shape->get_radius();
 			float radius = shape->get_radius();
 			float height = shape->get_height() / 2;
 			float height = shape->get_height() / 2;
 
 
-			handles.write[0] = Point2(radius, height);
-			handles.write[1] = Point2(0, height + radius);
+			handles.write[0] = Point2(radius, 0);
+			handles.write[1] = Point2(0, height);
 
 
 			p_overlay->draw_texture(h, gt.xform(handles[0]) - size);
 			p_overlay->draw_texture(h, gt.xform(handles[0]) - size);
 			p_overlay->draw_texture(h, gt.xform(handles[1]) - size);
 			p_overlay->draw_texture(h, gt.xform(handles[1]) - size);

+ 10 - 11
scene/resources/capsule_shape_2d.cpp

@@ -38,11 +38,11 @@ Vector<Vector2> CapsuleShape2D::_get_points() const {
 	Vector<Vector2> points;
 	Vector<Vector2> points;
 	const real_t turn_step = Math_TAU / 24.0;
 	const real_t turn_step = Math_TAU / 24.0;
 	for (int i = 0; i < 24; i++) {
 	for (int i = 0; i < 24; i++) {
-		Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5);
+		Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -height * 0.5 + radius : height * 0.5 - radius);
 
 
-		points.push_back(Vector2(Math::sin(i * turn_step), Math::cos(i * turn_step)) * get_radius() + ofs);
+		points.push_back(Vector2(Math::sin(i * turn_step), Math::cos(i * turn_step)) * radius + ofs);
 		if (i == 6 || i == 18) {
 		if (i == 6 || i == 18) {
-			points.push_back(Vector2(Math::sin(i * turn_step), Math::cos(i * turn_step)) * get_radius() - ofs);
+			points.push_back(Vector2(Math::sin(i * turn_step), Math::cos(i * turn_step)) * radius - ofs);
 		}
 		}
 	}
 	}
 
 
@@ -60,6 +60,9 @@ void CapsuleShape2D::_update_shape() {
 
 
 void CapsuleShape2D::set_radius(real_t p_radius) {
 void CapsuleShape2D::set_radius(real_t p_radius) {
 	radius = p_radius;
 	radius = p_radius;
+	if (radius > height * 0.5) {
+		height = radius * 2;
+	}
 	_update_shape();
 	_update_shape();
 }
 }
 
 
@@ -69,8 +72,8 @@ real_t CapsuleShape2D::get_radius() const {
 
 
 void CapsuleShape2D::set_height(real_t p_height) {
 void CapsuleShape2D::set_height(real_t p_height) {
 	height = p_height;
 	height = p_height;
-	if (height < 0) {
-		height = 0;
+	if (radius > height * 0.5) {
+		height = radius * 2;
 	}
 	}
 
 
 	_update_shape();
 	_update_shape();
@@ -93,15 +96,11 @@ void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
 }
 }
 
 
 Rect2 CapsuleShape2D::get_rect() const {
 Rect2 CapsuleShape2D::get_rect() const {
-	Vector2 he = Point2(get_radius(), get_radius() + get_height() * 0.5);
-	Rect2 rect;
-	rect.position = -he;
-	rect.size = he * 2.0;
-	return rect;
+	return Rect2(0, 0, radius, height);
 }
 }
 
 
 real_t CapsuleShape2D::get_enclosing_radius() const {
 real_t CapsuleShape2D::get_enclosing_radius() const {
-	return radius + height * 0.5;
+	return height * 0.5;
 }
 }
 
 
 void CapsuleShape2D::_bind_methods() {
 void CapsuleShape2D::_bind_methods() {

+ 1 - 1
scene/resources/capsule_shape_2d.h

@@ -36,7 +36,7 @@
 class CapsuleShape2D : public Shape2D {
 class CapsuleShape2D : public Shape2D {
 	GDCLASS(CapsuleShape2D, Shape2D);
 	GDCLASS(CapsuleShape2D, Shape2D);
 
 
-	real_t height = 20.0;
+	real_t height = 30.0;
 	real_t radius = 10.0;
 	real_t radius = 10.0;
 
 
 	void _update_shape();
 	void _update_shape();

+ 30 - 13
servers/physics_2d/collision_solver_2d_sat.cpp

@@ -560,16 +560,18 @@ static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &
 		return;
 		return;
 	}
 	}
 
 
-	if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+	real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
+	if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
-	if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+	if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
-	if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+	if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
-	if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+	if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
 
 
@@ -715,11 +717,13 @@ static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p
 		return;
 		return;
 	}
 	}
 
 
+	real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
 	//capsule endpoints
 	//capsule endpoints
-	if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5))) {
+	if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
-	if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5))) {
+	if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() - p_transform_b.elements[1] * capsule_dir))) {
 		return;
 		return;
 	}
 	}
 
 
@@ -864,9 +868,11 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
 
 
 	Transform2D boxinv = p_transform_a.affine_inverse();
 	Transform2D boxinv = p_transform_a.affine_inverse();
 
 
+	real_t capsule_dir = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
+
 	for (int i = 0; i < 2; i++) {
 	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);
+			Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
 
 
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
 				return;
 				return;
@@ -874,7 +880,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
 		}
 		}
 
 
 		if (castA) {
 		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);
+			Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
 			capsule_endpoint -= p_motion_a;
 			capsule_endpoint -= p_motion_a;
 
 
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -883,7 +889,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
 		}
 		}
 
 
 		if (castB) {
 		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);
+			Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
 			capsule_endpoint += p_motion_b;
 			capsule_endpoint += p_motion_b;
 
 
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
 			if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint))) {
@@ -892,7 +898,7 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
 		}
 		}
 
 
 		if (castA && castB) {
 		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);
+			Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir;
 			capsule_endpoint -= p_motion_a;
 			capsule_endpoint -= p_motion_a;
 			capsule_endpoint += p_motion_b;
 			capsule_endpoint += p_motion_b;
 
 
@@ -900,6 +906,8 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
 				return;
 				return;
 			}
 			}
 		}
 		}
+
+		capsule_dir *= -1.0;
 	}
 	}
 
 
 	separator.generate_contacts();
 	separator.generate_contacts();
@@ -994,16 +1002,22 @@ static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &
 
 
 	//capsule endpoints
 	//capsule endpoints
 
 
+	real_t capsule_dir_A = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
 	for (int i = 0; i < 2; i++) {
 	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);
+		Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir_A;
 
 
+		real_t capsule_dir_B = capsule_B->get_height() * 0.5 - capsule_B->get_radius();
 		for (int j = 0; j < 2; j++) {
 		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);
+			Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_dir_B;
 
 
 			if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B)) {
 			if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B)) {
 				return;
 				return;
 			}
 			}
+
+			capsule_dir_B *= -1.0;
 		}
 		}
+
+		capsule_dir_A *= -1.0;
 	}
 	}
 
 
 	separator.generate_contacts();
 	separator.generate_contacts();
@@ -1034,12 +1048,15 @@ static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transf
 	for (int i = 0; i < convex_B->get_point_count(); i++) {
 	for (int i = 0; i < convex_B->get_point_count(); i++) {
 		Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));
 		Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));
 
 
+		real_t capsule_dir = capsule_A->get_height() * 0.5 - capsule_A->get_radius();
 		for (int j = 0; j < 2; j++) {
 		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);
+			Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_dir;
 
 
 			if (TEST_POINT(capsule_endpoint_A, cpoint)) {
 			if (TEST_POINT(capsule_endpoint_A, cpoint)) {
 				return;
 				return;
 			}
 			}
+
+			capsule_dir *= -1.0;
 		}
 		}
 
 
 		if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i))) {
 		if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i))) {

+ 9 - 9
servers/physics_2d/shape_2d_sw.cpp

@@ -343,15 +343,15 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
 
 
 		r_amount = 2;
 		r_amount = 2;
 		r_supports[0] = n;
 		r_supports[0] = n;
-		r_supports[0].y += height * 0.5;
+		r_supports[0].y += height * 0.5 - radius;
 		r_supports[1] = n;
 		r_supports[1] = n;
-		r_supports[1].y -= height * 0.5;
+		r_supports[1].y -= height * 0.5 - radius;
 
 
 	} else {
 	} else {
-		real_t h = (d > 0) ? height : -height;
+		real_t h = height * 0.5 - radius;
 
 
 		n *= radius;
 		n *= radius;
-		n.y += h * 0.5;
+		n.y += (d > 0) ? h : -h;
 		r_amount = 1;
 		r_amount = 1;
 		*r_supports = n;
 		*r_supports = n;
 	}
 	}
@@ -360,7 +360,7 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
 bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const {
 bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const {
 	Vector2 p = p_point;
 	Vector2 p = p_point;
 	p.y = Math::abs(p.y);
 	p.y = Math::abs(p.y);
-	p.y -= height * 0.5;
+	p.y -= height * 0.5 - radius;
 	if (p.y < 0) {
 	if (p.y < 0) {
 		p.y = 0;
 		p.y = 0;
 	}
 	}
@@ -377,7 +377,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
 	for (int i = 0; i < 2; i++) {
 	for (int i = 0; i < 2; i++) {
 		Vector2 begin = p_begin;
 		Vector2 begin = p_begin;
 		Vector2 end = p_end;
 		Vector2 end = p_end;
-		real_t ofs = (i == 0) ? -height * 0.5 : height * 0.5;
+		real_t ofs = (i == 0) ? -height * 0.5 + radius : height * 0.5 - radius;
 		begin.y += ofs;
 		begin.y += ofs;
 		end.y += ofs;
 		end.y += ofs;
 
 
@@ -414,7 +414,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
 	}
 	}
 
 
 	Vector2 rpos, rnorm;
 	Vector2 rpos, rnorm;
-	if (Rect2(Point2(-radius, -height * 0.5), Size2(radius * 2.0, height)).intersects_segment(p_begin, p_end, &rpos, &rnorm)) {
+	if (Rect2(Point2(-radius, -height * 0.5 + radius), Size2(radius * 2.0, height - radius * 2)).intersects_segment(p_begin, p_end, &rpos, &rnorm)) {
 		real_t pd = n.dot(rpos);
 		real_t pd = n.dot(rpos);
 		if (pd < d) {
 		if (pd < d) {
 			r_point = rpos;
 			r_point = rpos;
@@ -429,7 +429,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
 }
 }
 
 
 real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
 real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
-	Vector2 he2 = Vector2(radius * 2, height + radius * 2) * p_scale;
+	Vector2 he2 = Vector2(radius * 2, height) * p_scale;
 	return p_mass * he2.dot(he2) / 12.0;
 	return p_mass * he2.dot(he2) / 12.0;
 }
 }
 
 
@@ -447,7 +447,7 @@ void CapsuleShape2DSW::set_data(const Variant &p_data) {
 		height = p.y;
 		height = p.y;
 	}
 	}
 
 
-	Point2 he(radius, height * 0.5 + radius);
+	Point2 he(radius, height * 0.5);
 	configure(Rect2(-he, he * 2));
 	configure(Rect2(-he, he * 2));
 }
 }
 
 

+ 2 - 2
servers/physics_2d/shape_2d_sw.h

@@ -361,10 +361,10 @@ public:
 	_FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
 	_FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
 		// no matter the angle, the box is mirrored anyway
 		// no matter the angle, the box is mirrored anyway
 		Vector2 n = p_transform.basis_xform_inv(p_normal).normalized();
 		Vector2 n = p_transform.basis_xform_inv(p_normal).normalized();
-		real_t h = (n.y > 0) ? height : -height;
+		real_t h = height * 0.5 - radius;
 
 
 		n *= radius;
 		n *= radius;
-		n.y += h * 0.5;
+		n.y += (n.y > 0) ? h : -h;
 
 
 		r_max = p_normal.dot(p_transform.xform(n));
 		r_max = p_normal.dot(p_transform.xform(n));
 		r_min = p_normal.dot(p_transform.xform(-n));
 		r_min = p_normal.dot(p_transform.xform(-n));