diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp index db9a9bef04b..7324a26186b 100644 --- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp @@ -495,50 +495,63 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { float radius = cs2->get_radius(); float height = cs2->get_height(); +#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); + + // Number of points in an octant. So there will be 8 * points_in_octant * 2 points in total for one circle. + // This corresponds to the smoothness of the circle. + const uint32_t points_in_octant = 16; + const real_t inc = (Math_PI / (4 * points_in_octant)); + const real_t radius_squared = radius * radius; + real_t r = 0; + Vector points; + uint32_t index = 0; + // 4 vertical lines and 2 full circles. + points.resize(4 * 2 + 2 * 8 * points_in_octant * 2); + Vector3 *points_ptrw = points.ptrw(); + float y_value = height * 0.5; - Vector3 d(0, height * 0.5, 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; + // 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); - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(b.x, 0, b.y) + d); + float previous_x = radius; + float previous_y = 0.f; - points.push_back(Vector3(a.x, 0, a.y) - d); - points.push_back(Vector3(b.x, 0, b.y) - d); + for (uint32_t i = 0; i < points_in_octant; ++i) { + r += inc; + real_t x = Math::cos(r) * radius; + real_t y = Math::sqrt(radius_squared - (x * x)); - if (i % 90 == 0) { - points.push_back(Vector3(a.x, 0, a.y) + d); - points.push_back(Vector3(a.x, 0, a.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); + + // Low circle ring. + PUSH_QUARTER(previous_x, previous_y, x, y, -y_value); + PUSH_QUARTER(previous_y, previous_x, y, x, -y_value); + + previous_x = x; + previous_y = y; } +#undef PUSH_QUARTER p_gizmo->add_lines(points, material, false, collision_color); - - Vector collision_segments; - - 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; - - collision_segments.push_back(Vector3(a.x, 0, a.y) + d); - collision_segments.push_back(Vector3(b.x, 0, b.y) + d); - - collision_segments.push_back(Vector3(a.x, 0, a.y) - d); - collision_segments.push_back(Vector3(b.x, 0, b.y) - d); - - 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); - } - } - - p_gizmo->add_collision_segments(collision_segments); + p_gizmo->add_collision_segments(points); Vector handles = helper->cylinder_get_handles(cs2->get_height(), cs2->get_radius()); p_gizmo->add_handles(handles, handles_material);