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.
This commit is contained in:
2026-09-29 04:19:39 -04:00
parent 6e508ccde2
commit 223eaf2f32
4 changed files with 189 additions and 85 deletions
@@ -72,26 +72,30 @@ void Character3D::_next_hurtbox_in_queue()
TypedArray<ArrayMesh> other_half_meshes_to_add;
for (uint32_t i = 0; i < num_mesh_instances; i++)
{
MeshInstance3D *original_mesh_instance = sliced_mesh_instances[i];
Ref<ArrayMesh> first_half; first_half.instantiate();
Ref<ArrayMesh> 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<MeshEditSliceInput> 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<MeshEditSliceOutput> 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<ArrayMesh> temp = first_half;
first_half = other_half;
other_half = temp;
Ref<ArrayMesh> 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);
}
}
+130 -70
View File
@@ -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<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const TypedArray<Material> &cap_materials)
Ref<MeshEditSliceOutput> MeshEditingLibrary::slice_mesh(const Ref<MeshEditSliceInput> input)
{
Ref<MeshEditSliceOutput> out; out.instantiate();
Ref<ArrayMesh> first_half; first_half.instantiate();
Ref<ArrayMesh> 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<ArrayMesh> original_mesh = original_mesh_instance->get_mesh();
const Ref<ArrayMesh> 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<Array> surface_arrays_list; surface_arrays_list.resize(num_surfaces);
std::vector<SkinnedVertices> skinned_vertex_positions; skinned_vertex_positions.resize(num_surfaces);
std::vector<std::vector<Transform3D>> skinned_vertex_transforms; skinned_vertex_transforms.resize(num_surfaces);
std::vector<bool> surface_has_normal; surface_has_normal.resize(num_surfaces);
std::vector<bool> surface_has_tangent; surface_has_tangent.resize(num_surfaces);
@@ -40,8 +47,8 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
std::vector<bool> surface_has_weight; surface_has_weight.resize(num_surfaces);
std::vector<bool> surface_has_custom0; surface_has_custom0.resize(num_surfaces);
std::vector<uint32_t> surface_bone_array_size; surface_bone_array_size.resize(num_surfaces);
std::vector<uint8_t> surface_num_bones_per_vertex; surface_num_bones_per_vertex.resize(num_surfaces);
std::vector<uint8_t> num_bones_per_vertex; num_bones_per_vertex.resize(num_surfaces);
std::vector<uint8_t> num_custom0_per_vertex; num_custom0_per_vertex.resize(num_surfaces);
std::vector<PackedVector3Array> first_half_vertices; first_half_vertices.resize(num_surfaces);
std::vector<PackedVector3Array> first_half_normals; first_half_normals.resize(num_surfaces);
@@ -66,15 +73,22 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(MeshInstance3D *original_mesh_
std::vector<PackedInt32Array> first_half_indices; first_half_indices.resize(num_surfaces);
std::vector<PackedInt32Array> other_half_indices; other_half_indices.resize(num_surfaces);
std::vector<std::vector<Transform3D>> skinned_vertex_transforms;
std::vector<std::vector<float>> vertex_distances; vertex_distances.resize(num_surfaces);
std::vector<std::map<uint32_t, uint32_t>> base_to_first_sliced_vert_indices; base_to_first_sliced_vert_indices.resize(num_surfaces);
std::vector<std::map<uint32_t, uint32_t>> 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<MeshEditEdge3D> clip_edges;
for (uint8_t surface = 0; surface < num_surfaces; surface++)
{
Ref<Material> original_material = original_mesh->surface_get_material(surface);
std::vector<Transform3D> 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<float> vertex_distance;
vertex_distance.resize(num_vertices);
std::map<uint32_t, uint32_t> &base_to_first_sliced_vert_index = base_to_first_sliced_vert_indices[surface];
std::map<uint32_t, uint32_t> &base_to_other_sliced_vert_index = base_to_other_sliced_vert_indices[surface];
std::map<uint32_t, uint32_t> base_to_sliced_vert_index;
std::map<uint32_t, uint32_t> base_to_other_sliced_vert_index;
std::vector<float> &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<Material> 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<Transform3D> &surface_skinned_vertex_transforms = skinned_vertex_transforms[surface];
const std::vector<float> &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<uint32_t, uint32_t>::iterator sliced_v[3];
std::map<uint32_t, uint32_t>::iterator sliced_other_v[3];
const std::map<uint32_t, uint32_t>::iterator base_to_sliced_end = base_to_sliced_vert_index.end();
const std::map<uint32_t, uint32_t>::iterator base_to_other_sliced_end = base_to_other_sliced_vert_index.end();
const std::map<uint32_t, uint32_t>::iterator base_to_first_sliced_end = base_to_first_sliced_vert_indices[surface].end();
const std::map<uint32_t, uint32_t>::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<int32_t, float> negative_side_bones_and_weights;
std::vector<std::pair<int32_t, float>> 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<int32_t, float> &a, std::pair<int32_t, float> &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<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);
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<uint32_t> indices = mapbox::earcut<uint32_t>(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<ArrayMesh> mesh, const Skeleton3D *skeleton, std::vector<Transform3D> &vertex_transforms)
+41 -3
View File
@@ -19,7 +19,7 @@ using namespace godot;
#define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary"
typedef std::vector<Vector3> SkinnedVertices;
typedef PackedVector3Array SkinnedVertices;
typedef std::vector<SkinnedVertices> 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<ArrayMesh> out_first_half, Ref<ArrayMesh> out_other_half, const MeshEditCapUV cap_option, const TypedArray<Material> &cap_materials);
static Ref<class MeshEditSliceOutput> slice_mesh(const Ref<class MeshEditSliceInput> input);
protected:
enum MeshSlicePlaneOrientation
@@ -85,6 +85,8 @@ private:
static SkinnedVertices get_skinned_vertex_positions(const uint8_t surface, const Ref<ArrayMesh> mesh, const Skeleton3D *skeleton = nullptr, std::vector<Transform3D> &bone_transforms = std::vector<Transform3D>());
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<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 bool find_next_edge(MeshEditEdge2D &out_next_edge, std::vector<MeshEditEdge2D> &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<Material> cap_materials;
protected:
static void _bind_methods(){}
};
class MeshEditSliceOutput : public RefCounted
{
GDCLASS(MeshEditSliceOutput, RefCounted);
public:
Ref<ArrayMesh> main_half;
Ref<ArrayMesh> secondary_half;
PackedVector3Array impact_points;
uint32_t hit_map = 0b0000000000000000000000000;
protected:
static void _bind_methods(){}
};
VARIANT_ENUM_CAST(MeshEditingLibrary::MeshEditCapUV);
+2
View File
@@ -78,6 +78,8 @@ void initialize_orng_module(ModuleInitializationLevel p_level) {
ClassDB::register_class<SaveFileData>();
ClassDB::register_class<MeshEditingLibrary>();
ClassDB::register_class<MeshEditSliceInput>();
ClassDB::register_class<MeshEditSliceOutput>();
GDSINGLETON_REGISTER_CLASS(InputHandler, _input_handler_singleton);
GDSINGLETON_REGISTER_CLASS(SaveManager, _save_manager_singleton);