diff options
Diffstat (limited to 'modules/csg')
-rw-r--r-- | modules/csg/csg.cpp | 242 | ||||
-rw-r--r-- | modules/csg/csg.h | 4 | ||||
-rw-r--r-- | modules/csg/csg_gizmos.cpp | 54 | ||||
-rw-r--r-- | modules/csg/csg_gizmos.h | 1 | ||||
-rw-r--r-- | modules/csg/csg_shape.cpp | 223 | ||||
-rw-r--r-- | modules/csg/csg_shape.h | 5 | ||||
-rw-r--r-- | modules/csg/register_types.cpp | 1 |
7 files changed, 224 insertions, 306 deletions
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index a6951a9320..df798623f9 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -37,15 +37,14 @@ // Static helper functions. inline static bool is_snapable(const Vector3 &p_point1, const Vector3 &p_point2, real_t p_distance) { - return (p_point1 - p_point2).length_squared() < p_distance * p_distance; } inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2], const Vector2 p_uvs[2], const Vector2 &p_interpolation_point) { - float segment_length = (p_segement_points[1] - p_segement_points[0]).length(); - if (segment_length < CMP_EPSILON) + if (segment_length < CMP_EPSILON) { return p_uvs[0]; + } float distance = (p_interpolation_point - p_segement_points[0]).length(); float fraction = distance / segment_length; @@ -54,13 +53,15 @@ inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2], } inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const Vector2 p_uvs[3], const Vector2 &p_interpolation_point) { - - if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) + if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) { return p_uvs[0]; - if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) + } + if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) { return p_uvs[1]; - if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) + } + if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) { return p_uvs[2]; + } Vector2 edge1 = p_vertices[1] - p_vertices[0]; Vector2 edge2 = p_vertices[2] - p_vertices[0]; @@ -72,8 +73,9 @@ inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const float inter_on_edge1 = interpolation.dot(edge1); float inter_on_edge2 = interpolation.dot(edge2); float scale = (edge1_on_edge1 * edge2_on_edge2 - edge1_on_edge2 * edge1_on_edge2); - if (scale == 0) + if (scale == 0) { return p_uvs[0]; + } float v = (edge2_on_edge2 * inter_on_edge1 - edge1_on_edge2 * inter_on_edge2) / scale; float w = (edge1_on_edge1 * inter_on_edge2 - edge1_on_edge2 * inter_on_edge1) / scale; @@ -83,25 +85,27 @@ inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const } static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 p_vertices[3], float p_tolerance, Vector3 &r_intersection_point) { - Vector3 edge1 = p_vertices[1] - p_vertices[0]; Vector3 edge2 = p_vertices[2] - p_vertices[0]; Vector3 h = p_dir.cross(edge2); real_t a = edge1.dot(h); // Check if ray is parallel to triangle. - if (Math::is_zero_approx(a)) + if (Math::is_zero_approx(a)) { return false; + } real_t f = 1.0 / a; Vector3 s = p_from - p_vertices[0]; real_t u = f * s.dot(h); - if (u < 0.0 - p_tolerance || u > 1.0 + p_tolerance) + if (u < 0.0 - p_tolerance || u > 1.0 + p_tolerance) { return false; + } Vector3 q = s.cross(edge1); real_t v = f * p_dir.dot(q); - if (v < 0.0 - p_tolerance || u + v > 1.0 + p_tolerance) + if (v < 0.0 - p_tolerance || u + v > 1.0 + p_tolerance) { return false; + } // Ray intersects triangle. // Calculate distance. @@ -110,12 +114,12 @@ static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 if (t >= p_tolerance) { r_intersection_point = p_from + p_dir * t; return true; - } else + } else { return false; + } } inline bool is_point_in_triangle(const Vector3 &p_point, const Vector3 p_vertices[3], int p_shifted = 0) { - real_t det = p_vertices[0].dot(p_vertices[1].cross(p_vertices[2])); // If determinant is, zero try shift the triangle and the point. @@ -138,26 +142,28 @@ inline bool is_point_in_triangle(const Vector3 &p_point, const Vector3 p_vertice lambda[2] = p_vertices[0].cross(p_vertices[1]).dot(p_point) / det; // Point is in the plane if all lambdas sum to 1. - if (!Math::is_equal_approx(lambda[0] + lambda[1] + lambda[2], 1)) + if (!Math::is_equal_approx(lambda[0] + lambda[1] + lambda[2], 1)) { return false; + } // Point is inside the triangle if all lambdas are positive. - if (lambda[0] < 0 || lambda[1] < 0 || lambda[2] < 0) + if (lambda[0] < 0 || lambda[1] < 0 || lambda[2] < 0) { return false; + } return true; } inline static bool are_segements_parallel(const Vector2 p_segment1_points[2], const Vector2 p_segment2_points[2], float p_vertex_snap2) { - Vector2 segment1 = p_segment1_points[1] - p_segment1_points[0]; Vector2 segment2 = p_segment2_points[1] - p_segment2_points[0]; real_t segment1_length2 = segment1.dot(segment1); real_t segment2_length2 = segment2.dot(segment2); real_t segment_onto_segment = segment2.dot(segment1); - if (segment1_length2 < p_vertex_snap2 || segment2_length2 < p_vertex_snap2) + if (segment1_length2 < p_vertex_snap2 || segment2_length2 < p_vertex_snap2) { return true; + } real_t max_separation2; if (segment1_length2 > segment2_length2) { @@ -172,7 +178,6 @@ inline static bool are_segements_parallel(const Vector2 p_segment1_points[2], co // CSGBrush void CSGBrush::_regen_face_aabbs() { - for (int i = 0; i < faces.size(); i++) { faces.write[i].aabb = AABB(); faces.write[i].aabb.position = faces[i].vertices[0]; @@ -182,7 +187,6 @@ void CSGBrush::_regen_face_aabbs() { } void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_invert_faces) { - faces.clear(); int vc = p_vertices.size(); @@ -204,7 +208,6 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< faces.resize(p_vertices.size() / 3); for (int i = 0; i < faces.size(); i++) { - Face &f = faces.write[i]; f.vertices[0] = rv[i * 3 + 0]; f.vertices[1] = rv[i * 3 + 1]; @@ -216,21 +219,21 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< f.uvs[2] = ruv[i * 3 + 2]; } - if (sc == vc / 3) + if (sc == vc / 3) { f.smooth = rs[i]; - else + } else { f.smooth = false; + } - if (ic == vc / 3) + if (ic == vc / 3) { f.invert = ri[i]; - else + } else { f.invert = false; + } if (mc == vc / 3) { - Ref<Material> mat = rm[i]; if (mat.is_valid()) { - const Map<Ref<Material>, int>::Element *E = material_map.find(mat); if (E) { @@ -255,7 +258,6 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< } void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform &p_xform) { - faces = p_brush.faces; materials = p_brush.materials; @@ -271,7 +273,6 @@ void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform &p_xform) { // CSGBrushOperation void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_brush_a, const CSGBrush &p_brush_b, CSGBrush &r_merged_brush, float p_vertex_snap) { - // Check for face collisions and add necessary faces. Build2DFaceCollection build2DFaceCollection; for (int i = 0; i < p_brush_a.faces.size(); i++) { @@ -287,7 +288,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b mesh_merge.vertex_snap = p_vertex_snap; for (int i = 0; i < p_brush_a.faces.size(); i++) { - Ref<Material> material; if (p_brush_a.faces[i].material != -1) { material = p_brush_a.materials[p_brush_a.faces[i].material]; @@ -307,7 +307,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } for (int i = 0; i < p_brush_b.faces.size(); i++) { - Ref<Material> material; if (p_brush_b.faces[i].material != -1) { material = p_brush_b.materials[p_brush_b.faces[i].material]; @@ -333,14 +332,13 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b r_merged_brush.faces.clear(); switch (p_operation) { - case OPERATION_UNION: { - int outside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].inside) { continue; + } outside_count++; } @@ -349,9 +347,9 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b outside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[outside_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -369,12 +367,12 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } break; case OPERATION_INTERSECTION: { - int inside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (!mesh_merge.faces[i].inside) + if (!mesh_merge.faces[i].inside) { continue; + } inside_count++; } @@ -383,9 +381,9 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b inside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (!mesh_merge.faces[i].inside) + if (!mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[inside_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -403,14 +401,15 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } break; case OPERATION_SUBSTRACTION: { - int face_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) { continue; - if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) + } + if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) { continue; + } face_count++; } @@ -419,11 +418,12 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b face_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) { continue; - if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) + } + if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[face_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -460,7 +460,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b #define BVH_LIMIT 8 int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) { - if (p_depth > r_max_depth) { r_max_depth = p_depth; } @@ -485,7 +484,6 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac int li = aabb.get_longest_axis_index(); switch (li) { - case Vector3::AXIS_X: { SortArray<FaceBVH *, FaceBVHCmpX> sort_x; sort_x.nth_element(0, p_size, p_size / 2, &facebvhptrptr[p_from]); @@ -521,19 +519,19 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac } void CSGBrushOperation::MeshMerge::_add_distance(List<real_t> &r_intersectionsA, List<real_t> &r_intersectionsB, bool p_from_B, real_t p_distance) const { - List<real_t> &intersections = p_from_B ? r_intersectionsB : r_intersectionsA; // Check if distance exists. - for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) - if (Math::abs(**E - p_distance) < vertex_snap) + for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) { + if (Math::abs(**E - p_distance) < vertex_snap) { return; + } + } intersections.push_back(p_distance); } bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const { - Face face = faces[p_face_idx]; Vector3 face_points[3] = { points[face.points[0]], @@ -563,22 +561,16 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const FaceBVH *current_facebvhptr = &(facebvhptr[node]); bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { - case TEST_AABB_BIT: { - if (current_facebvhptr->face >= 0) { - while (current_facebvhptr) { - if (p_face_idx != current_facebvhptr->face && current_facebvhptr->aabb.intersects_ray(face_center, face_normal)) { - const Face ¤t_face = faces[current_facebvhptr->face]; Vector3 current_points[3] = { points[current_face.points[0]], @@ -592,8 +584,9 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de if ((current_normal - face_normal).length_squared() < CMP_EPSILON2 && is_point_in_triangle(face_center, current_points)) { // Only add an intersection if checking a B face. - if (face.from_b) + if (face.from_b) { _add_distance(intersectionsA, intersectionsB, current_face.from_b, 0); + } } else if (ray_intersects_triangle(face_center, face_normal, current_points, CMP_EPSILON, intersection_point)) { real_t distance = (intersection_point - face_center).length(); _add_distance(intersectionsA, intersectionsB, current_face.from_b, distance); @@ -610,7 +603,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - bool valid = current_facebvhptr->aabb.intersects_ray(face_center, face_normal); if (!valid) { @@ -623,7 +615,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = current_facebvhptr->left | TEST_AABB_BIT; level++; @@ -631,7 +622,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = current_facebvhptr->right | TEST_AABB_BIT; level++; @@ -639,18 +629,19 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } // Inside if face normal intersects other faces an odd number of times. @@ -658,7 +649,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } void CSGBrushOperation::MeshMerge::mark_inside_faces() { - // Mark faces that are inside. This helps later do the boolean ops when merging. // This approach is very brute force with a bunch of optimizations, // such as BVH and pre AABB intersection test. @@ -704,8 +694,9 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() { AABB intersection_aabb = aabb_a.intersection(aabb_b); // Check if shape AABBs intersect. - if (intersection_aabb.size == Vector3()) + if (intersection_aabb.size == Vector3()) { return; + } Vector<FaceBVH *> bvhtrvec; bvhtrvec.resize(faces.size()); @@ -719,21 +710,20 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() { _create_bvh(facebvh, bvhptr, 0, faces.size(), 1, max_depth, max_alloc); for (int i = 0; i < faces.size(); i++) { - // Check if face AABB intersects the intersection AABB. - if (!intersection_aabb.intersects_inclusive(facebvh[i].aabb)) + if (!intersection_aabb.intersects_inclusive(facebvh[i].aabb)) { continue; + } - if (_bvh_inside(facebvh, max_depth, max_alloc - 1, i)) + if (_bvh_inside(facebvh, max_depth, max_alloc - 1, i)) { faces.write[i].inside = true; + } } } void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vector2 p_uvs[], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { - int indices[3]; for (int i = 0; i < 3; i++) { - VertexKey vk; vk.x = int((double(p_points[i].x) + double(vertex_snap) * 0.31234) / double(vertex_snap)); vk.y = int((double(p_points[i].y) + double(vertex_snap) * 0.31234) / double(vertex_snap)); @@ -750,8 +740,9 @@ void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vect } // Don't add degenerate faces. - if (indices[0] == indices[2] || indices[0] == indices[1] || indices[1] == indices[2]) + if (indices[0] == indices[2] || indices[0] == indices[1] || indices[1] == indices[2]) { return; + } MeshMerge::Face face; face.from_b = p_from_b; @@ -781,27 +772,26 @@ void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vect // CSGBrushOperation::Build2DFaces int CSGBrushOperation::Build2DFaces::_get_point_idx(const Vector2 &p_point) { - for (int vertex_idx = 0; vertex_idx < vertices.size(); ++vertex_idx) { - if ((p_point - vertices[vertex_idx].point).length_squared() < vertex_snap2) + if ((p_point - vertices[vertex_idx].point).length_squared() < vertex_snap2) { return vertex_idx; + } } return -1; } int CSGBrushOperation::Build2DFaces::_add_vertex(const Vertex2D &p_vertex) { - // Check if vertex exists. int vertex_id = _get_point_idx(p_vertex.point); - if (vertex_id != -1) + if (vertex_id != -1) { return vertex_id; + } vertices.push_back(p_vertex); return vertices.size() - 1; } void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vertex_indices, int p_new_vertex_index) { - if (p_new_vertex_index >= 0 && r_vertex_indices.find(p_new_vertex_index) == -1) { ERR_FAIL_COND_MSG(p_new_vertex_index >= vertices.size(), "Invalid vertex index."); @@ -814,20 +804,21 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert // The second vertex. if (r_vertex_indices.size() == 1) { - Vector2 first_point = vertices[r_vertex_indices[0]].point; Vector2 new_point = vertices[p_new_vertex_index].point; // Sort along the axis with the greatest difference. int axis = 0; - if (Math::abs(new_point.x - first_point.x) < Math::abs(new_point.y - first_point.y)) + if (Math::abs(new_point.x - first_point.x) < Math::abs(new_point.y - first_point.y)) { axis = 1; + } // Add it to the beginning or the end appropriately. - if (new_point[axis] < first_point[axis]) + if (new_point[axis] < first_point[axis]) { r_vertex_indices.insert(0, p_new_vertex_index); - else + } else { r_vertex_indices.push_back(p_new_vertex_index); + } return; } @@ -839,8 +830,9 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert // Determine axis being sorted against i.e. the axis with the greatest difference. int axis = 0; - if (Math::abs(last_point.x - first_point.x) < Math::abs(last_point.y - first_point.y)) + if (Math::abs(last_point.x - first_point.x) < Math::abs(last_point.y - first_point.y)) { axis = 1; + } // Insert the point at the appropriate index. for (int insert_idx = 0; insert_idx < r_vertex_indices.size(); ++insert_idx) { @@ -857,14 +849,13 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert } void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_indices) { - int segments = p_segment_indices.size() - 1; - if (segments < 2) + if (segments < 2) { return; + } // Faces around an inner vertex are merged by moving the inner vertex to the first vertex. for (int sorted_idx = 1; sorted_idx < segments; ++sorted_idx) { - int closest_idx = 0; int inner_idx = p_segment_indices[sorted_idx]; @@ -893,15 +884,15 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ // Create the new faces. for (int merge_idx = 0; merge_idx < merge_faces.size(); ++merge_idx) { - int outer_edge_idx[2]; outer_edge_idx[0] = merge_faces[merge_idx].vertex_idx[(merge_faces_inner_vertex_idx[merge_idx] + 1) % 3]; outer_edge_idx[1] = merge_faces[merge_idx].vertex_idx[(merge_faces_inner_vertex_idx[merge_idx] + 2) % 3]; // Skip flattened faces. if (outer_edge_idx[0] == p_segment_indices[closest_idx] || - outer_edge_idx[1] == p_segment_indices[closest_idx]) + outer_edge_idx[1] == p_segment_indices[closest_idx]) { continue; + } //Don't create degenerate triangles. Vector2 edge1[2] = { @@ -929,15 +920,16 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ // Delete the old faces in reverse index order. merge_faces_idx.sort(); merge_faces_idx.invert(); - for (int i = 0; i < merge_faces_idx.size(); ++i) + for (int i = 0; i < merge_faces_idx.size(); ++i) { faces.remove(merge_faces_idx[i]); + } - if (degenerate_points.size() == 0) + if (degenerate_points.size() == 0) { continue; + } // Split faces using degenerate points. for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -951,7 +943,6 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ }; for (int point_idx = 0; point_idx < degenerate_points.size(); ++point_idx) { - int degenerate_idx = degenerate_points[point_idx]; Vector2 point_2D = vertices[degenerate_idx].point; @@ -963,12 +954,12 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ break; } } - if (existing) + if (existing) { continue; + } // Check if point is on an each edge. for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { face_points[face_edge_idx], face_points[(face_edge_idx + 1) % 3] @@ -976,7 +967,6 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(point_2D, edge_points); if ((closest_point - point_2D).length_squared() < vertex_snap2) { - int opposite_vertex_idx = face.vertex_idx[(face_edge_idx + 2) % 3]; // If new vertex snaps to degenerate vertex, just delete this face. @@ -1014,10 +1004,8 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ } void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_segment_points[2], Vector<int> &r_segment_indices) { - // For each face. for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -1027,7 +1015,6 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // Check each edge. for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { face_vertices[face_edge_idx].point, face_vertices[(face_edge_idx + 1) % 3].point @@ -1050,15 +1037,16 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // Else check if the segment intersects the edge. if (on_edge || Geometry::segment_intersects_segment_2d(p_segment_points[0], p_segment_points[1], edge_points[0], edge_points[1], &intersection_point)) { - // Check if intersection point is an edge point. if ((intersection_point - edge_points[0]).length_squared() < vertex_snap2 || - (intersection_point - edge_points[1]).length_squared() < vertex_snap2) + (intersection_point - edge_points[1]).length_squared() < vertex_snap2) { continue; + } // Check if edge exists, by checking if the intersecting segment is parallel to the edge. - if (are_segements_parallel(p_segment_points, edge_points, vertex_snap2)) + if (are_segements_parallel(p_segment_points, edge_points, vertex_snap2)) { continue; + } // Add the intersection point as a new vertex. Vertex2D new_vertex; @@ -1087,8 +1075,9 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // If opposite point is on the segemnt, add its index to segment indices too. Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(vertices[opposite_vertex_idx].point, p_segment_points); - if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) + if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) { _add_vertex_idx_sorted(r_segment_indices, opposite_vertex_idx); + } // Create two new faces around the new edge and remove this face. // The new edge is the last edge. @@ -1113,11 +1102,9 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s } int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { - int new_vertex_idx = -1; for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -1137,14 +1124,14 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // Check if point is existing face vertex. for (int i = 0; i < 3; ++i) { - if ((p_point - face_vertices[i].point).length_squared() < vertex_snap2) + if ((p_point - face_vertices[i].point).length_squared() < vertex_snap2) { return face.vertex_idx[i]; + } } // Check if point is on an each edge. bool on_edge = false; for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { points[face_edge_idx], points[(face_edge_idx + 1) % 3] @@ -1206,7 +1193,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // If not on an edge, check if the point is inside the face. if (!on_edge && Geometry::is_point_in_triangle(p_point, face_vertices[0].point, face_vertices[1].point, face_vertices[2].point)) { - // Add the point as a new vertex. Vertex2D new_vertex; new_vertex.point = p_point; @@ -1216,7 +1202,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // Create three new faces around this point and remove this face. // The new vertex is the last vertex. for (int i = 0; i < 3; ++i) { - // Don't create degenerate triangles. Vector2 edge[2] = { points[i], points[(i + 1) % 3] }; Vector2 new_edge1[2] = { vertices[new_vertex_idx].point, points[i] }; @@ -1243,7 +1228,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { } void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face_idx) { - // Find edge points that cross the plane and face points that are in the plane. // Map those points to 2D. // Create new faces from those points. @@ -1252,7 +1236,6 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face int points_count = 0; for (int i = 0; i < 3; i++) { - Vector3 point_3D = p_brush.faces[p_face_idx].vertices[i]; if (plane.has_point(point_3D)) { @@ -1262,13 +1245,14 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face points_2D[points_count++] = Vector2(point_2D.x, point_2D.y); } else { - Vector3 next_point_3D = p_brush.faces[p_face_idx].vertices[(i + 1) % 3]; - if (plane.has_point(next_point_3D)) + if (plane.has_point(next_point_3D)) { continue; // Next point is in plane, it will be added separately. - if (plane.is_point_over(point_3D) == plane.is_point_over(next_point_3D)) + } + if (plane.is_point_over(point_3D) == plane.is_point_over(next_point_3D)) { continue; // Both points on the same side of the plane, ignore. + } // Edge crosses the plane, find and add the intersection point. Vector3 point_2D; @@ -1315,7 +1299,6 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face } void CSGBrushOperation::Build2DFaces::addFacesToMesh(MeshMerge &r_mesh_merge, bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { - for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { Face2D face = faces[face_idx]; Vertex2D fv[3] = { @@ -1339,7 +1322,6 @@ void CSGBrushOperation::Build2DFaces::addFacesToMesh(MeshMerge &r_mesh_merge, bo CSGBrushOperation::Build2DFaces::Build2DFaces(const CSGBrush &p_brush, int p_face_idx, float p_vertex_snap2) : vertex_snap2(p_vertex_snap2 * p_vertex_snap2) { - // Convert 3D vertex points to 2D. Vector3 points_3D[3] = { p_brush.faces[p_face_idx].vertices[0], @@ -1368,7 +1350,6 @@ CSGBrushOperation::Build2DFaces::Build2DFaces(const CSGBrush &p_brush, int p_fac } void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face_idx_a, const CSGBrush &p_brush_b, const int p_face_idx_b, Build2DFaceCollection &p_collection, float p_vertex_snap) { - Vector3 vertices_a[3] = { p_brush_a.faces[p_face_idx_a].vertices[0], p_brush_a.faces[p_face_idx_a].vertices[1], @@ -1396,8 +1377,9 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face p_collection.build2DFacesB[p_face_idx_b] = Build2DFaces(); has_degenerate = true; } - if (has_degenerate) + if (has_degenerate) { return; + } // Ensure B has points either side of or in the plane of A. int in_plane_count = 0, over_count = 0, under_count = 0; @@ -1405,16 +1387,18 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face ERR_FAIL_COND_MSG(plane_a.normal == Vector3(), "Couldn't form plane from Brush A face."); for (int i = 0; i < 3; i++) { - if (plane_a.has_point(vertices_b[i])) + if (plane_a.has_point(vertices_b[i])) { in_plane_count++; - else if (plane_a.is_point_over(vertices_b[i])) + } else if (plane_a.is_point_over(vertices_b[i])) { over_count++; - else + } else { under_count++; + } } // If all points under or over the plane, there is no intesection. - if (over_count == 3 || under_count == 3) + if (over_count == 3 || under_count == 3) { return; + } // Ensure A has points either side of or in the plane of B. in_plane_count = 0; @@ -1424,32 +1408,32 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face ERR_FAIL_COND_MSG(plane_b.normal == Vector3(), "Couldn't form plane from Brush B face."); for (int i = 0; i < 3; i++) { - if (plane_b.has_point(vertices_a[i])) + if (plane_b.has_point(vertices_a[i])) { in_plane_count++; - else if (plane_b.is_point_over(vertices_a[i])) + } else if (plane_b.is_point_over(vertices_a[i])) { over_count++; - else + } else { under_count++; + } } // If all points under or over the plane, there is no intesection. - if (over_count == 3 || under_count == 3) + if (over_count == 3 || under_count == 3) { return; + } // Check for intersection using the SAT theorem. { - // Edge pair cross product combinations. for (int i = 0; i < 3; i++) { - Vector3 axis_a = (vertices_a[i] - vertices_a[(i + 1) % 3]).normalized(); for (int j = 0; j < 3; j++) { - Vector3 axis_b = (vertices_b[j] - vertices_b[(j + 1) % 3]).normalized(); Vector3 sep_axis = axis_a.cross(axis_b); - if (sep_axis == Vector3()) + if (sep_axis == Vector3()) { continue; //colineal + } sep_axis.normalize(); real_t min_a = 1e20, max_a = -1e20; diff --git a/modules/csg/csg.h b/modules/csg/csg.h index d389cbc283..34ee239c17 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -44,7 +44,6 @@ #include "scene/resources/material.h" struct CSGBrush { - struct Face { Vector3 vertices[3]; Vector2 uvs[3]; @@ -65,7 +64,6 @@ struct CSGBrush { }; struct CSGBrushOperation { - enum Operation { OPERATION_UNION, OPERATION_INTERSECTION, @@ -75,7 +73,6 @@ struct CSGBrushOperation { void merge_brushes(Operation p_operation, const CSGBrush &p_brush_a, const CSGBrush &p_brush_b, CSGBrush &r_merged_brush, float p_vertex_snap); struct MeshMerge { - struct Face { bool from_b; bool inside; @@ -156,7 +153,6 @@ struct CSGBrushOperation { }; struct Build2DFaces { - struct Vertex2D { Vector2 point; Vector2 uv; diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index a859ef80a6..9fa7dc1340 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -33,7 +33,6 @@ /////////// CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { - Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15)); create_material("shape_union_material", gizmo_color); create_material("shape_union_solid_material", gizmo_color); @@ -50,44 +49,37 @@ CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { } String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { - CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); if (Object::cast_to<CSGSphere3D>(cs)) { - return "Radius"; } if (Object::cast_to<CSGBox3D>(cs)) { - static const char *hname[3] = { "Width", "Height", "Depth" }; return hname[p_idx]; } if (Object::cast_to<CSGCylinder3D>(cs)) { - return p_idx == 0 ? "Radius" : "Height"; } if (Object::cast_to<CSGTorus3D>(cs)) { - return p_idx == 0 ? "InnerRadius" : "OuterRadius"; } return ""; } -Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { +Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); if (Object::cast_to<CSGSphere3D>(cs)) { - CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); return s->get_radius(); } if (Object::cast_to<CSGBox3D>(cs)) { - CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); switch (p_idx) { case 0: @@ -100,21 +92,19 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int } if (Object::cast_to<CSGCylinder3D>(cs)) { - CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); return p_idx == 0 ? s->get_radius() : s->get_height(); } if (Object::cast_to<CSGTorus3D>(cs)) { - CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); return p_idx == 0 ? s->get_inner_radius() : s->get_outer_radius(); } return Variant(); } -void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { +void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); Transform gt = cs->get_global_transform(); @@ -127,7 +117,6 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; if (Object::cast_to<CSGSphere3D>(cs)) { - CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); Vector3 ra, rb; @@ -137,14 +126,14 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } s->set_radius(d); } if (Object::cast_to<CSGBox3D>(cs)) { - CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); Vector3 axis; @@ -156,8 +145,9 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } switch (p_idx) { case 0: @@ -173,7 +163,6 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca } if (Object::cast_to<CSGCylinder3D>(cs)) { - CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); Vector3 axis; @@ -185,17 +174,18 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } - if (p_idx == 0) + if (p_idx == 0) { s->set_radius(d); - else if (p_idx == 1) + } else if (p_idx == 1) { s->set_height(d * 2.0); + } } if (Object::cast_to<CSGTorus3D>(cs)) { - CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); Vector3 axis; @@ -207,17 +197,19 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } - if (p_idx == 0) + if (p_idx == 0) { s->set_inner_radius(d); - else if (p_idx == 1) + } else if (p_idx == 1) { s->set_outer_radius(d); + } } } -void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); if (Object::cast_to<CSGSphere3D>(cs)) { @@ -275,10 +267,11 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, if (Object::cast_to<CSGCylinder3D>(cs)) { CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); if (p_cancel) { - if (p_idx == 0) + if (p_idx == 0) { s->set_radius(p_restore); - else + } else { s->set_height(p_restore); + } return; } @@ -299,10 +292,11 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, if (Object::cast_to<CSGTorus3D>(cs)) { CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); if (p_cancel) { - if (p_idx == 0) + if (p_idx == 0) { s->set_inner_radius(p_restore); - else + } else { s->set_outer_radius(p_restore); + } return; } @@ -320,6 +314,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, ur->commit_action(); } } + bool CSGShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to<CSGSphere3D>(p_spatial) || Object::cast_to<CSGBox3D>(p_spatial) || Object::cast_to<CSGCylinder3D>(p_spatial) || Object::cast_to<CSGTorus3D>(p_spatial) || Object::cast_to<CSGMesh3D>(p_spatial) || Object::cast_to<CSGPolygon3D>(p_spatial); } @@ -337,7 +332,6 @@ bool CSGShape3DGizmoPlugin::is_selectable_when_hidden() const { } void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h index 7763989b2a..48a414d9c7 100644 --- a/modules/csg/csg_gizmos.h +++ b/modules/csg/csg_gizmos.h @@ -36,7 +36,6 @@ #include "editor/node_3d_editor_gizmos.h" class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin); public: diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 701c45a5d7..7df65b04c4 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -32,14 +32,15 @@ #include "scene/3d/path_3d.h" void CSGShape3D::set_use_collision(bool p_enable) { - - if (use_collision == p_enable) + if (use_collision == p_enable) { return; + } use_collision = p_enable; - if (!is_inside_tree() || !is_root_shape()) + if (!is_inside_tree() || !is_root_shape()) { return; + } if (use_collision) { root_collision_shape.instance(); @@ -71,12 +72,10 @@ void CSGShape3D::set_collision_layer(uint32_t p_layer) { } uint32_t CSGShape3D::get_collision_layer() const { - return collision_layer; } void CSGShape3D::set_collision_mask(uint32_t p_mask) { - collision_mask = p_mask; if (root_collision_instance.is_valid()) { PhysicsServer3D::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); @@ -84,42 +83,38 @@ void CSGShape3D::set_collision_mask(uint32_t p_mask) { } uint32_t CSGShape3D::get_collision_mask() const { - return collision_mask; } void CSGShape3D::set_collision_mask_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_mask(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_mask(mask); } bool CSGShape3D::get_collision_mask_bit(int p_bit) const { - return get_collision_mask() & (1 << p_bit); } void CSGShape3D::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_layer(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_layer(mask); } bool CSGShape3D::get_collision_layer_bit(int p_bit) const { - return get_collision_layer() & (1 << p_bit); } bool CSGShape3D::is_root_shape() const { - return !parent; } @@ -132,9 +127,9 @@ float CSGShape3D::get_snap() const { } void CSGShape3D::_make_dirty() { - - if (!is_inside_tree()) + if (!is_inside_tree()) { return; + } if (dirty) { return; @@ -151,7 +146,6 @@ void CSGShape3D::_make_dirty() { } CSGBrush *CSGShape3D::_get_brush() { - if (dirty) { if (brush) { memdelete(brush); @@ -161,23 +155,24 @@ CSGBrush *CSGShape3D::_get_brush() { CSGBrush *n = _build_brush(); for (int i = 0; i < get_child_count(); i++) { - CSGShape3D *child = Object::cast_to<CSGShape3D>(get_child(i)); - if (!child) + if (!child) { continue; - if (!child->is_visible_in_tree()) + } + if (!child->is_visible_in_tree()) { continue; + } CSGBrush *n2 = child->_get_brush(); - if (!n2) + if (!n2) { continue; + } if (!n) { n = memnew(CSGBrush); n->copy_from(*n2, child->get_transform()); } else { - CSGBrush *nn = memnew(CSGBrush); CSGBrush *nn2 = memnew(CSGBrush); nn2->copy_from(*n2, child->get_transform()); @@ -205,10 +200,11 @@ CSGBrush *CSGShape3D::_get_brush() { AABB aabb; for (int i = 0; i < n->faces.size(); i++) { for (int j = 0; j < 3; j++) { - if (i == 0 && j == 0) + if (i == 0 && j == 0) { aabb.position = n->faces[i].vertices[j]; - else + } else { aabb.expand_to(n->faces[i].vertices[j]); + } } } node_aabb = aabb; @@ -263,7 +259,6 @@ void CSGShape3D::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTe void CSGShape3D::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert) { - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); int i = iFace * 3 + iVert; @@ -280,9 +275,9 @@ void CSGShape3D::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const } void CSGShape3D::_update_shape() { - - if (parent) + if (parent) { return; + } set_base(RID()); root_mesh.unref(); //byebye root mesh @@ -325,7 +320,6 @@ void CSGShape3D::_update_shape() { //create arrays for (int i = 0; i < surfaces.size(); i++) { - surfaces.write[i].vertices.resize(face_count[i] * 3); surfaces.write[i].normals.resize(face_count[i] * 3); surfaces.write[i].uvs.resize(face_count[i] * 3); @@ -346,35 +340,36 @@ void CSGShape3D::_update_shape() { } } - //fill arrays - Vector<Vector3> physics_faces; - bool fill_physics_faces = false; + // Update collision faces. if (root_collision_shape.is_valid()) { + Vector<Vector3> physics_faces; physics_faces.resize(n->faces.size() * 3); - fill_physics_faces = true; - } + Vector3 *physicsw = physics_faces.ptrw(); - { - Vector3 *physicsw; + for (int i = 0; i < n->faces.size(); i++) { + int order[3] = { 0, 1, 2 }; - if (fill_physics_faces) { - physicsw = physics_faces.ptrw(); + if (n->faces[i].invert) { + SWAP(order[1], order[2]); + } + + physicsw[i * 3 + 0] = n->faces[i].vertices[order[0]]; + physicsw[i * 3 + 1] = n->faces[i].vertices[order[1]]; + physicsw[i * 3 + 2] = n->faces[i].vertices[order[2]]; } - for (int i = 0; i < n->faces.size(); i++) { + root_collision_shape->set_faces(physics_faces); + } + //fill arrays + { + for (int i = 0; i < n->faces.size(); i++) { int order[3] = { 0, 1, 2 }; if (n->faces[i].invert) { SWAP(order[1], order[2]); } - if (fill_physics_faces) { - physicsw[i * 3 + 0] = n->faces[i].vertices[order[0]]; - physicsw[i * 3 + 1] = n->faces[i].vertices[order[1]]; - physicsw[i * 3 + 2] = n->faces[i].vertices[order[2]]; - } - int mat = n->faces[i].material; ERR_CONTINUE(mat < -1 || mat >= face_count.size()); int idx = mat == -1 ? face_count.size() - 1 : mat; @@ -384,7 +379,6 @@ void CSGShape3D::_update_shape() { Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); for (int j = 0; j < 3; j++) { - Vector3 v = n->faces[i].vertices[j]; Vector3 normal = p.normal; @@ -394,7 +388,6 @@ void CSGShape3D::_update_shape() { } if (n->faces[i].invert) { - normal = -normal; } @@ -439,8 +432,9 @@ void CSGShape3D::_update_shape() { have_tangents = genTangSpaceDefault(&msc); } - if (surfaces[i].last_added == 0) + if (surfaces[i].last_added == 0) { continue; + } // and convert to surface array Array array; @@ -458,12 +452,9 @@ void CSGShape3D::_update_shape() { root_mesh->surface_set_material(idx, surfaces[i].material); } - if (root_collision_shape.is_valid()) { - root_collision_shape->set_faces(physics_faces); - } - set_base(root_mesh->get_rid()); } + AABB CSGShape3D::get_aabb() const { return node_aabb; } @@ -491,14 +482,11 @@ Vector<Vector3> CSGShape3D::get_brush_faces() { } Vector<Face3> CSGShape3D::get_faces(uint32_t p_usage_flags) const { - return Vector<Face3>(); } void CSGShape3D::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - Node *parentn = get_parent(); if (parentn) { parent = Object::cast_to<CSGShape3D>(parentn); @@ -523,23 +511,21 @@ void CSGShape3D::_notification(int p_what) { } if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (parent) { parent->_make_dirty(); } } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (parent) { parent->_make_dirty(); } } if (p_what == NOTIFICATION_EXIT_TREE) { - - if (parent) + if (parent) { parent->_make_dirty(); + } parent = nullptr; if (use_collision && is_root_shape() && root_collision_instance.is_valid()) { @@ -552,7 +538,6 @@ void CSGShape3D::_notification(int p_what) { } void CSGShape3D::set_operation(Operation p_operation) { - operation = p_operation; _make_dirty(); update_gizmo(); @@ -582,7 +567,6 @@ void CSGShape3D::_validate_property(PropertyInfo &property) const { } Array CSGShape3D::get_meshes() const { - if (root_mesh.is_valid()) { Array arr; arr.resize(2); @@ -593,8 +577,8 @@ Array CSGShape3D::get_meshes() const { return Array(); } -void CSGShape3D::_bind_methods() { +void CSGShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape3D::_update_shape); ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape3D::is_root_shape); @@ -657,10 +641,10 @@ CSGShape3D::~CSGShape3D() { brush = nullptr; } } + ////////////////////////////////// CSGBrush *CSGCombiner3D::_build_brush() { - return nullptr; //does not build anything } @@ -670,7 +654,6 @@ CSGCombiner3D::CSGCombiner3D() { ///////////////////// CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uv, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials) { - CSGBrush *brush = memnew(CSGBrush); Vector<bool> invert; @@ -688,7 +671,6 @@ CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector<Vector3> &p_ver } void CSGPrimitive3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive3D::set_invert_faces); ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive3D::is_inverting_faces); @@ -696,8 +678,9 @@ void CSGPrimitive3D::_bind_methods() { } void CSGPrimitive3D::set_invert_faces(bool p_invert) { - if (invert_faces == p_invert) + if (invert_faces == p_invert) { return; + } invert_faces = p_invert; @@ -715,9 +698,9 @@ CSGPrimitive3D::CSGPrimitive3D() { ///////////////////// CSGBrush *CSGMesh3D::_build_brush() { - - if (!mesh.is_valid()) + if (!mesh.is_valid()) { return nullptr; + } Vector<Vector3> vertices; Vector<bool> smooth; @@ -726,7 +709,6 @@ CSGBrush *CSGMesh3D::_build_brush() { Ref<Material> material = get_material(); for (int i = 0; i < mesh->get_surface_count(); i++) { - if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; } @@ -739,8 +721,9 @@ CSGBrush *CSGMesh3D::_build_brush() { } Vector<Vector3> avertices = arrays[Mesh::ARRAY_VERTEX]; - if (avertices.size() == 0) + if (avertices.size() == 0) { continue; + } const Vector3 *vr = avertices.ptr(); @@ -781,7 +764,6 @@ CSGBrush *CSGMesh3D::_build_brush() { const int *ir = aindices.ptr(); for (int j = 0; j < is; j += 3) { - Vector3 vertex[3]; Vector3 normal[3]; Vector2 uv[3]; @@ -825,7 +807,6 @@ CSGBrush *CSGMesh3D::_build_brush() { Ref<Material> *mw = materials.ptrw(); for (int j = 0; j < is; j += 3) { - Vector3 vertex[3]; Vector3 normal[3]; Vector2 uv[3]; @@ -856,8 +837,9 @@ CSGBrush *CSGMesh3D::_build_brush() { } } - if (vertices.size() == 0) + if (vertices.size() == 0) { return nullptr; + } return _create_brush_from_arrays(vertices, uvs, smooth, materials); } @@ -868,19 +850,18 @@ void CSGMesh3D::_mesh_changed() { } void CSGMesh3D::set_material(const Ref<Material> &p_material) { - if (material == p_material) + if (material == p_material) { return; + } material = p_material; _make_dirty(); } Ref<Material> CSGMesh3D::get_material() const { - return material; } void CSGMesh3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh3D::set_mesh); ClassDB::bind_method(D_METHOD("get_mesh"), &CSGMesh3D::get_mesh); @@ -892,9 +873,9 @@ void CSGMesh3D::_bind_methods() { } void CSGMesh3D::set_mesh(const Ref<Mesh> &p_mesh) { - - if (mesh == p_mesh) + if (mesh == p_mesh) { return; + } if (mesh.is_valid()) { mesh->disconnect("changed", callable_mp(this, &CSGMesh3D::_mesh_changed)); } @@ -914,7 +895,6 @@ Ref<Mesh> CSGMesh3D::get_mesh() { //////////////////////////////// CSGBrush *CSGSphere3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -938,7 +918,6 @@ CSGBrush *CSGSphere3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -959,7 +938,6 @@ CSGBrush *CSGSphere3D::_build_brush() { double u1 = double(i) / rings; for (int j = radial_segments; j >= 1; j--) { - double lng0 = 2 * Math_PI * (double)(j - 1) / radial_segments; double x0 = Math::cos(lng0); double y0 = Math::sin(lng0); @@ -986,7 +964,6 @@ CSGBrush *CSGSphere3D::_build_brush() { }; if (i < rings) { - //face 1 facesw[face * 3 + 0] = v[0]; facesw[face * 3 + 1] = v[1]; @@ -1096,13 +1073,11 @@ bool CSGSphere3D::get_smooth_faces() const { } void CSGSphere3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); } Ref<Material> CSGSphere3D::get_material() const { - return material; } @@ -1117,7 +1092,6 @@ CSGSphere3D::CSGSphere3D() { /////////////// CSGBrush *CSGBox3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1141,7 +1115,6 @@ CSGBrush *CSGBox3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1153,25 +1126,22 @@ CSGBrush *CSGBox3D::_build_brush() { Vector3 vertex_mul(width * 0.5, height * 0.5, depth * 0.5); { - for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 }; for (int j = 0; j < 4; j++) { - float v[3]; v[0] = 1.0; v[1] = 1 - 2 * ((j >> 1) & 1); v[2] = v[1] * (1 - 2 * (j & 1)); for (int k = 0; k < 3; k++) { - - if (i < 3) + if (i < 3) { face_points[j][(i + k) % 3] = v[k]; - else + } else { face_points[3 - j][(i + k) % 3] = -v[k]; + } } } @@ -1274,14 +1244,12 @@ float CSGBox3D::get_depth() const { } void CSGBox3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); update_gizmo(); } Ref<Material> CSGBox3D::get_material() const { - return material; } @@ -1295,7 +1263,6 @@ CSGBox3D::CSGBox3D() { /////////////// CSGBrush *CSGCylinder3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1319,7 +1286,6 @@ CSGBrush *CSGCylinder3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1331,9 +1297,7 @@ CSGBrush *CSGCylinder3D::_build_brush() { Vector3 vertex_mul(radius, height * 0.5, radius); { - for (int i = 0; i < sides; i++) { - float inc = float(i) / sides; float inc_n = float((i + 1)) / sides; @@ -1510,13 +1474,11 @@ bool CSGCylinder3D::get_smooth_faces() const { } void CSGCylinder3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); } Ref<Material> CSGCylinder3D::get_material() const { - return material; } @@ -1532,14 +1494,14 @@ CSGCylinder3D::CSGCylinder3D() { /////////////// CSGBrush *CSGTorus3D::_build_brush() { - // set our bounding box float min_radius = inner_radius; float max_radius = outer_radius; - if (min_radius == max_radius) + if (min_radius == max_radius) { return nullptr; //sorry, can't + } if (min_radius > max_radius) { SWAP(min_radius, max_radius); @@ -1568,7 +1530,6 @@ CSGBrush *CSGTorus3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1578,9 +1539,7 @@ CSGBrush *CSGTorus3D::_build_brush() { int face = 0; { - for (int i = 0; i < sides; i++) { - float inci = float(i) / sides; float inci_n = float((i + 1)) / sides; @@ -1591,7 +1550,6 @@ CSGBrush *CSGTorus3D::_build_brush() { Vector3 normali_n = Vector3(Math::cos(angi_n), 0, Math::sin(angi_n)); for (int j = 0; j < ring_sides; j++) { - float incj = float(j) / ring_sides; float incj_n = float((j + 1)) / ring_sides; @@ -1738,13 +1696,11 @@ bool CSGTorus3D::get_smooth_faces() const { } void CSGTorus3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); } Ref<Material> CSGTorus3D::get_material() const { - return material; } @@ -1760,11 +1716,11 @@ CSGTorus3D::CSGTorus3D() { /////////////// CSGBrush *CSGPolygon3D::_build_brush() { - // set our bounding box - if (polygon.size() < 3) + if (polygon.size() < 3) { return nullptr; + } Vector<Point2> final_polygon = polygon; @@ -1774,8 +1730,9 @@ CSGBrush *CSGPolygon3D::_build_brush() { Vector<int> triangles = Geometry::triangulate_polygon(final_polygon); - if (triangles.size() < 3) + if (triangles.size() < 3) { return nullptr; + } Path3D *path = nullptr; Ref<Curve3D> curve; @@ -1789,28 +1746,35 @@ CSGBrush *CSGPolygon3D::_build_brush() { final_polygon_min = p; final_polygon_max = final_polygon_min; } else { - if (p.x < final_polygon_min.x) + if (p.x < final_polygon_min.x) { final_polygon_min.x = p.x; - if (p.y < final_polygon_min.y) + } + if (p.y < final_polygon_min.y) { final_polygon_min.y = p.y; + } - if (p.x > final_polygon_max.x) + if (p.x > final_polygon_max.x) { final_polygon_max.x = p.x; - if (p.y > final_polygon_max.y) + } + if (p.y > final_polygon_max.y) { final_polygon_max.y = p.y; + } } } Vector2 final_polygon_size = final_polygon_max - final_polygon_min; if (mode == MODE_PATH) { - if (!has_node(path_node)) + if (!has_node(path_node)) { return nullptr; + } Node *n = get_node(path_node); - if (!n) + if (!n) { return nullptr; + } path = Object::cast_to<Path3D>(n); - if (!path) + if (!path) { return nullptr; + } if (path != path_cache) { if (path_cache) { @@ -1826,10 +1790,12 @@ CSGBrush *CSGPolygon3D::_build_brush() { path_cache = nullptr; } curve = path->get_curve(); - if (curve.is_null()) + if (curve.is_null()) { return nullptr; - if (curve->get_baked_length() <= 0) + } + if (curve->get_baked_length() <= 0) { return nullptr; + } } CSGBrush *brush = memnew(CSGBrush); @@ -1871,7 +1837,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { AABB aabb; //must be computed { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1882,10 +1847,8 @@ CSGBrush *CSGPolygon3D::_build_brush() { switch (mode) { case MODE_DEPTH: { - //add triangles, front and back for (int i = 0; i < 2; i++) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, i == 0 ? 1 : 2, i == 0 ? 2 : 1 }; @@ -1910,7 +1873,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { //add triangles for depth for (int i = 0; i < final_polygon.size(); i++) { - int i_n = (i + 1) % final_polygon.size(); Vector3 v[4] = { @@ -1960,9 +1922,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } break; case MODE_SPIN: { - for (int i = 0; i < spin_sides; i++) { - float inci = float(i) / spin_sides; float inci_n = float((i + 1)) / spin_sides; @@ -1974,7 +1934,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { //add triangles for depth for (int j = 0; j < final_polygon.size(); j++) { - int j_n = (j + 1) % final_polygon.size(); Vector3 v[4] = { @@ -2023,7 +1982,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } if (i == 0 && spin_degrees < 360) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 2, 1 }; @@ -2041,7 +1999,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } if (i == spin_sides - 1 && spin_degrees < 360) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 1, 2 }; @@ -2061,7 +2018,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } } break; case MODE_PATH: { - float bl = curve->get_baked_length(); int splits = MAX(2, Math::ceil(bl / path_interval)); float u1 = 0.0; @@ -2087,7 +2043,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } for (int i = 0; i <= splits; i++) { - float ofs = i * path_interval; if (ofs > bl) { ofs = bl; @@ -2127,7 +2082,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { //put triangles where they belong //add triangles for depth for (int j = 0; j < final_polygon.size(); j++) { - int j_n = (j + 1) % final_polygon.size(); Vector3 v[4] = { @@ -2177,7 +2131,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } if (i == 0 && !path_joined) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 1, 2 }; @@ -2195,7 +2148,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } if (i == splits && !path_joined) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 2, 1 }; @@ -2417,6 +2369,7 @@ void CSGPolygon3D::set_path_interval(float p_interval) { _make_dirty(); update_gizmo(); } + float CSGPolygon3D::get_path_interval() const { return path_interval; } @@ -2461,13 +2414,11 @@ bool CSGPolygon3D::get_smooth_faces() const { } void CSGPolygon3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); } Ref<Material> CSGPolygon3D::get_material() const { - return material; } diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index abab1ded20..7e95d685c5 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -204,7 +204,6 @@ public: }; class CSGSphere3D : public CSGPrimitive3D { - GDCLASS(CSGSphere3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -237,7 +236,6 @@ public: }; class CSGBox3D : public CSGPrimitive3D { - GDCLASS(CSGBox3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -266,7 +264,6 @@ public: }; class CSGCylinder3D : public CSGPrimitive3D { - GDCLASS(CSGCylinder3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -303,7 +300,6 @@ public: }; class CSGTorus3D : public CSGPrimitive3D { - GDCLASS(CSGTorus3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -340,7 +336,6 @@ public: }; class CSGPolygon3D : public CSGPrimitive3D { - GDCLASS(CSGPolygon3D, CSGPrimitive3D); public: diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index 40eef84b1b..a8bcc2fed1 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -34,7 +34,6 @@ #include "csg_shape.h" void register_csg_types() { - #ifndef _3D_DISABLED ClassDB::register_virtual_class<CSGShape3D>(); |