From c874e284ebd0551f14d0ebed5ed2ecfce8ebf1fc Mon Sep 17 00:00:00 2001 From: Carson Bates Date: Tue, 19 Nov 2024 20:04:41 -0800 Subject: [PATCH] Optimize mesh generation by preventing unneeded shape recalculations Co-authored-by: Sequoia Haynes --- scene/resources/3d/primitive_meshes.cpp | 169 ++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/scene/resources/3d/primitive_meshes.cpp b/scene/resources/3d/primitive_meshes.cpp index ceeb73d0ef2..4d04ae77b1b 100644 --- a/scene/resources/3d/primitive_meshes.cpp +++ b/scene/resources/3d/primitive_meshes.cpp @@ -31,6 +31,7 @@ #include "primitive_meshes.h" #include "core/config/project_settings.h" +#include "core/math/math_funcs.h" #include "scene/resources/theme.h" #include "scene/theme/theme_db.h" #include "servers/rendering_server.h" @@ -261,6 +262,9 @@ void PrimitiveMesh::_bind_methods() { } void PrimitiveMesh::set_material(const Ref &p_material) { + if (p_material == material) { + return; + } material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. @@ -279,6 +283,9 @@ Array PrimitiveMesh::get_mesh_arrays() const { } void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { + if (p_custom.is_equal_approx(custom_aabb)) { + return; + } custom_aabb = p_custom; RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); @@ -289,6 +296,9 @@ AABB PrimitiveMesh::get_custom_aabb() const { } void PrimitiveMesh::set_flip_faces(bool p_enable) { + if (p_enable == flip_faces) { + return; + } flip_faces = p_enable; request_update(); } @@ -298,12 +308,18 @@ bool PrimitiveMesh::get_flip_faces() const { } void PrimitiveMesh::set_add_uv2(bool p_enable) { + if (p_enable == add_uv2) { + return; + } add_uv2 = p_enable; _update_lightmap_size(); request_update(); } void PrimitiveMesh::set_uv2_padding(float p_padding) { + if (Math::is_equal_approx(p_padding, uv2_padding)) { + return; + } uv2_padding = p_padding; _update_lightmap_size(); request_update(); @@ -578,6 +594,10 @@ void CapsuleMesh::_bind_methods() { } void CapsuleMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(radius, p_radius)) { + return; + } + radius = p_radius; if (radius > height * 0.5) { height = radius * 2.0; @@ -591,6 +611,10 @@ float CapsuleMesh::get_radius() const { } void CapsuleMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } + height = p_height; if (radius > height * 0.5) { radius = height * 0.5; @@ -604,6 +628,10 @@ float CapsuleMesh::get_height() const { } void CapsuleMesh::set_radial_segments(const int p_segments) { + if (radial_segments == p_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -613,6 +641,10 @@ int CapsuleMesh::get_radial_segments() const { } void CapsuleMesh::set_rings(const int p_rings) { + if (rings == p_rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -908,6 +940,10 @@ void BoxMesh::_bind_methods() { } void BoxMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } + size = p_size; _update_lightmap_size(); request_update(); @@ -918,6 +954,10 @@ Vector3 BoxMesh::get_size() const { } void BoxMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w) { + return; + } + subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -927,6 +967,10 @@ int BoxMesh::get_subdivide_width() const { } void BoxMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h) { + return; + } + subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -936,6 +980,10 @@ int BoxMesh::get_subdivide_height() const { } void BoxMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d) { + return; + } + subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1183,6 +1231,10 @@ void CylinderMesh::_bind_methods() { } void CylinderMesh::set_top_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, top_radius)) { + return; + } + top_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1193,6 +1245,10 @@ float CylinderMesh::get_top_radius() const { } void CylinderMesh::set_bottom_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, bottom_radius)) { + return; + } + bottom_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1203,6 +1259,10 @@ float CylinderMesh::get_bottom_radius() const { } void CylinderMesh::set_height(const float p_height) { + if (Math::is_equal_approx(p_height, height)) { + return; + } + height = p_height; _update_lightmap_size(); request_update(); @@ -1213,6 +1273,10 @@ float CylinderMesh::get_height() const { } void CylinderMesh::set_radial_segments(const int p_segments) { + if (p_segments == radial_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -1222,6 +1286,10 @@ int CylinderMesh::get_radial_segments() const { } void CylinderMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -1232,6 +1300,10 @@ int CylinderMesh::get_rings() const { } void CylinderMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } + cap_top = p_cap_top; request_update(); } @@ -1241,6 +1313,10 @@ bool CylinderMesh::is_cap_top() const { } void CylinderMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } + cap_bottom = p_cap_bottom; request_update(); } @@ -1375,6 +1451,9 @@ void PlaneMesh::_bind_methods() { } void PlaneMesh::set_size(const Size2 &p_size) { + if (p_size == size) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1385,6 +1464,9 @@ Size2 PlaneMesh::get_size() const { } void PlaneMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (subdivide_w == 0 && p_divisions < 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1394,6 +1476,9 @@ int PlaneMesh::get_subdivide_width() const { } void PlaneMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (subdivide_d == 0 && p_divisions < 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1403,6 +1488,9 @@ int PlaneMesh::get_subdivide_depth() const { } void PlaneMesh::set_center_offset(const Vector3 p_offset) { + if (p_offset.is_equal_approx(center_offset)) { + return; + } center_offset = p_offset; request_update(); } @@ -1412,6 +1500,9 @@ Vector3 PlaneMesh::get_center_offset() const { } void PlaneMesh::set_orientation(const Orientation p_orientation) { + if (p_orientation == orientation) { + return; + } orientation = p_orientation; request_update(); } @@ -1719,6 +1810,9 @@ void PrismMesh::_bind_methods() { } void PrismMesh::set_left_to_right(const float p_left_to_right) { + if (Math::is_equal_approx(p_left_to_right, left_to_right)) { + return; + } left_to_right = p_left_to_right; request_update(); } @@ -1728,6 +1822,9 @@ float PrismMesh::get_left_to_right() const { } void PrismMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1738,6 +1835,9 @@ Vector3 PrismMesh::get_size() const { } void PrismMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (p_divisions < 0 && subdivide_w == 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1747,6 +1847,9 @@ int PrismMesh::get_subdivide_width() const { } void PrismMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h || (p_divisions < 0 && subdivide_h == 0)) { + return; + } subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1756,6 +1859,9 @@ int PrismMesh::get_subdivide_height() const { } void PrismMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (p_divisions < 0 && subdivide_d == 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1902,6 +2008,9 @@ void SphereMesh::_bind_methods() { } void SphereMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; _update_lightmap_size(); request_update(); @@ -1912,6 +2021,9 @@ float SphereMesh::get_radius() const { } void SphereMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } height = p_height; _update_lightmap_size(); request_update(); @@ -1922,6 +2034,9 @@ float SphereMesh::get_height() const { } void SphereMesh::set_radial_segments(const int p_radial_segments) { + if (p_radial_segments == radial_segments || (radial_segments == 4 && p_radial_segments < 4)) { + return; + } radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; request_update(); } @@ -1931,6 +2046,9 @@ int SphereMesh::get_radial_segments() const { } void SphereMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 1); rings = p_rings; request_update(); @@ -1941,6 +2059,9 @@ int SphereMesh::get_rings() const { } void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { + if (p_is_hemisphere == is_hemisphere) { + return; + } is_hemisphere = p_is_hemisphere; _update_lightmap_size(); request_update(); @@ -2086,6 +2207,9 @@ void TorusMesh::_bind_methods() { } void TorusMesh::set_inner_radius(const float p_inner_radius) { + if (Math::is_equal_approx(p_inner_radius, inner_radius)) { + return; + } inner_radius = p_inner_radius; request_update(); } @@ -2095,6 +2219,9 @@ float TorusMesh::get_inner_radius() const { } void TorusMesh::set_outer_radius(const float p_outer_radius) { + if (Math::is_equal_approx(p_outer_radius, outer_radius)) { + return; + } outer_radius = p_outer_radius; request_update(); } @@ -2104,6 +2231,9 @@ float TorusMesh::get_outer_radius() const { } void TorusMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 3); rings = p_rings; request_update(); @@ -2114,6 +2244,9 @@ int TorusMesh::get_rings() const { } void TorusMesh::set_ring_segments(const int p_ring_segments) { + if (p_ring_segments == ring_segments) { + return; + } ERR_FAIL_COND(p_ring_segments < 3); ring_segments = p_ring_segments; request_update(); @@ -2143,6 +2276,9 @@ PointMesh::PointMesh() { // TUBE TRAIL void TubeTrailMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; request_update(); } @@ -2151,6 +2287,9 @@ float TubeTrailMesh::get_radius() const { } void TubeTrailMesh::set_radial_steps(const int p_radial_steps) { + if (p_radial_steps == radial_steps) { + return; + } ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128); radial_steps = p_radial_steps; request_update(); @@ -2160,6 +2299,9 @@ int TubeTrailMesh::get_radial_steps() const { } void TubeTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2169,6 +2311,9 @@ int TubeTrailMesh::get_sections() const { } void TubeTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2177,6 +2322,9 @@ float TubeTrailMesh::get_section_length() const { } void TubeTrailMesh::set_section_rings(const int p_section_rings) { + if (p_section_rings == section_rings) { + return; + } ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024); section_rings = p_section_rings; request_update(); @@ -2186,6 +2334,9 @@ int TubeTrailMesh::get_section_rings() const { } void TubeTrailMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } cap_top = p_cap_top; request_update(); } @@ -2195,6 +2346,9 @@ bool TubeTrailMesh::is_cap_top() const { } void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } cap_bottom = p_cap_bottom; request_update(); } @@ -2501,6 +2655,9 @@ TubeTrailMesh::TubeTrailMesh() { // RIBBON TRAIL void RibbonTrailMesh::set_shape(Shape p_shape) { + if (p_shape == shape) { + return; + } shape = p_shape; request_update(); } @@ -2509,6 +2666,9 @@ RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const { } void RibbonTrailMesh::set_size(const float p_size) { + if (Math::is_equal_approx(p_size, size)) { + return; + } size = p_size; request_update(); } @@ -2517,6 +2677,9 @@ float RibbonTrailMesh::get_size() const { } void RibbonTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2526,6 +2689,9 @@ int RibbonTrailMesh::get_sections() const { } void RibbonTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2534,6 +2700,9 @@ float RibbonTrailMesh::get_section_length() const { } void RibbonTrailMesh::set_section_segments(const int p_section_segments) { + if (p_section_segments == section_segments) { + return; + } ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024); section_segments = p_section_segments; request_update();