Przeglądaj źródła

Merge pull request #101533 from kiroxas/improveCapsuleGizmo

Improve capsule gizmo performance
Thaddeus Crews 6 miesięcy temu
rodzic
commit
8b0bbe7f8d

+ 75 - 43
editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp

@@ -459,64 +459,96 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 		float radius = cs2->get_radius();
 		float radius = cs2->get_radius();
 		float height = cs2->get_height();
 		float height = cs2->get_height();
 
 
-		Vector<Vector3> points;
-
-		Vector3 d(0, height * 0.5 - radius, 0);
-		for (int i = 0; i < 360; i++) {
-			float ra = Math::deg_to_rad((float)i);
-			float rb = Math::deg_to_rad((float)i + 1);
-			Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
-			Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
+		// Number of points in an octant. So there will be 8 * points_in_octant points in total.
+		// This corresponds to the smoothness of the circle.
+		const uint32_t points_in_octant = 16;
+		const real_t octant_angle = Math_PI / 4;
+		const real_t inc = (Math_PI / (4 * points_in_octant));
+		const real_t radius_squared = radius * radius;
+		real_t r = 0;
 
 
-			points.push_back(Vector3(a.x, 0, a.y) + d);
-			points.push_back(Vector3(b.x, 0, b.y) + d);
+		Vector<Vector3> points;
+		// 4 vertical lines and 4 full circles.
+		points.resize(4 * 2 + 4 * 8 * points_in_octant * 2);
+		Vector3 *points_ptrw = points.ptrw();
 
 
-			points.push_back(Vector3(a.x, 0, a.y) - d);
-			points.push_back(Vector3(b.x, 0, b.y) - d);
+		uint32_t index = 0;
+		float y_value = height * 0.5 - radius;
 
 
-			if (i % 90 == 0) {
-				points.push_back(Vector3(a.x, 0, a.y) + d);
-				points.push_back(Vector3(a.x, 0, a.y) - d);
-			}
+		// Vertical Lines.
+		points_ptrw[index++] = Vector3(0.f, y_value, radius);
+		points_ptrw[index++] = Vector3(0.f, -y_value, radius);
+		points_ptrw[index++] = Vector3(0.f, y_value, -radius);
+		points_ptrw[index++] = Vector3(0.f, -y_value, -radius);
+		points_ptrw[index++] = Vector3(radius, y_value, 0.f);
+		points_ptrw[index++] = Vector3(radius, -y_value, 0.f);
+		points_ptrw[index++] = Vector3(-radius, y_value, 0.f);
+		points_ptrw[index++] = Vector3(-radius, -y_value, 0.f);
 
 
-			Vector3 dud = i < 180 ? d : -d;
+#define PUSH_QUARTER(from_x, from_y, to_x, to_y, y)      \
+	points_ptrw[index++] = Vector3(from_x, y, from_y);   \
+	points_ptrw[index++] = Vector3(to_x, y, to_y);       \
+	points_ptrw[index++] = Vector3(from_x, y, -from_y);  \
+	points_ptrw[index++] = Vector3(to_x, y, -to_y);      \
+	points_ptrw[index++] = Vector3(-from_x, y, from_y);  \
+	points_ptrw[index++] = Vector3(-to_x, y, to_y);      \
+	points_ptrw[index++] = Vector3(-from_x, y, -from_y); \
+	points_ptrw[index++] = Vector3(-to_x, y, -to_y);
 
 
-			points.push_back(Vector3(0, a.x, a.y) + dud);
-			points.push_back(Vector3(0, b.x, b.y) + dud);
-			points.push_back(Vector3(a.y, a.x, 0) + dud);
-			points.push_back(Vector3(b.y, b.x, 0) + dud);
-		}
+#define PUSH_QUARTER_XY(from_x, from_y, to_x, to_y, y)       \
+	points_ptrw[index++] = Vector3(from_x, -from_y - y, 0);  \
+	points_ptrw[index++] = Vector3(to_x, -to_y - y, 0);      \
+	points_ptrw[index++] = Vector3(from_x, from_y + y, 0);   \
+	points_ptrw[index++] = Vector3(to_x, to_y + y, 0);       \
+	points_ptrw[index++] = Vector3(-from_x, -from_y - y, 0); \
+	points_ptrw[index++] = Vector3(-to_x, -to_y - y, 0);     \
+	points_ptrw[index++] = Vector3(-from_x, from_y + y, 0);  \
+	points_ptrw[index++] = Vector3(-to_x, to_y + y, 0);
 
 
-		p_gizmo->add_lines(points, material, false, collision_color);
+#define PUSH_QUARTER_YZ(from_x, from_y, to_x, to_y, y)       \
+	points_ptrw[index++] = Vector3(0, -from_y - y, from_x);  \
+	points_ptrw[index++] = Vector3(0, -to_y - y, to_x);      \
+	points_ptrw[index++] = Vector3(0, from_y + y, from_x);   \
+	points_ptrw[index++] = Vector3(0, to_y + y, to_x);       \
+	points_ptrw[index++] = Vector3(0, -from_y - y, -from_x); \
+	points_ptrw[index++] = Vector3(0, -to_y - y, -to_x);     \
+	points_ptrw[index++] = Vector3(0, from_y + y, -from_x);  \
+	points_ptrw[index++] = Vector3(0, to_y + y, -to_x);
 
 
-		Vector<Vector3> collision_segments;
+		float previous_x = radius;
+		float previous_y = 0.f;
 
 
-		for (int i = 0; i < 64; i++) {
-			float ra = i * (Math_TAU / 64.0);
-			float rb = (i + 1) * (Math_TAU / 64.0);
-			Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
-			Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
+		for (uint32_t i = 0; i < points_in_octant; ++i) {
+			r += inc;
+			real_t x = Math::cos((i == points_in_octant - 1) ? octant_angle : r) * radius;
+			real_t y = Math::sqrt(radius_squared - (x * x));
 
 
-			collision_segments.push_back(Vector3(a.x, 0, a.y) + d);
-			collision_segments.push_back(Vector3(b.x, 0, b.y) + d);
+			// High circle ring.
+			PUSH_QUARTER(previous_x, previous_y, x, y, y_value);
+			PUSH_QUARTER(previous_y, previous_x, y, x, y_value);
 
 
-			collision_segments.push_back(Vector3(a.x, 0, a.y) - d);
-			collision_segments.push_back(Vector3(b.x, 0, b.y) - d);
+			// Low circle ring.
+			PUSH_QUARTER(previous_x, previous_y, x, y, -y_value);
+			PUSH_QUARTER(previous_y, previous_x, y, x, -y_value);
 
 
-			if (i % 16 == 0) {
-				collision_segments.push_back(Vector3(a.x, 0, a.y) + d);
-				collision_segments.push_back(Vector3(a.x, 0, a.y) - d);
-			}
+			// Up and Low circle in X-Y plane.
+			PUSH_QUARTER_XY(previous_x, previous_y, x, y, y_value);
+			PUSH_QUARTER_XY(previous_y, previous_x, y, x, y_value);
 
 
-			Vector3 dud = i < 32 ? d : -d;
+			// Up and Low circle in Y-Z plane.
+			PUSH_QUARTER_YZ(previous_x, previous_y, x, y, y_value);
+			PUSH_QUARTER_YZ(previous_y, previous_x, y, x, y_value)
 
 
-			collision_segments.push_back(Vector3(0, a.x, a.y) + dud);
-			collision_segments.push_back(Vector3(0, b.x, b.y) + dud);
-			collision_segments.push_back(Vector3(a.y, a.x, 0) + dud);
-			collision_segments.push_back(Vector3(b.y, b.x, 0) + dud);
+			previous_x = x;
+			previous_y = y;
 		}
 		}
 
 
-		p_gizmo->add_collision_segments(collision_segments);
+#undef PUSH_QUARTER
+#undef PUSH_QUARTER_XY
+#undef PUSH_QUARTER_YZ
+
+		p_gizmo->add_lines(points, material, false, collision_color);
+		p_gizmo->add_collision_segments(points);
 
 
 		Vector<Vector3> handles = {
 		Vector<Vector3> handles = {
 			Vector3(cs2->get_radius(), 0, 0),
 			Vector3(cs2->get_radius(), 0, 0),