diff options
Diffstat (limited to 'modules/csg')
-rw-r--r-- | modules/csg/csg.cpp | 316 | ||||
-rw-r--r-- | modules/csg/csg.h | 18 | ||||
-rw-r--r-- | modules/csg/csg_gizmos.cpp | 123 | ||||
-rw-r--r-- | modules/csg/csg_gizmos.h | 25 | ||||
-rw-r--r-- | modules/csg/csg_shape.cpp | 348 | ||||
-rw-r--r-- | modules/csg/csg_shape.h | 47 | ||||
-rw-r--r-- | modules/csg/doc_classes/CSGBox3D.xml | 10 | ||||
-rw-r--r-- | modules/csg/doc_classes/CSGShape3D.xml | 4 | ||||
-rw-r--r-- | modules/csg/icons/CSGBox3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGCapsule3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGCombiner3D.svg | 9 | ||||
-rw-r--r-- | modules/csg/icons/CSGCylinder3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGMesh3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGPolygon3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGSphere3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/icons/CSGTorus3D.svg | 7 | ||||
-rw-r--r-- | modules/csg/register_types.cpp | 5 | ||||
-rw-r--r-- | modules/csg/register_types.h | 4 |
18 files changed, 402 insertions, 556 deletions
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 6714db76bb..f0a2f17ba9 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,22 +30,21 @@ #include "csg.h" -#include "core/math/geometry.h" +#include "core/math/geometry_2d.h" #include "core/math/math_funcs.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" // 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,24 +142,36 @@ 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)) return false; + 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) return false; + 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) { +inline static bool is_triangle_degenerate(const Vector2 p_vertices[3], real_t p_vertex_snap2) { + real_t det = p_vertices[0].x * p_vertices[1].y - p_vertices[0].x * p_vertices[2].y + + p_vertices[0].y * p_vertices[2].x - p_vertices[0].y * p_vertices[1].x + + p_vertices[1].x * p_vertices[2].y - p_vertices[1].y * p_vertices[2].x; + return det < p_vertex_snap2; +} + +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) { @@ -170,7 +186,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]; @@ -180,7 +195,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(); @@ -202,7 +216,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]; @@ -214,21 +227,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) { @@ -253,7 +266,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; @@ -269,7 +281,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++) { @@ -285,7 +296,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]; @@ -305,7 +315,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]; @@ -331,14 +340,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++; } @@ -347,9 +355,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]]; @@ -367,12 +375,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++; } @@ -381,9 +389,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]]; @@ -401,14 +409,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++; } @@ -417,11 +426,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]]; @@ -458,7 +468,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; } @@ -483,7 +492,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]); @@ -519,18 +527,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) return; + for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) { + if (Math::is_equal_approx(**E, p_distance)) { + 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]], @@ -560,22 +569,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]], @@ -588,9 +591,10 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de // Check if faces are co-planar. 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) + // Only add an intersection if not a B face. + 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); @@ -607,7 +611,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) { @@ -620,7 +623,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++; @@ -628,7 +630,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++; @@ -636,18 +637,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. @@ -655,7 +657,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. @@ -701,8 +702,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()); @@ -716,21 +718,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)); @@ -747,8 +748,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; @@ -778,26 +780,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) return vertex_id; + 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."); @@ -810,19 +812,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)) axis = 1; + 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; } @@ -834,7 +838,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)) axis = 1; + 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) { @@ -851,13 +857,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) return; + 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]; @@ -886,14 +892,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]) continue; + outer_edge_idx[1] == p_segment_indices[closest_idx]) { + continue; + } //Don't create degenerate triangles. Vector2 edge1[2] = { @@ -905,8 +912,12 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ vertices[p_segment_indices[closest_idx]].point }; if (are_segements_parallel(edge1, edge2, vertex_snap2)) { - degenerate_points.push_back(outer_edge_idx[0]); - degenerate_points.push_back(outer_edge_idx[1]); + if (!degenerate_points.find(outer_edge_idx[0])) { + degenerate_points.push_back(outer_edge_idx[0]); + } + if (!degenerate_points.find(outer_edge_idx[1])) { + degenerate_points.push_back(outer_edge_idx[1]); + } continue; } @@ -921,14 +932,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) continue; + 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]], @@ -942,7 +955,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; @@ -954,19 +966,19 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ break; } } - if (existing) continue; + 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] }; - Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(point_2D, edge_points); + Vector2 closest_point = Geometry2D::get_closest_point_to_segment(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. @@ -1004,10 +1016,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]], @@ -1017,7 +1027,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 @@ -1031,7 +1040,7 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // First check if the ends of the segment are on the edge. bool on_edge = false; for (int edge_point_idx = 0; edge_point_idx < 2; ++edge_point_idx) { - intersection_point = Geometry::get_closest_point_to_segment_2d(p_segment_points[edge_point_idx], edge_points); + intersection_point = Geometry2D::get_closest_point_to_segment(p_segment_points[edge_point_idx], edge_points); if ((intersection_point - p_segment_points[edge_point_idx]).length_squared() < vertex_snap2) { on_edge = true; break; @@ -1039,14 +1048,17 @@ 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)) { - + if (on_edge || Geometry2D::segment_intersects_segment(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) continue; + (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)) continue; + if (are_segements_parallel(p_segment_points, edge_points, vertex_snap2)) { + continue; + } // Add the intersection point as a new vertex. Vertex2D new_vertex; @@ -1064,19 +1076,11 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s break; } - // Don't create degenerate triangles. - Vector2 split_edge1[2] = { vertices[new_vertex_idx].point, edge_points[0] }; - Vector2 split_edge2[2] = { vertices[new_vertex_idx].point, edge_points[1] }; - Vector2 new_edge[2] = { vertices[new_vertex_idx].point, vertices[opposite_vertex_idx].point }; - if (are_segements_parallel(split_edge1, new_edge, vertex_snap2) && - are_segements_parallel(split_edge2, new_edge, vertex_snap2)) { - break; - } - // 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) + Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points); + 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. @@ -1101,11 +1105,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]], @@ -1123,16 +1125,21 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { face_vertices[2].uv }; + // Skip degenerate triangles. + if (is_triangle_degenerate(points, vertex_snap2)) { + continue; + } + // 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] @@ -1142,7 +1149,7 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { uvs[(face_edge_idx + 1) % 3] }; - Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(p_point, edge_points); + Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, edge_points); if ((closest_point - p_point).length_squared() < vertex_snap2) { on_edge = true; @@ -1193,8 +1200,7 @@ 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)) { - + if (!on_edge && Geometry2D::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; @@ -1204,13 +1210,9 @@ 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] }; - Vector2 new_edge2[2] = { vertices[new_vertex_idx].point, points[(i + 1) % 3] }; - if (are_segements_parallel(edge, new_edge1, vertex_snap2) && - are_segements_parallel(edge, new_edge2, vertex_snap2)) { + Vector2 new_points[3] = { points[i], points[(i + 1) % 3], vertices[new_vertex_idx].point }; + if (is_triangle_degenerate(new_points, vertex_snap2)) { continue; } @@ -1231,7 +1233,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. @@ -1240,7 +1241,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)) { @@ -1250,13 +1250,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; @@ -1303,7 +1304,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] = { @@ -1327,7 +1327,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], @@ -1356,7 +1355,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], @@ -1384,7 +1382,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) return; + 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; @@ -1392,15 +1392,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) return; + 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; @@ -1410,31 +1413,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) return; + 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..1612c16a32 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,20 +31,19 @@ #ifndef CSG_H #define CSG_H -#include "core/list.h" -#include "core/map.h" #include "core/math/aabb.h" #include "core/math/plane.h" #include "core/math/transform.h" #include "core/math/vector2.h" #include "core/math/vector3.h" -#include "core/oa_hash_map.h" -#include "core/reference.h" -#include "core/vector.h" +#include "core/object/reference.h" +#include "core/templates/list.h" +#include "core/templates/map.h" +#include "core/templates/oa_hash_map.h" +#include "core/templates/vector.h" #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 fa176cb94e..e23442ef99 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -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,68 +49,54 @@ 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]; + return "Size"; } 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: return s->get_width(); - case 1: return s->get_height(); - case 2: return s->get_depth(); - } + return s->get_size(); } 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(); @@ -124,91 +109,91 @@ 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; - Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb); + Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb); float d = ra.x; if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); + d = Math::snapped(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; axis[p_idx] = 1.0; Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); + Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); + d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; - - switch (p_idx) { - case 0: s->set_width(d * 2); break; - case 1: s->set_height(d * 2); break; - case 2: s->set_depth(d * 2); break; } + + Vector3 h = s->get_size(); + h[p_idx] = d * 2; + s->set_size(h); } if (Object::cast_to<CSGCylinder3D>(cs)) { - CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); Vector3 axis; axis[p_idx == 0 ? 0 : 1] = 1.0; Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); + Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); + d = Math::snapped(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; axis[0] = 1.0; Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); + Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); + d = Math::snapped(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)) { @@ -228,36 +213,25 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, if (Object::cast_to<CSGBox3D>(cs)) { CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); if (p_cancel) { - switch (p_idx) { - case 0: s->set_width(p_restore); break; - case 1: s->set_height(p_restore); break; - case 2: s->set_depth(p_restore); break; - } + s->set_size(p_restore); return; } UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Box Shape Extents")); - static const char *method[3] = { "set_width", "set_height", "set_depth" }; - float current = 0; - switch (p_idx) { - case 0: current = s->get_width(); break; - case 1: current = s->get_height(); break; - case 2: current = s->get_depth(); break; - } - - ur->add_do_method(s, method[p_idx], current); - ur->add_undo_method(s, method[p_idx], p_restore); + ur->create_action(TTR("Change Box Shape Size")); + ur->add_do_method(s, "set_size", s->get_size()); + ur->add_undo_method(s, "set_size", p_restore); ur->commit_action(); } 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; } @@ -278,10 +252,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; } @@ -299,11 +274,12 @@ 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); } -String CSGShape3DGizmoPlugin::get_name() const { +String CSGShape3DGizmoPlugin::get_gizmo_name() const { return "CSGShape3D"; } @@ -316,7 +292,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(); @@ -393,9 +368,13 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); Vector<Vector3> handles; - handles.push_back(Vector3(s->get_width() * 0.5, 0, 0)); - handles.push_back(Vector3(0, s->get_height() * 0.5, 0)); - handles.push_back(Vector3(0, 0, s->get_depth() * 0.5)); + + for (int i = 0; i < 3; i++) { + Vector3 h; + h[i] = s->get_size()[i] / 2; + handles.push_back(h); + } + p_gizmo->add_handles(handles, handles_material); } diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h index 7763989b2a..8f7da35de3 100644 --- a/modules/csg/csg_gizmos.h +++ b/modules/csg/csg_gizmos.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,20 +36,19 @@ #include "editor/node_3d_editor_gizmos.h" class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Node3D *p_spatial); - String get_name() const; - int get_priority() const; - bool is_selectable_when_hidden() const; - void redraw(EditorNode3DGizmo *p_gizmo); - - String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); - void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + bool has_gizmo(Node3D *p_spatial) override; + String get_gizmo_name() const override; + int get_priority() const override; + bool is_selectable_when_hidden() const override; + void redraw(EditorNode3DGizmo *p_gizmo) override; + + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override; + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) override; CSGShape3DGizmoPlugin(); }; diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 550a919d0d..042c3aaca7 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,17 +29,19 @@ /*************************************************************************/ #include "csg_shape.h" +#include "core/math/geometry_2d.h" #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 +73,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 +84,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,26 +128,20 @@ float CSGShape3D::get_snap() const { } void CSGShape3D::_make_dirty() { - - if (!is_inside_tree()) - return; - - if (dirty) { + if (!is_inside_tree()) { return; } - dirty = true; - if (parent) { parent->_make_dirty(); - } else { - //only parent will do + } else if (!dirty) { call_deferred("_update_shape"); } + + dirty = true; } CSGBrush *CSGShape3D::_get_brush() { - if (dirty) { if (brush) { memdelete(brush); @@ -161,23 +151,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()); @@ -185,9 +176,15 @@ CSGBrush *CSGShape3D::_get_brush() { CSGBrushOperation bop; switch (child->get_operation()) { - case CSGShape3D::OPERATION_UNION: bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); break; - case CSGShape3D::OPERATION_INTERSECTION: bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); break; - case CSGShape3D::OPERATION_SUBTRACTION: bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); break; + case CSGShape3D::OPERATION_UNION: + bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); + break; + case CSGShape3D::OPERATION_INTERSECTION: + bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); + break; + case CSGShape3D::OPERATION_SUBTRACTION: + bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); + break; } memdelete(n); memdelete(nn2); @@ -199,10 +196,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; @@ -257,7 +255,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; @@ -274,9 +271,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 @@ -319,7 +316,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); @@ -340,35 +336,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; @@ -378,7 +375,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; @@ -388,7 +384,6 @@ void CSGShape3D::_update_shape() { } if (n->faces[i].invert) { - normal = -normal; } @@ -433,8 +428,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; @@ -452,12 +448,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; } @@ -485,14 +478,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); @@ -516,24 +506,28 @@ void CSGShape3D::_notification(int p_what) { _make_dirty(); } - if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + if (use_collision && is_root_shape() && root_collision_instance.is_valid()) { + PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + } + } + 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()) { @@ -546,7 +540,6 @@ void CSGShape3D::_notification(int p_what) { } void CSGShape3D::set_operation(Operation p_operation) { - operation = p_operation; _make_dirty(); update_gizmo(); @@ -576,7 +569,6 @@ void CSGShape3D::_validate_property(PropertyInfo &property) const { } Array CSGShape3D::get_meshes() const { - if (root_mesh.is_valid()) { Array arr; arr.resize(2); @@ -587,8 +579,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); @@ -651,11 +643,11 @@ CSGShape3D::~CSGShape3D() { brush = nullptr; } } + ////////////////////////////////// CSGBrush *CSGCombiner3D::_build_brush() { - - return nullptr; //does not build anything + return memnew(CSGBrush); //does not build anything } CSGCombiner3D::CSGCombiner3D() { @@ -664,7 +656,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; @@ -682,7 +673,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); @@ -690,8 +680,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; @@ -709,9 +700,9 @@ CSGPrimitive3D::CSGPrimitive3D() { ///////////////////// CSGBrush *CSGMesh3D::_build_brush() { - - if (!mesh.is_valid()) - return nullptr; + if (!mesh.is_valid()) { + return memnew(CSGBrush); + } Vector<Vector3> vertices; Vector<bool> smooth; @@ -720,7 +711,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; } @@ -729,12 +719,13 @@ CSGBrush *CSGMesh3D::_build_brush() { if (arrays.size() == 0) { _make_dirty(); - ERR_FAIL_COND_V(arrays.size() == 0, nullptr); + ERR_FAIL_COND_V(arrays.size() == 0, memnew(CSGBrush)); } Vector<Vector3> avertices = arrays[Mesh::ARRAY_VERTEX]; - if (avertices.size() == 0) + if (avertices.size() == 0) { continue; + } const Vector3 *vr = avertices.ptr(); @@ -775,7 +766,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]; @@ -819,7 +809,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]; @@ -850,8 +839,9 @@ CSGBrush *CSGMesh3D::_build_brush() { } } - if (vertices.size() == 0) - return nullptr; + if (vertices.size() == 0) { + return memnew(CSGBrush); + } return _create_brush_from_arrays(vertices, uvs, smooth, materials); } @@ -862,19 +852,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); @@ -886,9 +875,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)); } @@ -908,7 +897,6 @@ Ref<Mesh> CSGMesh3D::get_mesh() { //////////////////////////////// CSGBrush *CSGSphere3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -932,7 +920,6 @@ CSGBrush *CSGSphere3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -953,7 +940,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); @@ -980,7 +966,6 @@ CSGBrush *CSGSphere3D::_build_brush() { }; if (i < rings) { - //face 1 facesw[face * 3 + 0] = v[0]; facesw[face * 3 + 1] = v[1]; @@ -1090,13 +1075,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; } @@ -1111,7 +1094,6 @@ CSGSphere3D::CSGSphere3D() { /////////////// CSGBrush *CSGBox3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1135,7 +1117,6 @@ CSGBrush *CSGBox3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1144,28 +1125,25 @@ CSGBrush *CSGBox3D::_build_brush() { int face = 0; - Vector3 vertex_mul(width * 0.5, height * 0.5, depth * 0.5); + Vector3 vertex_mul = size / 2; { - 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]; + } } } @@ -1216,80 +1194,40 @@ CSGBrush *CSGBox3D::_build_brush() { } void CSGBox3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &CSGBox3D::set_width); - ClassDB::bind_method(D_METHOD("get_width"), &CSGBox3D::get_width); - - ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGBox3D::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CSGBox3D::get_height); - - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGBox3D::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CSGBox3D::get_depth); + ClassDB::bind_method(D_METHOD("set_size", "size"), &CSGBox3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &CSGBox3D::get_size); ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox3D::set_material); ClassDB::bind_method(D_METHOD("get_material"), &CSGBox3D::get_material); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_width", "get_width"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_depth", "get_depth"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGBox3D::set_width(const float p_width) { - width = p_width; - _make_dirty(); - update_gizmo(); - _change_notify("width"); -} - -float CSGBox3D::get_width() const { - return width; -} - -void CSGBox3D::set_height(const float p_height) { - height = p_height; - _make_dirty(); - update_gizmo(); - _change_notify("height"); -} - -float CSGBox3D::get_height() const { - return height; -} - -void CSGBox3D::set_depth(const float p_depth) { - depth = p_depth; +void CSGBox3D::set_size(const Vector3 &p_size) { + size = p_size; _make_dirty(); update_gizmo(); - _change_notify("depth"); + _change_notify("size"); } -float CSGBox3D::get_depth() const { - return depth; +Vector3 CSGBox3D::get_size() const { + return size; } void CSGBox3D::set_material(const Ref<Material> &p_material) { - material = p_material; _make_dirty(); update_gizmo(); } Ref<Material> CSGBox3D::get_material() const { - return material; } -CSGBox3D::CSGBox3D() { - // defaults - width = 2.0; - height = 2.0; - depth = 2.0; -} - /////////////// CSGBrush *CSGCylinder3D::_build_brush() { - // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1313,7 +1251,6 @@ CSGBrush *CSGCylinder3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1325,9 +1262,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; @@ -1504,13 +1439,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; } @@ -1526,14 +1459,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) - return nullptr; //sorry, can't + if (min_radius == max_radius) { + return memnew(CSGBrush); //sorry, can't + } if (min_radius > max_radius) { SWAP(min_radius, max_radius); @@ -1562,7 +1495,6 @@ CSGBrush *CSGTorus3D::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1572,9 +1504,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; @@ -1585,7 +1515,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; @@ -1732,13 +1661,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; } @@ -1754,11 +1681,11 @@ CSGTorus3D::CSGTorus3D() { /////////////// CSGBrush *CSGPolygon3D::_build_brush() { - // set our bounding box - if (polygon.size() < 3) - return nullptr; + if (polygon.size() < 3) { + return memnew(CSGBrush); + } Vector<Point2> final_polygon = polygon; @@ -1766,10 +1693,11 @@ CSGBrush *CSGPolygon3D::_build_brush() { final_polygon.invert(); } - Vector<int> triangles = Geometry::triangulate_polygon(final_polygon); + Vector<int> triangles = Geometry2D::triangulate_polygon(final_polygon); - if (triangles.size() < 3) - return nullptr; + if (triangles.size() < 3) { + return memnew(CSGBrush); + } Path3D *path = nullptr; Ref<Curve3D> curve; @@ -1783,24 +1711,35 @@ CSGBrush *CSGPolygon3D::_build_brush() { final_polygon_min = p; final_polygon_max = final_polygon_min; } else { - if (p.x < final_polygon_min.x) final_polygon_min.x = p.x; - if (p.y < final_polygon_min.y) final_polygon_min.y = p.y; + if (p.x < final_polygon_min.x) { + final_polygon_min.x = p.x; + } + if (p.y < final_polygon_min.y) { + final_polygon_min.y = p.y; + } - if (p.x > final_polygon_max.x) final_polygon_max.x = p.x; - if (p.y > final_polygon_max.y) final_polygon_max.y = p.y; + if (p.x > final_polygon_max.x) { + final_polygon_max.x = p.x; + } + 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)) - return nullptr; + if (!has_node(path_node)) { + return memnew(CSGBrush); + } Node *n = get_node(path_node); - if (!n) - return nullptr; + if (!n) { + return memnew(CSGBrush); + } path = Object::cast_to<Path3D>(n); - if (!path) - return nullptr; + if (!path) { + return memnew(CSGBrush); + } if (path != path_cache) { if (path_cache) { @@ -1816,18 +1755,24 @@ CSGBrush *CSGPolygon3D::_build_brush() { path_cache = nullptr; } curve = path->get_curve(); - if (curve.is_null()) - return nullptr; - if (curve->get_baked_length() <= 0) - return nullptr; + if (curve.is_null()) { + return memnew(CSGBrush); + } + if (curve->get_baked_length() <= 0) { + return memnew(CSGBrush); + } } CSGBrush *brush = memnew(CSGBrush); int face_count = 0; switch (mode) { - case MODE_DEPTH: face_count = triangles.size() * 2 / 3 + (final_polygon.size()) * 2; break; - case MODE_SPIN: face_count = (spin_degrees < 360 ? triangles.size() * 2 / 3 : 0) + (final_polygon.size()) * 2 * spin_sides; break; + case MODE_DEPTH: + face_count = triangles.size() * 2 / 3 + (final_polygon.size()) * 2; + break; + case MODE_SPIN: + face_count = (spin_degrees < 360 ? triangles.size() * 2 / 3 : 0) + (final_polygon.size()) * 2 * spin_sides; + break; case MODE_PATH: { float bl = curve->get_baked_length(); int splits = MAX(2, Math::ceil(bl / path_interval)); @@ -1857,7 +1802,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { AABB aabb; //must be computed { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1868,10 +1812,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 }; @@ -1896,7 +1838,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] = { @@ -1946,9 +1887,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; @@ -1960,7 +1899,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] = { @@ -2009,7 +1947,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 }; @@ -2027,7 +1964,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 }; @@ -2047,7 +1983,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; @@ -2073,7 +2008,6 @@ CSGBrush *CSGPolygon3D::_build_brush() { } for (int i = 0; i <= splits; i++) { - float ofs = i * path_interval; if (ofs > bl) { ofs = bl; @@ -2113,7 +2047,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] = { @@ -2163,7 +2096,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 }; @@ -2181,7 +2113,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 }; @@ -2403,6 +2334,7 @@ void CSGPolygon3D::set_path_interval(float p_interval) { _make_dirty(); update_gizmo(); } + float CSGPolygon3D::get_path_interval() const { return path_interval; } @@ -2447,13 +2379,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..7dff8b6d3b 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -114,7 +114,7 @@ protected: friend class CSGCombiner3D; CSGBrush *_get_brush(); - virtual void _validate_property(PropertyInfo &property) const; + virtual void _validate_property(PropertyInfo &property) const override; public: Array get_meshes() const; @@ -124,8 +124,8 @@ public: virtual Vector<Vector3> get_brush_faces(); - virtual AABB get_aabb() const; - virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const; + virtual AABB get_aabb() const override; + virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override; void set_use_collision(bool p_enable); bool is_using_collision() const; @@ -159,7 +159,7 @@ class CSGCombiner3D : public CSGShape3D { GDCLASS(CSGCombiner3D, CSGShape3D); private: - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; public: CSGCombiner3D(); @@ -185,7 +185,7 @@ public: class CSGMesh3D : public CSGPrimitive3D { GDCLASS(CSGMesh3D, CSGPrimitive3D); - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Ref<Mesh> mesh; Ref<Material> material; @@ -204,9 +204,8 @@ public: }; class CSGSphere3D : public CSGPrimitive3D { - GDCLASS(CSGSphere3D, CSGPrimitive3D); - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Ref<Material> material; bool smooth_faces; @@ -237,38 +236,28 @@ public: }; class CSGBox3D : public CSGPrimitive3D { - GDCLASS(CSGBox3D, CSGPrimitive3D); - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Ref<Material> material; - float width; - float height; - float depth; + Vector3 size = Vector3(2, 2, 2); protected: static void _bind_methods(); public: - void set_width(const float p_width); - float get_width() const; - - void set_height(const float p_height); - float get_height() const; - - void set_depth(const float p_depth); - float get_depth() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; - CSGBox3D(); + CSGBox3D() {} }; class CSGCylinder3D : public CSGPrimitive3D { - GDCLASS(CSGCylinder3D, CSGPrimitive3D); - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Ref<Material> material; float radius; @@ -303,9 +292,8 @@ public: }; class CSGTorus3D : public CSGPrimitive3D { - GDCLASS(CSGTorus3D, CSGPrimitive3D); - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Ref<Material> material; float inner_radius; @@ -340,7 +328,6 @@ public: }; class CSGPolygon3D : public CSGPrimitive3D { - GDCLASS(CSGPolygon3D, CSGPrimitive3D); public: @@ -357,7 +344,7 @@ public: }; private: - virtual CSGBrush *_build_brush(); + virtual CSGBrush *_build_brush() override; Vector<Vector2> polygon; Ref<Material> material; @@ -388,7 +375,7 @@ private: protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const; + virtual void _validate_property(PropertyInfo &property) const override; void _notification(int p_what); public: diff --git a/modules/csg/doc_classes/CSGBox3D.xml b/modules/csg/doc_classes/CSGBox3D.xml index 492bf68c44..b1d0454b76 100644 --- a/modules/csg/doc_classes/CSGBox3D.xml +++ b/modules/csg/doc_classes/CSGBox3D.xml @@ -11,17 +11,11 @@ <methods> </methods> <members> - <member name="depth" type="float" setter="set_depth" getter="get_depth" default="2.0"> - Depth of the box measured from the center of the box. - </member> - <member name="height" type="float" setter="set_height" getter="get_height" default="2.0"> - Height of the box measured from the center of the box. - </member> <member name="material" type="Material" setter="set_material" getter="get_material"> The material used to render the box. </member> - <member name="width" type="float" setter="set_width" getter="get_width" default="2.0"> - Width of the box measured from the center of the box. + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3( 2, 2, 2 )"> + The box's width, height and depth. </member> </members> <constants> diff --git a/modules/csg/doc_classes/CSGShape3D.xml b/modules/csg/doc_classes/CSGShape3D.xml index 43ce988c30..dac556c7f1 100644 --- a/modules/csg/doc_classes/CSGShape3D.xml +++ b/modules/csg/doc_classes/CSGShape3D.xml @@ -71,10 +71,10 @@ <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this area is in. Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. - A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. + A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this CSG shape scans for collisions. + The physics layers this CSG shape scans for collisions. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape3D.Operation" default="0"> The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent. diff --git a/modules/csg/icons/CSGBox3D.svg b/modules/csg/icons/CSGBox3D.svg index 67e34df444..ceef9196a7 100644 --- a/modules/csg/icons/CSGBox3D.svg +++ b/modules/csg/icons/CSGBox3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/> -<path transform="translate(0 1036.4)" d="m8 0.94531-7 3.5v7.2227l7 3.5 0.29492-0.14844c-0.18282-0.30101-0.29492-0.64737-0.29492-1.0195v-2c0-0.72651 0.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c0.36419 0 0.70336 0.10754 1 0.2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc9c9c" stroke-width="1.0667"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m8 .94531-7 3.5v7.2227l7 3.5.29492-.14844c-.18282-.30101-.29492-.64737-.29492-1.0195v-2c0-.72651.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c.36419 0 .70336.10754 1 .2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc9c9c" stroke-width="1.0667"/></svg> diff --git a/modules/csg/icons/CSGCapsule3D.svg b/modules/csg/icons/CSGCapsule3D.svg index 92a7b5a870..14e582ee84 100644 --- a/modules/csg/icons/CSGCapsule3D.svg +++ b/modules/csg/icons/CSGCapsule3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g> -<path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922 0.092943 0 0.18367-0.008623 0.27539-0.013672-0.17055-0.29341-0.27539-0.62792-0.27539-0.98633v-2c0-0.72887 0.41095-1.3691 1.0059-1.7188v-0.28125c0.34771-0.034464 0.68259-0.10691 1.0156-0.19922 0.10394-0.99856 0.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-0.66556-0.1047-1.2974-0.37231-1.9941-0.66211v-1.3223c0-1.3474 0.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957 0.4088 1.9941 1.5256 1.9941 2.873v1.3457c-0.68406 0.3054-1.3142 0.57292-1.9941 0.66602v-4.8848zm-4.0059 6.334c0.67836 0.2231 1.3126 0.44599 1.9941 0.52539v2.8848c-1.1957-0.4092-1.9941-1.5237-1.9941-2.8711v-0.53906z" fill="#fc9c9c"/> -<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922.092943 0 .18367-.008623.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72887.41095-1.3691 1.0059-1.7188v-.28125c.34771-.034464.68259-.10691 1.0156-.19922.10394-.99856.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-.66556-.1047-1.2974-.37231-1.9941-.66211v-1.3223c0-1.3474.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957.4088 1.9941 1.5256 1.9941 2.873v1.3457c-.68406.3054-1.3142.57292-1.9941.66602v-4.8848zm-4.0059 6.334c.67836.2231 1.3126.44599 1.9941.52539v2.8848c-1.1957-.4092-1.9941-1.5237-1.9941-2.8711v-.53906z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg> diff --git a/modules/csg/icons/CSGCombiner3D.svg b/modules/csg/icons/CSGCombiner3D.svg index cce2902e24..50ce4179d9 100644 --- a/modules/csg/icons/CSGCombiner3D.svg +++ b/modules/csg/icons/CSGCombiner3D.svg @@ -1,8 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/> -<g fill="#fc9c9c"> -<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-0.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046 0.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc9c9c"/> -</g> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc9c9c"/></svg> diff --git a/modules/csg/icons/CSGCylinder3D.svg b/modules/csg/icons/CSGCylinder3D.svg index 645a74c79b..c84594928a 100644 --- a/modules/csg/icons/CSGCylinder3D.svg +++ b/modules/csg/icons/CSGCylinder3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 14.999999 14.999999" xmlns="http://www.w3.org/2000/svg"> -<g> -<path transform="scale(.9375)" d="m8 1c-1.7469 0-3.328 0.22648-4.5586 0.63672-0.61528 0.20512-1.1471 0.45187-1.5898 0.80078-0.44272 0.34891-0.85156 0.88101-0.85156 1.5625v8c0 0.68149 0.40884 1.2155 0.85156 1.5645 0.44272 0.34891 0.97457 0.59577 1.5898 0.80078 1.2306 0.41024 2.8117 0.63477 4.5586 0.63477 0.095648 0 0.18467-0.008426 0.2793-0.009766-0.1722-0.29446-0.2793-0.62995-0.2793-0.99023v-1c-1.5668 0-2.9867-0.2195-3.9277-0.5332-0.46329-0.15435-0.90474-0.33752-1.0723-0.4668v-5.8125c0.1468 0.058667 0.2835 0.12515 0.44141 0.17773 1.2306 0.41024 2.8117 0.63477 4.5586 0.63477s3.328-0.22453 4.5586-0.63477c0.15791-0.052267 0.29461-0.11864 0.44141-0.17773v1.8125h1c0.36396 0 0.70348 0.10774 1 0.2832v-4.2832c0-0.68149-0.40884-1.2136-0.85156-1.5625-0.44272-0.34891-0.97457-0.59566-1.5898-0.80078-1.2306-0.41024-2.8117-0.63672-4.5586-0.63672zm0 2c1.5668 0 2.9867 0.22145 3.9277 0.53516 0.46368 0.15456 0.80138 0.33741 0.96875 0.4668-0.16752 0.12928-0.50546 0.3105-0.96875 0.46484-0.94102 0.31371-2.361 0.5332-3.9277 0.5332s-2.9867-0.2195-3.9277-0.5332c-0.46329-0.15435-0.80123-0.33556-0.96875-0.46484 0.16737-0.12939 0.50507-0.31224 0.96875-0.4668 0.94102-0.31371 2.361-0.53516 3.9277-0.53516z" fill="#fc9c9c" stroke-width="1.0667"/> -<path d="m11.25 8.4375c-0.51938 0-0.9375 0.41812-0.9375 0.9375v0.9375h1.875v1.875h0.9375c0.51938 0 0.9375-0.41812 0.9375-0.9375v-1.875c0-0.51938-0.41812-0.9375-0.9375-0.9375zm0.9375 3.75h-1.875v-1.875h-0.9375c-0.51938 0-0.9375 0.41812-0.9375 0.9375v1.875c0 0.51938 0.41812 0.9375 0.9375 0.9375h1.875c0.51938 0 0.9375-0.41812 0.9375-0.9375z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.7469 0-3.328.22648-4.5586.63672-.61528.20512-1.1471.45187-1.5898.80078-.44272.34891-.85156.88101-.85156 1.5625v8c0 .68149.40884 1.2155.85156 1.5645.44272.34891.97457.59577 1.5898.80078 1.2306.41024 2.8117.63477 4.5586.63477.095648 0 .18467-.008426.2793-.009766-.1722-.29446-.2793-.62995-.2793-.99023v-1c-1.5668 0-2.9867-.2195-3.9277-.5332-.46329-.15435-.90474-.33752-1.0723-.4668v-5.8125c.1468.058667.2835.12515.44141.17773 1.2306.41024 2.8117.63477 4.5586.63477s3.328-.22453 4.5586-.63477c.15791-.052267.29461-.11864.44141-.17773v1.8125h1c.36396 0 .70348.10774 1 .2832v-4.2832c0-.68149-.40884-1.2136-.85156-1.5625-.44272-.34891-.97457-.59566-1.5898-.80078-1.2306-.41024-2.8117-.63672-4.5586-.63672zm0 2c1.5668 0 2.9867.22145 3.9277.53516.46368.15456.80138.33741.96875.4668-.16752.12928-.50546.3105-.96875.46484-.94102.31371-2.361.5332-3.9277.5332s-2.9867-.2195-3.9277-.5332c-.46329-.15435-.80123-.33556-.96875-.46484.16737-.12939.50507-.31224.96875-.4668.94102-.31371 2.361-.53516 3.9277-.53516z" fill="#fc9c9c" stroke-width="1.0667" transform="scale(.9375)"/><path d="m11.25 8.4375c-.51938 0-.9375.41812-.9375.9375v.9375h1.875v1.875h.9375c.51938 0 .9375-.41812.9375-.9375v-1.875c0-.51938-.41812-.9375-.9375-.9375zm.9375 3.75h-1.875v-1.875h-.9375c-.51938 0-.9375.41812-.9375.9375v1.875c0 .51938.41812.9375.9375.9375h1.875c.51938 0 .9375-.41812.9375-.9375z" fill="#84c2ff"/></svg> diff --git a/modules/csg/icons/CSGMesh3D.svg b/modules/csg/icons/CSGMesh3D.svg index 6e940a4aa5..962e71f6ae 100644 --- a/modules/csg/icons/CSGMesh3D.svg +++ b/modules/csg/icons/CSGMesh3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g> -<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h3.2695v-2h-3.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l4.916 4.916c0.31428-0.20669 0.68609-0.33008 1.084-0.33008 0-0.3979 0.12338-0.76971 0.33008-1.084l-4.916-4.916h5.8574c0.17478 0.30301 0.42598 0.55488 0.72852 0.73047v3.2695h2v-3.2715c0.61771-0.35663 0.99874-1.0152 1-1.7285 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1z" fill="#fc9c9c"/> -<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h3.2695v-2h-3.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l4.916 4.916c.31428-.20669.68609-.33008 1.084-.33008 0-.3979.12338-.76971.33008-1.084l-4.916-4.916h5.8574c.17478.30301.42598.55488.72852.73047v3.2695h2v-3.2715c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg> diff --git a/modules/csg/icons/CSGPolygon3D.svg b/modules/csg/icons/CSGPolygon3D.svg index 71b03cb8e6..1d496e5fd9 100644 --- a/modules/csg/icons/CSGPolygon3D.svg +++ b/modules/csg/icons/CSGPolygon3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m7.9629 1.002c-0.14254 0.00487-0.28238 0.04016-0.41016 0.10352l-6 3c-0.33878 0.16944-0.55276 0.51574-0.55273 0.89453v5.832c-0.105 0.61631 0.37487 1.1768 1 1.168h5v2c2.16e-5 0.67546 0.64487 1.1297 1.2617 0.95898-0.16118-0.28721-0.26172-0.61135-0.26172-0.95898v-2c0-0.72673 0.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c0.36397 0 0.70348 0.10774 1 0.2832v-3.2773c6e-6 -0.00195 6e-6 -0.0039094 0-0.0058594 2.6e-5 -0.37879-0.21395-0.72509-0.55273-0.89453l-6-3c-0.15022-0.074574-0.31679-0.11017-0.48438-0.10352zm0.037109 2.1172l3.7637 1.8809-2.7637 1.3809v-1.3809c-5.52e-5 -0.55226-0.44774-0.99994-1-1h-1.7617l1.7617-0.88086zm-5 2.8809h4v4h-4v-4z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002c-.14254.00487-.28238.04016-.41016.10352l-6 3c-.33878.16944-.55276.51574-.55273.89453v5.832c-.105.61631.37487 1.1768 1 1.168h5v2c.0000216.67546.64487 1.1297 1.2617.95898-.16118-.28721-.26172-.61135-.26172-.95898v-2c0-.72673.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c.36397 0 .70348.10774 1 .2832v-3.2773c.000006-.00195.000006-.0039094 0-.0058594.000026-.37879-.21395-.72509-.55273-.89453l-6-3c-.15022-.074574-.31679-.11017-.48438-.10352zm.037109 2.1172 3.7637 1.8809-2.7637 1.3809v-1.3809c-.0000552-.55226-.44774-.99994-1-1h-1.7617l1.7617-.88086zm-5 2.8809h4v4h-4z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg> diff --git a/modules/csg/icons/CSGSphere3D.svg b/modules/csg/icons/CSGSphere3D.svg index f81b566993..639e38f49f 100644 --- a/modules/csg/icons/CSGSphere3D.svg +++ b/modules/csg/icons/CSGSphere3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g> -<path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 0.093042 0 0.18321-0.01004 0.27539-0.013672-0.17055-0.29341-0.27539-0.62792-0.27539-0.98633v-2c0-0.72673 0.40794-1.3664 1-1.7168v-0.33398c0.34074-0.019259 0.67728-0.069097 1.0156-0.10547 0.083091-1.0187 0.94713-1.8438 1.9844-1.8438h2c0.35841 0 0.69292 0.10484 0.98633 0.27539 0.003633-0.092184 0.013672-0.18235 0.013672-0.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-0.071342-2.6061-0.29819-3.9434-0.69141 0.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549 0.41253 3.637 2.0767 3.9414 4.1699-1.3046 0.36677-2.6158 0.60259-3.9414 0.6875v-4.8574zm-5.7793 6.2988c1.2733 0.31892 2.5337 0.50215 3.7793 0.5625v2.9414c-1.8291-0.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc9c9c"/> -<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 .093042 0 .18321-.01004.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72673.40794-1.3664 1-1.7168v-.33398c.34074-.019259.67728-.069097 1.0156-.10547.083091-1.0187.94713-1.8438 1.9844-1.8438h2c.35841 0 .69292.10484.98633.27539.003633-.092184.013672-.18235.013672-.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm-5.7793 6.2988c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg> diff --git a/modules/csg/icons/CSGTorus3D.svg b/modules/csg/icons/CSGTorus3D.svg index 3d30aa47b2..eb8c0f37cb 100644 --- a/modules/csg/icons/CSGTorus3D.svg +++ b/modules/csg/icons/CSGTorus3D.svg @@ -1,6 +1 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m8 3c-1.8145 0-3.4691 0.41721-4.7461 1.1621-1.277 0.745-2.2539 1.9082-2.2539 3.3379 0 1.4298 0.9769 2.5949 2.2539 3.3398 1.277 0.7449 2.9316 1.1602 4.7461 1.1602 0-1.0907 0.90931-2 2-2 0-0.080836 0.013744-0.15778 0.023438-0.23633-0.61769 0.14673-1.3008 0.23633-2.0234 0.23633-1.4992 0-2.8437-0.36687-3.7383-0.88867-0.89456-0.5219-1.2617-1.108-1.2617-1.6113 0-0.5032 0.36716-1.0876 1.2617-1.6094 0.89456-0.5219 2.2391-0.89062 3.7383-0.89062s2.8437 0.36872 3.7383 0.89062c0.89456 0.5218 1.2617 1.1062 1.2617 1.6094 0 0.15978-0.053679 0.32822-0.13281 0.5h1.1328c0.32481 0 0.62893 0.088408 0.90234 0.23047 0.057552-0.23582 0.097656-0.47718 0.097656-0.73047 0-1.4297-0.9769-2.5929-2.2539-3.3379-1.277-0.7449-2.9316-1.1621-4.7461-1.1621z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> -<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/> -</g> -</svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3c-1.8145 0-3.4691.41721-4.7461 1.1621-1.277.745-2.2539 1.9082-2.2539 3.3379 0 1.4298.9769 2.5949 2.2539 3.3398s2.9316 1.1602 4.7461 1.1602c0-1.0907.90931-2 2-2 0-.080836.013744-.15778.023438-.23633-.61769.14673-1.3008.23633-2.0234.23633-1.4992 0-2.8437-.36687-3.7383-.88867-.89456-.5219-1.2617-1.108-1.2617-1.6113 0-.5032.36716-1.0876 1.2617-1.6094.89456-.5219 2.2391-.89062 3.7383-.89062s2.8437.36872 3.7383.89062c.89456.5218 1.2617 1.1062 1.2617 1.6094 0 .15978-.053679.32822-.13281.5h1.1328c.32481 0 .62893.088408.90234.23047.057552-.23582.097656-.47718.097656-.73047 0-1.4297-.9769-2.5929-2.2539-3.3379-1.277-.7449-2.9316-1.1621-4.7461-1.1621z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg> diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index 40eef84b1b..e28f44d1eb 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,6 @@ #include "csg_shape.h" void register_csg_types() { - #ifndef _3D_DISABLED ClassDB::register_virtual_class<CSGShape3D>(); diff --git a/modules/csg/register_types.h b/modules/csg/register_types.h index 926e598561..8747b3fade 100644 --- a/modules/csg/register_types.h +++ b/modules/csg/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |