From 6e508ccde2ed122992f44adc4fa6d52108ec9902 Mon Sep 17 00:00:00 2001 From: Jamie Greunbaum Date: Sun, 27 Sep 2026 17:36:49 -0400 Subject: [PATCH] - slice_mesh now supports interpolating custom Float32 data arrays. - get_skinned_vertex_positions now uses Ref instead of a pointer. --- src/liborng/nodes/mesh_editing_library.cpp | 101 +++++++++++++++++---- src/liborng/nodes/mesh_editing_library.h | 2 +- 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/liborng/nodes/mesh_editing_library.cpp b/src/liborng/nodes/mesh_editing_library.cpp index ecc5474..db61589 100644 --- a/src/liborng/nodes/mesh_editing_library.cpp +++ b/src/liborng/nodes/mesh_editing_library.cpp @@ -24,7 +24,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms"); - const Mesh *original_mesh = original_mesh_instance->get_mesh().ptr(); + const Ref original_mesh = original_mesh_instance->get_mesh(); const uint8_t num_surfaces = original_mesh->get_surface_count(); PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Got skinned vertices at ", time->get_ticks_msec(), "ms"); @@ -38,6 +38,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::vector surface_has_colour; surface_has_colour.resize(num_surfaces); std::vector surface_has_bone; surface_has_bone.resize(num_surfaces); std::vector surface_has_weight; surface_has_weight.resize(num_surfaces); + std::vector surface_has_custom0; surface_has_custom0.resize(num_surfaces); std::vector surface_bone_array_size; surface_bone_array_size.resize(num_surfaces); std::vector surface_num_bones_per_vertex; surface_num_bones_per_vertex.resize(num_surfaces); @@ -50,6 +51,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::vector first_half_colours; first_half_colours.resize(num_surfaces); std::vector first_half_bones; first_half_bones.resize(num_surfaces); std::vector first_half_weights; first_half_weights.resize(num_surfaces); + std::vector first_half_custom0; first_half_custom0.resize(num_surfaces); std::vector other_half_vertices; other_half_vertices.resize(num_surfaces); std::vector other_half_normals; other_half_normals.resize(num_surfaces); @@ -59,6 +61,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::vector other_half_colours; other_half_colours.resize(num_surfaces); std::vector other_half_bones; other_half_bones.resize(num_surfaces); std::vector other_half_weights; other_half_weights.resize(num_surfaces); + std::vector other_half_custom0; other_half_custom0.resize(num_surfaces); std::vector first_half_indices; first_half_indices.resize(num_surfaces); std::vector other_half_indices; other_half_indices.resize(num_surfaces); @@ -82,6 +85,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ const PackedColorArray &surface_colour_array = surface_arrays[ArrayMesh::ARRAY_COLOR]; const PackedInt32Array &surface_bone_array = surface_arrays[ArrayMesh::ARRAY_BONES]; const PackedFloat32Array &surface_weight_array = surface_arrays[ArrayMesh::ARRAY_WEIGHTS]; + const PackedFloat32Array &surface_custom0_array = surface_arrays[ArrayMesh::ARRAY_CUSTOM0]; const Vector3 *surface_vertex_array_ptr = surface_vertex_array.ptr(); const uint32_t num_vertices = surface_vertex_array.size(); @@ -92,18 +96,23 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::map base_to_sliced_vert_index; std::map base_to_other_sliced_vert_index; - const bool has_normal = surface_normal_array.size() >= num_vertices; surface_has_normal[surface] = has_normal; - const bool has_tangent = surface_tangent_array.size() >= num_vertices * 4; surface_has_tangent[surface] = has_tangent; - const bool has_uv = surface_uv_array.size() >= num_vertices; surface_has_uv[surface] = has_uv; - const bool has_uv2 = surface_uv2_array.size() >= num_vertices; surface_has_uv2[surface] = has_uv2; - const bool has_colour = surface_colour_array.size() >= num_vertices; surface_has_colour[surface] = has_colour; - const bool has_bone = surface_bone_array.size() >= num_vertices * 4; surface_has_bone[surface] = has_bone; - const bool has_weight = surface_weight_array.size() >= num_vertices * 4; surface_has_weight[surface] = has_weight; + const int64_t &original_mesh_format_mask = (int64_t)original_mesh->surface_get_format(surface); - const uint32_t bone_array_size = surface_bone_array.size(); - surface_bone_array_size[surface] = bone_array_size; + const bool has_normal = surface_normal_array.size() >= num_vertices; surface_has_normal[surface] = has_normal; + const bool has_tangent = surface_tangent_array.size() >= num_vertices * 4; surface_has_tangent[surface] = has_tangent; + const bool has_uv = surface_uv_array.size() >= num_vertices; surface_has_uv[surface] = has_uv; + const bool has_uv2 = surface_uv2_array.size() >= num_vertices; surface_has_uv2[surface] = has_uv2; + const bool has_colour = surface_colour_array.size() >= num_vertices; surface_has_colour[surface] = has_colour; + const bool has_bone = original_mesh_format_mask & Mesh::ARRAY_FORMAT_BONES; surface_has_bone[surface] = has_bone; + const bool has_weight = original_mesh_format_mask & Mesh::ARRAY_FORMAT_WEIGHTS; surface_has_weight[surface] = has_weight; + const bool has_custom0 = original_mesh_format_mask & Mesh::ARRAY_FORMAT_CUSTOM0; surface_has_custom0[surface] = has_custom0; - const uint8_t num_bones_per_vertex = surface_bone_array_size[surface] / num_vertices; + const uint8_t num_custom0_per_vertex = has_custom0 ? ( + ((original_mesh_format_mask & (Mesh::ARRAY_FORMAT_CUSTOM_MASK << Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT)) == + (Mesh::ARRAY_CUSTOM_RGBA_FLOAT << Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT)) ? 4 : 2 ) : 0; + + const uint8_t num_bones_per_vertex = (has_bone && has_weight) ? ( + (original_mesh_format_mask & Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 8 : 4 ) : 0; surface_num_bones_per_vertex[surface] = num_bones_per_vertex; for (uint32_t vertex = 0; vertex < num_vertices; vertex++) @@ -126,6 +135,13 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ first_half_tangents[surface].append(surface_tangent_array.ptr()[(vertex * 4) + 2]); first_half_tangents[surface].append(surface_tangent_array.ptr()[(vertex * 4) + 3]); } + if (has_custom0) + { + for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + { + first_half_custom0[surface].append(surface_custom0_array.ptr()[(vertex * num_custom0_per_vertex) + i]); + } + } if (has_bone) { for (uint8_t i = 0; i < num_bones_per_vertex; i++) @@ -151,6 +167,13 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ other_half_tangents[surface].append(surface_tangent_array.ptr()[(vertex * 4) + 2]); other_half_tangents[surface].append(surface_tangent_array.ptr()[(vertex * 4) + 3]); } + if (has_custom0) + { + for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + { + other_half_custom0[surface].append(surface_custom0_array.ptr()[(vertex * num_custom0_per_vertex) + i]); + } + } if (has_bone) { for (uint8_t i = 0; i < num_bones_per_vertex; i++) @@ -316,6 +339,19 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ other_half_uv2s[surface].append(interp_uv2); } + if (has_custom0) + { + for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + { + const float &interp_custom0 = UtilityFunctions::lerpf( + surface_custom0_array.ptr()[(base_v[this_vert] * num_custom0_per_vertex) + i], + surface_custom0_array.ptr()[(base_v[next_vert] * num_custom0_per_vertex) + i], + alpha); + first_half_custom0[surface].append(interp_custom0); + other_half_custom0[surface].append(interp_custom0); + } + } + if (has_colour) { const Color &interp_colour = surface_colour_array.ptr()[base_v[this_vert]].lerp(surface_colour_array.ptr()[base_v[next_vert]], alpha); @@ -430,6 +466,17 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ } } + int64_t array_format_bit_mask = Mesh::ARRAY_FORMAT_VERTEX; + if (has_normal) array_format_bit_mask |= Mesh::ARRAY_FORMAT_NORMAL; + if (has_tangent) array_format_bit_mask |= Mesh::ARRAY_FORMAT_TANGENT; + if (has_uv) array_format_bit_mask |= Mesh::ARRAY_FORMAT_TEX_UV; + if (has_uv2) array_format_bit_mask |= Mesh::ARRAY_FORMAT_TEX_UV2; + if (has_colour) array_format_bit_mask |= Mesh::ARRAY_FORMAT_COLOR; + if (has_bone) array_format_bit_mask |= Mesh::ARRAY_FORMAT_BONES; + if (has_weight) array_format_bit_mask |= Mesh::ARRAY_FORMAT_WEIGHTS; + if (has_custom0) array_format_bit_mask |= (Mesh::ARRAY_FORMAT_CUSTOM0 | (Mesh::ARRAY_CUSTOM_RG_FLOAT << Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT)); + BitField array_format(array_format_bit_mask); + if (first_half_vertices[surface].size() > 0 && first_half_indices[surface].size() > 0) { Array first_half_section; @@ -442,10 +489,11 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ if (has_colour) first_half_section[ArrayMesh::ARRAY_COLOR] = first_half_colours[surface]; if (has_bone) first_half_section[ArrayMesh::ARRAY_BONES] = first_half_bones[surface]; if (has_weight) first_half_section[ArrayMesh::ARRAY_WEIGHTS] = first_half_weights[surface]; + if (has_custom0) first_half_section[ArrayMesh::ARRAY_CUSTOM0] = first_half_custom0[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, Array(), Dictionary(), array_format_bit_mask); out_first_half->surface_set_material(next_surface, original_material); } @@ -461,10 +509,11 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ if (has_colour) other_half_section[ArrayMesh::ARRAY_COLOR] = other_half_colours[surface]; if (has_bone) other_half_section[ArrayMesh::ARRAY_BONES] = other_half_bones[surface]; if (has_weight) other_half_section[ArrayMesh::ARRAY_WEIGHTS] = other_half_weights[surface]; + if (has_custom0) other_half_section[ArrayMesh::ARRAY_CUSTOM0] = other_half_custom0[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, Array(), Dictionary(), array_format_bit_mask); out_other_half->surface_set_material(next_surface, original_material); } @@ -490,9 +539,13 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ SurfaceTool *surface_tool_first_half = memnew(SurfaceTool); SurfaceTool *surface_tool_other_half = memnew(SurfaceTool); + surface_tool_first_half->begin(Mesh::PRIMITIVE_TRIANGLES); surface_tool_other_half->begin(Mesh::PRIMITIVE_TRIANGLES); + surface_tool_first_half->set_custom_format(0, SurfaceTool::CUSTOM_RG_FLOAT); + surface_tool_other_half->set_custom_format(0, SurfaceTool::CUSTOM_RG_FLOAT); + std::vector edges_2d; std::vector polygon_set; std::vector error_polygons; @@ -529,6 +582,16 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ surface_tool_other_half->set_uv2(uv); } + if (surface_has_custom0[vertex.surface]) + { + const Color &custom_uv3 = Color( + first_half_custom0[vertex.surface][(vertex.index * 2)], + first_half_custom0[vertex.surface][(vertex.index * 2) + 1], + 0.0f, 0.0f); + surface_tool_first_half->set_custom(0, custom_uv3); + surface_tool_other_half->set_custom(0, custom_uv3); + } + if (surface_has_colour[vertex.surface]) { const Color &colour = first_half_colours[vertex.surface][vertex.index]; @@ -589,15 +652,15 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ surface_tool_first_half->generate_normals(); surface_tool_other_half->generate_normals(); - // surface_tool_first_half->generate_tangents(); - // surface_tool_other_half->generate_tangents(); + surface_tool_first_half->generate_tangents(); + surface_tool_other_half->generate_tangents(); + + surface_tool_first_half->set_material(cap_materials[uv_plane]); + surface_tool_other_half->set_material(cap_materials[uv_plane]); out_first_half = surface_tool_first_half->commit(out_first_half); out_other_half = surface_tool_other_half->commit(out_other_half); - out_first_half->surface_set_material(out_first_half->get_surface_count()-1, cap_materials[uv_plane]); - out_other_half->surface_set_material(out_other_half->get_surface_count()-1, cap_materials[uv_plane]); - PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Created cap surfaces at ", time->get_ticks_msec(), "ms"); } @@ -606,7 +669,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ return impact_points; } -SkinnedVertices MeshEditingLibrary::get_skinned_vertex_positions(const uint8_t surface, const Mesh *mesh, const Skeleton3D *skeleton, std::vector &vertex_transforms) +SkinnedVertices MeshEditingLibrary::get_skinned_vertex_positions(const uint8_t surface, const Ref mesh, const Skeleton3D *skeleton, std::vector &vertex_transforms) { const uint8_t num_surfaces = mesh->get_surface_count(); if (surface > num_surfaces) diff --git a/src/liborng/nodes/mesh_editing_library.h b/src/liborng/nodes/mesh_editing_library.h index b71c113..e411c6f 100644 --- a/src/liborng/nodes/mesh_editing_library.h +++ b/src/liborng/nodes/mesh_editing_library.h @@ -83,7 +83,7 @@ protected: private: static const Vector2 calculate_planar_uv(const Vector3 &vertex, const Vector3 &mesh_bounds, const MeshSlicePlaneOrientation &axis); - static SkinnedVertices get_skinned_vertex_positions(const uint8_t surface, const Mesh *mesh, const Skeleton3D *skeleton = nullptr, std::vector &bone_transforms = std::vector()); + static SkinnedVertices get_skinned_vertex_positions(const uint8_t surface, const Ref mesh, const Skeleton3D *skeleton = nullptr, std::vector &bone_transforms = std::vector()); static const Transform3D project_edges(std::vector &out_2d_edges, const std::vector &in_3d_edges, const Plane &plane); static void build_2d_polygons_from_edges(std::vector &out_polygons, const std::vector &in_edges, std::vector &error_polygons);