From 223eaf2f3269418d18bba7f15ff2fb244a6cf9b0 Mon Sep 17 00:00:00 2001 From: Jamie Greunbaum Date: Tue, 29 Sep 2026 04:18:34 -0400 Subject: [PATCH] Reworked slicing code in various ways: - slice_mesh takes an input struct, and returns all data in an output struct. - Separated loops to ease the possibility of making them deferred functions. --- .../nodes/character_nodes/character_3d.cpp | 28 +-- src/liborng/nodes/mesh_editing_library.cpp | 200 ++++++++++++------ src/liborng/nodes/mesh_editing_library.h | 44 +++- src/liborng/register_types.cpp | 2 + 4 files changed, 189 insertions(+), 85 deletions(-) diff --git a/src/liborng/nodes/character_nodes/character_3d.cpp b/src/liborng/nodes/character_nodes/character_3d.cpp index d2c0719..607ba24 100644 --- a/src/liborng/nodes/character_nodes/character_3d.cpp +++ b/src/liborng/nodes/character_nodes/character_3d.cpp @@ -72,26 +72,30 @@ void Character3D::_next_hurtbox_in_queue() TypedArray other_half_meshes_to_add; for (uint32_t i = 0; i < num_mesh_instances; i++) { - MeshInstance3D *original_mesh_instance = sliced_mesh_instances[i]; - Ref first_half; first_half.instantiate(); - Ref other_half; other_half.instantiate(); - PackedVector3Array &impact_points = MeshEditingLibrary::slice_mesh(original_mesh_instance, skeleton, this->_full_aabb, local_slice_plane, first_half, other_half, MeshEditingLibrary::CAP_UV_FILL_MESH_BOUNDS, this->inner_materials); + Ref input; input.instantiate(); + input->sliceable_mesh_instance = sliced_mesh_instances[i]; + input->sliceable_skeleton = skeleton; + input->original_aabb = this->_full_aabb; + input->local_plane = local_slice_plane; + input->cap_option = MeshEditingLibrary::CAP_UV_FILL_MESH_BOUNDS; + input->cap_materials = this->inner_materials; + Ref output = MeshEditingLibrary::slice_mesh(input); - if (first_half->get_surface_count() <= 0 && other_half->get_surface_count() > 0) + if (output->main_half->get_surface_count() <= 0 && output->secondary_half->get_surface_count() > 0) { - Ref temp = first_half; - first_half = other_half; - other_half = temp; + Ref temp = output->main_half; + output->main_half = output->secondary_half; + output->secondary_half = temp; } - if (first_half->get_surface_count() > 0) + if (output->main_half->get_surface_count() > 0) { - first_half_meshes_to_add.append(first_half); + first_half_meshes_to_add.append(output->main_half); } - if (other_half->get_surface_count() > 0) + if (output->secondary_half->get_surface_count() > 0) { - other_half_meshes_to_add.append(other_half); + other_half_meshes_to_add.append(output->secondary_half); } } diff --git a/src/liborng/nodes/mesh_editing_library.cpp b/src/liborng/nodes/mesh_editing_library.cpp index db61589..65bfb08 100644 --- a/src/liborng/nodes/mesh_editing_library.cpp +++ b/src/liborng/nodes/mesh_editing_library.cpp @@ -18,18 +18,25 @@ using namespace godot; -PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const AABB &original_aabb, const Plane &local_plane, Ref out_first_half, Ref out_other_half, const MeshEditCapUV cap_option, const TypedArray &cap_materials) +Ref MeshEditingLibrary::slice_mesh(const Ref input) { + Ref out; out.instantiate(); + + Ref first_half; first_half.instantiate(); + Ref other_half; other_half.instantiate(); + const Time *time = Time::get_singleton(); PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms"); - const Ref original_mesh = original_mesh_instance->get_mesh(); + const Ref original_mesh = input->sliceable_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"); - PackedVector3Array impact_points; + std::vector surface_arrays_list; surface_arrays_list.resize(num_surfaces); + std::vector skinned_vertex_positions; skinned_vertex_positions.resize(num_surfaces); + std::vector> skinned_vertex_transforms; skinned_vertex_transforms.resize(num_surfaces); std::vector surface_has_normal; surface_has_normal.resize(num_surfaces); std::vector surface_has_tangent; surface_has_tangent.resize(num_surfaces); @@ -40,8 +47,8 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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); + std::vector num_bones_per_vertex; num_bones_per_vertex.resize(num_surfaces); + std::vector num_custom0_per_vertex; num_custom0_per_vertex.resize(num_surfaces); std::vector first_half_vertices; first_half_vertices.resize(num_surfaces); std::vector first_half_normals; first_half_normals.resize(num_surfaces); @@ -66,15 +73,22 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::vector first_half_indices; first_half_indices.resize(num_surfaces); std::vector other_half_indices; other_half_indices.resize(num_surfaces); - std::vector> skinned_vertex_transforms; + std::vector> vertex_distances; vertex_distances.resize(num_surfaces); + + std::vector> base_to_first_sliced_vert_indices; base_to_first_sliced_vert_indices.resize(num_surfaces); + std::vector> base_to_other_sliced_vert_indices; base_to_other_sliced_vert_indices.resize(num_surfaces); + + uint32_t first_half_split_map = 0x00000000; + uint32_t other_half_split_map = 0x00000000; + std::vector clip_edges; for (uint8_t surface = 0; surface < num_surfaces; surface++) { - Ref original_material = original_mesh->surface_get_material(surface); - std::vector surface_skinned_vertex_transforms; - const SkinnedVertices &surface_skinned_vertex_positions = MeshEditingLibrary::get_skinned_vertex_positions(surface, original_mesh, original_skeleton, surface_skinned_vertex_transforms); + const SkinnedVertices &surface_skinned_vertex_positions = MeshEditingLibrary::get_skinned_vertex_positions(surface, original_mesh, input->sliceable_skeleton, surface_skinned_vertex_transforms); + skinned_vertex_positions[surface] = surface_skinned_vertex_positions; + skinned_vertex_transforms[surface] = surface_skinned_vertex_transforms; const Array &surface_arrays = original_mesh->surface_get_arrays(surface); const PackedVector3Array &surface_vertex_array = surface_arrays[ArrayMesh::ARRAY_VERTEX]; @@ -86,15 +100,16 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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]; + surface_arrays_list[surface] = surface_arrays; const Vector3 *surface_vertex_array_ptr = surface_vertex_array.ptr(); const uint32_t num_vertices = surface_vertex_array.size(); - std::vector vertex_distance; - vertex_distance.resize(num_vertices); + std::map &base_to_first_sliced_vert_index = base_to_first_sliced_vert_indices[surface]; + std::map &base_to_other_sliced_vert_index = base_to_other_sliced_vert_indices[surface]; - std::map base_to_sliced_vert_index; - std::map base_to_other_sliced_vert_index; + std::vector &vertex_distance = vertex_distances[surface]; + vertex_distance.resize(num_vertices); const int64_t &original_mesh_format_mask = (int64_t)original_mesh->surface_get_format(surface); @@ -107,21 +122,22 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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_custom0_per_vertex = has_custom0 ? ( + const uint8_t surface_num_bones_per_vertex = (has_bone && has_weight) ? ( + (original_mesh_format_mask & Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 8 : 4 ) : 0; + num_bones_per_vertex[surface] = surface_num_bones_per_vertex; + + const uint8_t surface_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; + num_custom0_per_vertex[surface] = surface_num_custom0_per_vertex; for (uint32_t vertex = 0; vertex < num_vertices; vertex++) { - vertex_distance[vertex] = local_plane.distance_to(surface_skinned_vertex_positions[vertex]); + vertex_distance[vertex] = input->local_plane.distance_to(surface_skinned_vertex_positions[vertex]); if (vertex_distance[vertex] >= 0.0f) { - base_to_sliced_vert_index[vertex] = first_half_vertices[surface].size(); + base_to_first_sliced_vert_index[vertex] = first_half_vertices[surface].size(); first_half_vertices[surface].append(surface_vertex_array_ptr[vertex]); if (has_normal) { first_half_normals[surface].append(surface_normal_array.ptr()[vertex]); } @@ -137,17 +153,21 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ } if (has_custom0) { - for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + float hit_grid[] = { 0.0f, 0.0f }; + for (uint8_t i = 0; i < surface_num_custom0_per_vertex; i++) { - first_half_custom0[surface].append(surface_custom0_array.ptr()[(vertex * num_custom0_per_vertex) + i]); + const float value = surface_custom0_array.ptr()[(vertex * surface_num_custom0_per_vertex) + i]; + first_half_custom0[surface].append(value); + hit_grid[i] = value; } + first_half_split_map |= (0x00000001 << MeshEditingLibrary::uv_to_body_part_shift(hit_grid[0], hit_grid[1])); } if (has_bone) { - for (uint8_t i = 0; i < num_bones_per_vertex; i++) + for (uint8_t i = 0; i < surface_num_bones_per_vertex; i++) { - first_half_bones[surface].append(surface_bone_array.ptr()[(vertex * num_bones_per_vertex) + i]); - first_half_weights[surface].append(surface_weight_array.ptr()[(vertex * num_bones_per_vertex) + i]); + first_half_bones[surface].append(surface_bone_array.ptr()[(vertex * surface_num_bones_per_vertex) + i]); + first_half_weights[surface].append(surface_weight_array.ptr()[(vertex * surface_num_bones_per_vertex) + i]); } } } @@ -169,25 +189,62 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ } if (has_custom0) { - for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + float hit_grid[] = { 0.0f, 0.0f }; + for (uint8_t i = 0; i < surface_num_custom0_per_vertex; i++) { - other_half_custom0[surface].append(surface_custom0_array.ptr()[(vertex * num_custom0_per_vertex) + i]); + const float value = surface_custom0_array.ptr()[(vertex * surface_num_custom0_per_vertex) + i]; + other_half_custom0[surface].append(value); + hit_grid[i] = value; } + other_half_split_map |= (0x00000001 << MeshEditingLibrary::uv_to_body_part_shift(hit_grid[0], hit_grid[1])); } if (has_bone) { - for (uint8_t i = 0; i < num_bones_per_vertex; i++) + for (uint8_t i = 0; i < surface_num_bones_per_vertex; i++) { - other_half_bones[surface].append(surface_bone_array.ptr()[(vertex * num_bones_per_vertex) + i]); - other_half_weights[surface].append(surface_weight_array.ptr()[(vertex * num_bones_per_vertex) + i]); + other_half_bones[surface].append(surface_bone_array.ptr()[(vertex * surface_num_bones_per_vertex) + i]); + other_half_weights[surface].append(surface_weight_array.ptr()[(vertex * surface_num_bones_per_vertex) + i]); } } } } - const PackedInt32Array &surface_index_array = surface_arrays[ArrayMesh::ARRAY_INDEX]; - PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " sorted by plane distance at ", time->get_ticks_msec(), "ms"); + } + + out->hit_map = first_half_split_map & other_half_split_map; + + for (uint8_t surface = 0; surface < num_surfaces; surface++) + { + Ref original_material = original_mesh->surface_get_material(surface); + + const PackedVector3Array &surface_vertex_array = surface_arrays_list[surface][ArrayMesh::ARRAY_VERTEX]; + const PackedVector3Array &surface_normal_array = surface_arrays_list[surface][ArrayMesh::ARRAY_NORMAL]; + const PackedFloat32Array &surface_tangent_array = surface_arrays_list[surface][ArrayMesh::ARRAY_TANGENT]; + const PackedVector2Array &surface_uv_array = surface_arrays_list[surface][ArrayMesh::ARRAY_TEX_UV]; + const PackedVector2Array &surface_uv2_array = surface_arrays_list[surface][ArrayMesh::ARRAY_TEX_UV2]; + const PackedColorArray &surface_colour_array = surface_arrays_list[surface][ArrayMesh::ARRAY_COLOR]; + const PackedInt32Array &surface_bone_array = surface_arrays_list[surface][ArrayMesh::ARRAY_BONES]; + const PackedFloat32Array &surface_weight_array = surface_arrays_list[surface][ArrayMesh::ARRAY_WEIGHTS]; + const PackedFloat32Array &surface_custom0_array = surface_arrays_list[surface][ArrayMesh::ARRAY_CUSTOM0]; + const PackedInt32Array &surface_index_array = surface_arrays_list[surface][ArrayMesh::ARRAY_INDEX]; + + SkinnedVertices &surface_skinned_vertex_positions = skinned_vertex_positions[surface]; + std::vector &surface_skinned_vertex_transforms = skinned_vertex_transforms[surface]; + + const std::vector &vertex_distance = vertex_distances[surface]; + + const bool has_normal = surface_has_normal[surface]; + const bool has_tangent = surface_has_tangent[surface]; + const bool has_uv = surface_has_uv[surface]; + const bool has_uv2 = surface_has_uv2[surface]; + const bool has_colour = surface_has_colour[surface]; + const bool has_bone = surface_has_bone[surface]; + const bool has_weight = surface_has_weight[surface]; + const bool has_custom0 = surface_has_custom0[surface]; + + const uint8_t &surface_num_bones_per_vertex = num_bones_per_vertex[surface]; + const uint8_t &surface_num_custom0_per_vertex = num_custom0_per_vertex[surface]; if (!(first_half_vertices[surface].size() > 0 && other_half_vertices[surface].size() > 0)) { @@ -209,19 +266,19 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::map::iterator sliced_v[3]; std::map::iterator sliced_other_v[3]; - const std::map::iterator base_to_sliced_end = base_to_sliced_vert_index.end(); - const std::map::iterator base_to_other_sliced_end = base_to_other_sliced_vert_index.end(); + const std::map::iterator base_to_first_sliced_end = base_to_first_sliced_vert_indices[surface].end(); + const std::map::iterator base_to_other_sliced_end = base_to_other_sliced_vert_indices[surface].end(); for (uint32_t i = 0; i < 3; i++) { base_v[i] = surface_index_array.ptr()[triangle_index + i]; - sliced_v[i] = base_to_sliced_vert_index.find(base_v[i]); - sliced_other_v[i] = base_to_other_sliced_vert_index.find(base_v[i]); + sliced_v[i] = base_to_first_sliced_vert_indices[surface].find(base_v[i]); + sliced_other_v[i] = base_to_other_sliced_vert_indices[surface].find(base_v[i]); // All vertex indices must be represented by one of the two slice index maps. - assert((sliced_v[i] != base_to_sliced_vert_index.end()) != (sliced_other_v[i] != base_to_other_sliced_vert_index.end())); + assert((sliced_v[i] != base_to_first_sliced_vert_indices[surface].end()) != (sliced_other_v[i] != base_to_other_sliced_vert_indices[surface].end())); } - if (sliced_v[0] != base_to_sliced_end && sliced_v[1] != base_to_sliced_end && sliced_v[2] != base_to_sliced_end) + if (sliced_v[0] != base_to_first_sliced_end && sliced_v[1] != base_to_first_sliced_end && sliced_v[2] != base_to_first_sliced_end) { // If the triangle is entirely in the first slice, send all the vertices to the first slice. first_half_indices[surface].append(sliced_v[0]->second); first_half_indices[surface].append(sliced_v[1]->second); @@ -252,7 +309,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ for (uint32_t this_vert = 0; this_vert < 3; this_vert++) { - if (sliced_v[this_vert] != base_to_sliced_end) + if (sliced_v[this_vert] != base_to_first_sliced_end) { final_verts[num_final_verts] = sliced_v[this_vert]->second; num_final_verts++; @@ -264,7 +321,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ } uint32_t next_vert = (this_vert + 1) % 3; - if ((sliced_v[this_vert] == base_to_sliced_end) != (sliced_v[next_vert] == base_to_sliced_end)) + if ((sliced_v[this_vert] == base_to_first_sliced_end) != (sliced_v[next_vert] == base_to_first_sliced_end)) { const float alpha = UtilityFunctions::clampf(-plane_distance[this_vert] / (plane_distance[next_vert] - plane_distance[this_vert]), 0.0f, 1.0f); @@ -341,11 +398,11 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ if (has_custom0) { - for (uint8_t i = 0; i < num_custom0_per_vertex; i++) + for (uint8_t i = 0; i < surface_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], + surface_custom0_array.ptr()[(base_v[this_vert] * surface_num_custom0_per_vertex) + i], + surface_custom0_array.ptr()[(base_v[next_vert] * surface_num_custom0_per_vertex) + i], alpha); first_half_custom0[surface].append(interp_custom0); other_half_custom0[surface].append(interp_custom0); @@ -366,10 +423,10 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ // First pack all active bones and weights into a list of pairs uint8_t vertex_bone = 0; - for (vertex_bone = 0; vertex_bone < num_bones_per_vertex; vertex_bone++) + for (vertex_bone = 0; vertex_bone < surface_num_bones_per_vertex; vertex_bone++) { - const int32_t bone = surface_bone_array[(base_v[this_vert] * num_bones_per_vertex) + vertex_bone]; - const float weight = surface_weight_array[(base_v[this_vert] * num_bones_per_vertex) + vertex_bone]; + const int32_t bone = surface_bone_array[(base_v[this_vert] * surface_num_bones_per_vertex) + vertex_bone]; + const float weight = surface_weight_array[(base_v[this_vert] * surface_num_bones_per_vertex) + vertex_bone]; if (weight > TINY_NUMBER) { positive_side_bones_and_weights[bone] = weight; } } @@ -378,10 +435,10 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ // Delete any matches from the first half, leaving only unique bones to add later. std::map negative_side_bones_and_weights; std::vector> bone_weight_pairs; - for (uint32_t other_bone_index = 0; other_bone_index < num_bones_per_vertex; other_bone_index++) + for (uint32_t other_bone_index = 0; other_bone_index < surface_num_bones_per_vertex; other_bone_index++) { - const uint32_t other_bone = surface_bone_array[(base_v[next_vert] * num_bones_per_vertex) + other_bone_index]; - const float other_weight = surface_weight_array[(base_v[next_vert] * num_bones_per_vertex) + other_bone_index]; + const uint32_t other_bone = surface_bone_array[(base_v[next_vert] * surface_num_bones_per_vertex) + other_bone_index]; + const float other_weight = surface_weight_array[(base_v[next_vert] * surface_num_bones_per_vertex) + other_bone_index]; if (negative_side_bones_and_weights.find(other_bone) != negative_side_bones_and_weights.end()) { @@ -419,7 +476,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ [=](std::pair &a, std::pair &b) { return a.second > b.second; }); // Finally, add all our new interpolated bones and weights to the arrays - for (vertex_bone = 0; vertex_bone < num_bones_per_vertex; vertex_bone++) + for (vertex_bone = 0; vertex_bone < surface_num_bones_per_vertex; vertex_bone++) { if (vertex_bone < bone_weight_pairs.size()) { @@ -492,9 +549,9 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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, Array(), Dictionary(), array_format_bit_mask); - out_first_half->surface_set_material(next_surface, original_material); + const uint16_t next_surface = first_half->get_surface_count(); + first_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, first_half_section, Array(), Dictionary(), array_format_bit_mask); + first_half->surface_set_material(next_surface, original_material); } if (other_half_vertices[surface].size() > 0 && other_half_indices[surface].size() > 0) @@ -512,9 +569,9 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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, Array(), Dictionary(), array_format_bit_mask); - out_other_half->surface_set_material(next_surface, original_material); + const uint16_t next_surface = other_half->get_surface_count(); + other_half->add_surface_from_arrays(ArrayMesh::PRIMITIVE_TRIANGLES, other_half_section, Array(), Dictionary(), array_format_bit_mask); + other_half->surface_set_material(next_surface, original_material); } skinned_vertex_transforms.emplace_back(surface_skinned_vertex_transforms); @@ -526,8 +583,8 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ if (clip_edges.size() > 0) { MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z; - const Basis &mesh_instance_basis = original_mesh_instance->get_basis(); - const Vector3 &local_plane_normal = local_plane.get_normal(); + const Basis &mesh_instance_basis = input->sliceable_mesh_instance->get_basis(); + const Vector3 &local_plane_normal = input->local_plane.get_normal(); if (UtilityFunctions::absf(local_plane_normal.dot(mesh_instance_basis.xform(Vector3(0.0f, 1.0f, 0.0f)))) > 0.5f) { uv_plane = MeshSlicePlaneOrientation::Y; @@ -549,11 +606,11 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ std::vector edges_2d; std::vector polygon_set; std::vector error_polygons; - const Transform3D &plane_inverse_transform = MeshEditingLibrary::project_edges(edges_2d, clip_edges, local_plane); + const Transform3D &plane_inverse_transform = MeshEditingLibrary::project_edges(edges_2d, clip_edges, input->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)); + MeshEditingLibrary::draw_debug_polygons(input->sliceable_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 Vector3 &mesh_bounds = input->original_aabb.get_size(); const uint32_t num_polygons = polygon_set.size(); uint32_t polygon_vertex_base = 0; for (uint32_t polygon_index = 0; polygon_index < num_polygons; polygon_index++) @@ -604,10 +661,10 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ PackedInt32Array bones; bones.resize(4); PackedFloat32Array weights; weights.resize(4); - for (uint8_t i = 0; i < surface_num_bones_per_vertex[vertex.surface] && i < 4; i++) + for (uint8_t i = 0; i < num_bones_per_vertex[vertex.surface] && i < 4; i++) { - bones[i] = first_half_bones[vertex.surface][(vertex.index * surface_num_bones_per_vertex[vertex.surface]) + i]; - weights[i] = first_half_weights[vertex.surface][(vertex.index * surface_num_bones_per_vertex[vertex.surface]) + i]; + bones[i] = first_half_bones[vertex.surface][(vertex.index * num_bones_per_vertex[vertex.surface]) + i]; + weights[i] = first_half_weights[vertex.surface][(vertex.index * num_bones_per_vertex[vertex.surface]) + i]; } surface_tool_first_half->set_bones(bones); @@ -627,7 +684,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ } polygon_centroid /= polygon_set[polygon_index].vertices.size(); - impact_points.append(polygon_centroid); + out->impact_points.append(polygon_centroid); earcut_polygon.push_back(sub_polygon); std::vector indices = mapbox::earcut(earcut_polygon); @@ -655,18 +712,21 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_ 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]); + surface_tool_first_half->set_material(input->cap_materials[uv_plane]); + surface_tool_other_half->set_material(input->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); + first_half = surface_tool_first_half->commit(first_half); + other_half = surface_tool_other_half->commit(other_half); PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Created cap surfaces at ", time->get_ticks_msec(), "ms"); } PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Generated final cap surface at ", time->get_ticks_msec(), "ms"); - return impact_points; + out->main_half = first_half; + out->secondary_half = other_half; + + return out; } SkinnedVertices MeshEditingLibrary::get_skinned_vertex_positions(const uint8_t surface, const Ref mesh, const Skeleton3D *skeleton, std::vector &vertex_transforms) diff --git a/src/liborng/nodes/mesh_editing_library.h b/src/liborng/nodes/mesh_editing_library.h index e411c6f..37050af 100644 --- a/src/liborng/nodes/mesh_editing_library.h +++ b/src/liborng/nodes/mesh_editing_library.h @@ -19,7 +19,7 @@ using namespace godot; #define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary" -typedef std::vector SkinnedVertices; +typedef PackedVector3Array SkinnedVertices; typedef std::vector SkinnedSurfaces; @@ -70,7 +70,7 @@ public: CAP_UV_TILED }; - static PackedVector3Array slice_mesh(MeshInstance3D *original_mesh_instance, const Skeleton3D *original_skeleton, const AABB &original_aabb, const Plane &local_plane, Ref out_first_half, Ref out_other_half, const MeshEditCapUV cap_option, const TypedArray &cap_materials); + static Ref slice_mesh(const Ref input); protected: enum MeshSlicePlaneOrientation @@ -85,6 +85,8 @@ private: static SkinnedVertices get_skinned_vertex_positions(const uint8_t surface, const Ref mesh, const Skeleton3D *skeleton = nullptr, std::vector &bone_transforms = std::vector()); + static constexpr const uint8_t uv_to_body_part_shift(const float x, const float y) { return (uint8_t(y * 5.0f) * 5) + uint8_t(x * 5.0f); } + 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); static bool find_next_edge(MeshEditEdge2D &out_next_edge, std::vector &in_edge_set, const MeshEditVert2D &start); @@ -96,7 +98,7 @@ private: protected: static void _bind_methods() { - ClassDB::bind_static_method("MeshEditingLibrary", D_METHOD("slice_mesh", "original_mesh_instance", "original_skeleton", "local_plane", "out_first_half", "out_other_half", "cap_option", "cap_material"), &MeshEditingLibrary::slice_mesh); + ClassDB::bind_static_method("MeshEditingLibrary", D_METHOD("slice_mesh", "input"), &MeshEditingLibrary::slice_mesh); BIND_ENUM_CONSTANT(CAP_UV_FILL_MESH_BOUNDS); BIND_ENUM_CONSTANT(CAP_UV_FILL_CAP_BOUNDS); @@ -104,4 +106,40 @@ protected: } }; + +class MeshEditSliceInput : public RefCounted +{ + GDCLASS(MeshEditSliceInput, RefCounted); + +public: + MeshInstance3D *sliceable_mesh_instance = nullptr; + const Skeleton3D *sliceable_skeleton = nullptr; + AABB original_aabb; + Plane local_plane; + + uint32_t hit_mask = 0b1111111111111111111111111; + + MeshEditingLibrary::MeshEditCapUV cap_option; + TypedArray cap_materials; + +protected: + static void _bind_methods(){} +}; + +class MeshEditSliceOutput : public RefCounted +{ + GDCLASS(MeshEditSliceOutput, RefCounted); + +public: + Ref main_half; + + Ref secondary_half; + + PackedVector3Array impact_points; + uint32_t hit_map = 0b0000000000000000000000000; + +protected: + static void _bind_methods(){} +}; + VARIANT_ENUM_CAST(MeshEditingLibrary::MeshEditCapUV); diff --git a/src/liborng/register_types.cpp b/src/liborng/register_types.cpp index 40472c8..86f57bd 100644 --- a/src/liborng/register_types.cpp +++ b/src/liborng/register_types.cpp @@ -78,6 +78,8 @@ void initialize_orng_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); GDSINGLETON_REGISTER_CLASS(InputHandler, _input_handler_singleton); GDSINGLETON_REGISTER_CLASS(SaveManager, _save_manager_singleton);