- MeshEditingLibrary now uses the mesh's full AABB for cap UV generation.

- MeshEditingLibrary can now also set X/Y/Z plane cap materials as needed.
This commit is contained in:
2026-09-19 02:10:13 -04:00
parent 205ab4357a
commit bdca6d83b3
2 changed files with 31 additions and 35 deletions
+23 -27
View File
@@ -17,15 +17,7 @@
using namespace godot; using namespace godot;
MeshEditingLibrary::MeshEditingLibrary() PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const AABB &original_aabb, const Plane &local_plane, Ref<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const TypedArray<Material> &cap_materials)
{
}
MeshEditingLibrary::~MeshEditingLibrary()
{
}
PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const Plane &local_plane, Ref<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const Ref<StandardMaterial3D> cap_material)
{ {
const Time *time = Time::get_singleton(); const Time *time = Time::get_singleton();
@@ -89,6 +81,8 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
for (uint8_t surface = 0; surface < num_surfaces; surface++) for (uint8_t surface = 0; surface < num_surfaces; surface++)
{ {
Ref<Material> original_material = original_mesh->surface_get_material(surface);
const SkinnedVertices &surface_skinned_vertex_positions = skinned_vertex_positions[surface]; const SkinnedVertices &surface_skinned_vertex_positions = skinned_vertex_positions[surface];
const Array &surface_arrays = original_mesh->surface_get_arrays(surface); const Array &surface_arrays = original_mesh->surface_get_arrays(surface);
@@ -458,8 +452,9 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
if (has_weight) first_half_section[ArrayMesh::ARRAY_WEIGHTS] = first_half_weights[surface]; if (has_weight) first_half_section[ArrayMesh::ARRAY_WEIGHTS] = first_half_weights[surface];
first_half_section[ArrayMesh::ARRAY_INDEX] = first_half_indices[surface]; first_half_section[ArrayMesh::ARRAY_INDEX] = first_half_indices[surface];
const uint16_t next_surface = out_first_half->get_surface_count();
out_first_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, first_half_section); out_first_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, first_half_section);
out_first_half->surface_set_material(surface, original_mesh->surface_get_material(surface)); out_first_half->surface_set_material(next_surface, original_material);
} }
if (other_half_vertices[surface].size() > 0 && other_half_indices[surface].size() > 0) if (other_half_vertices[surface].size() > 0 && other_half_indices[surface].size() > 0)
@@ -476,22 +471,14 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
if (has_weight) other_half_section[ArrayMesh::ARRAY_WEIGHTS] = other_half_weights[surface]; if (has_weight) other_half_section[ArrayMesh::ARRAY_WEIGHTS] = other_half_weights[surface];
other_half_section[ArrayMesh::ARRAY_INDEX] = other_half_indices[surface]; other_half_section[ArrayMesh::ARRAY_INDEX] = other_half_indices[surface];
const uint16_t next_surface = out_other_half->get_surface_count();
out_other_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, other_half_section); out_other_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, other_half_section);
out_other_half->surface_set_material(surface, original_mesh->surface_get_material(surface)); out_other_half->surface_set_material(next_surface, original_material);
} }
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " split edges at ", time->get_ticks_msec(), "ms"); PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " split edges at ", time->get_ticks_msec(), "ms");
} }
if (clip_edges.size() > 0)
{
std::vector<MeshEditEdge2D> edges_2d;
std::vector<MeshEditPolygon2D> polygon_set;
std::vector<MeshEditPolygon2D> error_polygons;
const Transform3D &plane_inverse_transform = MeshEditingLibrary::project_edges(edges_2d, original_mesh_instance->get_transform(), clip_edges, local_plane);
MeshEditingLibrary::build_2d_polygons_from_edges(polygon_set, edges_2d, error_polygons);
MeshEditingLibrary::draw_debug_polygons(original_mesh_instance, error_polygons, plane_inverse_transform, Color(1.0f, 0.0f, 0.0f, 1.0f));
MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z; MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z;
const Basis &mesh_instance_basis = original_mesh_instance->get_basis(); const Basis &mesh_instance_basis = original_mesh_instance->get_basis();
const Vector3 &local_plane_normal = local_plane.get_normal(); const Vector3 &local_plane_normal = local_plane.get_normal();
@@ -504,7 +491,16 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
uv_plane = MeshSlicePlaneOrientation::X; uv_plane = MeshSlicePlaneOrientation::X;
} }
const Vector3 &mesh_bounds = original_mesh->get_aabb().get_size(); if (clip_edges.size() > 0)
{
std::vector<MeshEditEdge2D> edges_2d;
std::vector<MeshEditPolygon2D> polygon_set;
std::vector<MeshEditPolygon2D> error_polygons;
const Transform3D &plane_inverse_transform = MeshEditingLibrary::project_edges(edges_2d, clip_edges, local_plane);
MeshEditingLibrary::build_2d_polygons_from_edges(polygon_set, edges_2d, error_polygons);
MeshEditingLibrary::draw_debug_polygons(original_mesh_instance, error_polygons, plane_inverse_transform, Color(1.0f, 0.0f, 0.0f, 1.0f));
const Vector3 &mesh_bounds = original_aabb.get_size();
const uint32_t num_polygons = polygon_set.size(); const uint32_t num_polygons = polygon_set.size();
for (uint32_t polygon_index = 0; polygon_index < num_polygons; polygon_index++) for (uint32_t polygon_index = 0; polygon_index < num_polygons; polygon_index++)
{ {
@@ -588,7 +584,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
if (cap_section_bones.size()) cap_mesh_section[ArrayMesh::ARRAY_BONES] = cap_section_bones; if (cap_section_bones.size()) cap_mesh_section[ArrayMesh::ARRAY_BONES] = cap_section_bones;
if (cap_section_weights.size()) cap_mesh_section[ArrayMesh::ARRAY_WEIGHTS] = cap_section_weights; if (cap_section_weights.size()) cap_mesh_section[ArrayMesh::ARRAY_WEIGHTS] = cap_section_weights;
out_first_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, cap_mesh_section); out_first_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, cap_mesh_section);
out_first_half->surface_set_material(out_first_half->get_surface_count()-1, cap_material); out_first_half->surface_set_material(out_first_half->get_surface_count()-1, cap_materials[uv_plane]);
const uint32_t num_cap_triangles = cap_section_indices.size(); const uint32_t num_cap_triangles = cap_section_indices.size();
for (uint32_t i = 0; i < num_cap_triangles; i += 3) for (uint32_t i = 0; i < num_cap_triangles; i += 3)
@@ -610,7 +606,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
if (cap_section_bones.size()) cap_other_mesh_section[ArrayMesh::ARRAY_BONES] = cap_section_bones; if (cap_section_bones.size()) cap_other_mesh_section[ArrayMesh::ARRAY_BONES] = cap_section_bones;
if (cap_section_weights.size()) cap_other_mesh_section[ArrayMesh::ARRAY_WEIGHTS] = cap_section_weights; if (cap_section_weights.size()) cap_other_mesh_section[ArrayMesh::ARRAY_WEIGHTS] = cap_section_weights;
out_other_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, cap_other_mesh_section); out_other_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, cap_other_mesh_section);
out_other_half->surface_set_material(out_other_half->get_surface_count()-1, cap_material); out_other_half->surface_set_material(out_other_half->get_surface_count()-1, cap_materials[uv_plane]);
} }
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Generated final cap surface at ", time->get_ticks_msec(), "ms"); PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Generated final cap surface at ", time->get_ticks_msec(), "ms");
@@ -717,7 +713,7 @@ SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mes
} }
const Transform3D MeshEditingLibrary::project_edges(std::vector<MeshEditEdge2D> &out_2d_edges, const Transform3D &to_node_space, const std::vector<MeshEditEdge3D> &in_3d_edges, const Plane &plane) const Transform3D MeshEditingLibrary::project_edges(std::vector<MeshEditEdge2D> &out_2d_edges, const std::vector<MeshEditEdge3D> &in_3d_edges, const Plane &plane)
{ {
out_2d_edges.resize(in_3d_edges.size()); out_2d_edges.resize(in_3d_edges.size());
@@ -863,11 +859,11 @@ const Vector2 MeshEditingLibrary::calculate_planar_uv(const Vector3 &vertex, con
switch(axis) switch(axis)
{ {
case MeshSlicePlaneOrientation::X: case MeshSlicePlaneOrientation::X:
return Vector2(vertex.y / mesh_bounds.y, vertex.z / mesh_bounds.z); return Vector2(1.0f - (vertex.z / mesh_bounds.z) + 0.5f, 1.0f - (vertex.y / mesh_bounds.y));
case MeshSlicePlaneOrientation::Y: case MeshSlicePlaneOrientation::Y:
return Vector2(vertex.x / mesh_bounds.x, vertex.z / mesh_bounds.z); return Vector2(1.0f - (vertex.x / mesh_bounds.x) + 0.5f, (vertex.z / mesh_bounds.z) + 0.5f);
case MeshSlicePlaneOrientation::Z: default: case MeshSlicePlaneOrientation::Z: default:
return Vector2(vertex.x / mesh_bounds.x, vertex.y / mesh_bounds.y); return Vector2(1.0f - (vertex.x / mesh_bounds.x) + 0.5f, 1.0f - (vertex.y / mesh_bounds.y));
} }
} }
+4 -4
View File
@@ -60,8 +60,8 @@ class MeshEditingLibrary : public Node
GDCLASS(MeshEditingLibrary, Node); GDCLASS(MeshEditingLibrary, Node);
public: public:
MeshEditingLibrary(); MeshEditingLibrary(){}
~MeshEditingLibrary(); ~MeshEditingLibrary(){}
enum MeshEditCapUV enum MeshEditCapUV
{ {
@@ -70,7 +70,7 @@ public:
CAP_UV_TILED CAP_UV_TILED
}; };
static PackedVector3Array slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const Plane &local_plane, Ref<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const Ref<StandardMaterial3D> cap_material); static PackedVector3Array slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const AABB &original_aabb, const Plane &local_plane, Ref<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const TypedArray<Material> &cap_materials);
protected: protected:
enum MeshSlicePlaneOrientation enum MeshSlicePlaneOrientation
@@ -85,7 +85,7 @@ private:
static SkinnedSurfaces get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton = nullptr, std::vector<std::vector<Transform3D>> &bone_transforms = std::vector<std::vector<Transform3D>>()); static SkinnedSurfaces get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton = nullptr, std::vector<std::vector<Transform3D>> &bone_transforms = std::vector<std::vector<Transform3D>>());
static const Transform3D project_edges(std::vector<MeshEditEdge2D> &out_2d_edges, const Transform3D &to_node_space, const std::vector<MeshEditEdge3D> &in_3d_edges, const Plane &plane); static const Transform3D project_edges(std::vector<MeshEditEdge2D> &out_2d_edges, const std::vector<MeshEditEdge3D> &in_3d_edges, const Plane &plane);
static void build_2d_polygons_from_edges(std::vector<MeshEditPolygon2D> &out_polygons, const std::vector<MeshEditEdge2D> &in_edges, std::vector<MeshEditPolygon2D> &error_polygons); static void build_2d_polygons_from_edges(std::vector<MeshEditPolygon2D> &out_polygons, const std::vector<MeshEditEdge2D> &in_edges, std::vector<MeshEditPolygon2D> &error_polygons);
static bool find_next_edge(MeshEditEdge2D &out_next_edge, std::vector<MeshEditEdge2D> &in_edge_set, const MeshEditVert2D &start); static bool find_next_edge(MeshEditEdge2D &out_next_edge, std::vector<MeshEditEdge2D> &in_edge_set, const MeshEditVert2D &start);
static void fix_polygon_winding(MeshEditPolygon2D &polygon); static void fix_polygon_winding(MeshEditPolygon2D &polygon);