diff options
Diffstat (limited to 'modules/csg/csg.cpp')
-rw-r--r-- | modules/csg/csg.cpp | 242 |
1 files changed, 113 insertions, 129 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; |