Browse Source

Optimize mesh generation by preventing unneeded shape recalculations

Co-authored-by: Sequoia Haynes <[email protected]>
Carson Bates 9 months ago
parent
commit
c874e284eb
1 changed files with 169 additions and 0 deletions
  1. 169 0
      scene/resources/3d/primitive_meshes.cpp

+ 169 - 0
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<Material> &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();