Slice performance improved by setting time limits on loops.

This commit is contained in:
2026-10-02 00:26:44 -04:00
parent 4fd24f03a1
commit 4e0b756000
5 changed files with 90 additions and 39 deletions
+36 -12
View File
@@ -16,14 +16,19 @@
void IDamageable::_slice_meshes(Ref<MeshEditSliceInput> data)
{
this->_is_slicing = true;
this->_input_queue.emplace_back(data);
if (this->_slice_state_queue.empty())
this->_new_slice_loop();
if (this->_validate_input(data))
{
this->_input_queue.emplace_back(data);
if (this->_slice_state_queue.empty())
this->_new_slice_loop();
}
}
void IDamageable::_new_slice_loop()
{
this->_slice_state_queue.emplace_back(MeshEditingLibrary::slice_mesh(this->_input_queue.front()));
Ref<MeshEditSliceInput> next_in_queue = this->_input_queue.front();
Ref<MeshSliceState> new_state = MeshEditingLibrary::slice_mesh(next_in_queue);
this->_slice_state_queue.emplace_back(new_state);
this->_slice_loop();
}
@@ -33,17 +38,17 @@ void IDamageable::_slice_loop()
switch(current_state->current_stage)
{
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_INIT:
MeshEditingLibrary::slice_mesh_init(current_state);
break;
if (MeshEditingLibrary::slice_mesh_init(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
break;
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_PLANE_SPLIT:
MeshEditingLibrary::slice_mesh_plane_split(current_state);
break;
if (MeshEditingLibrary::slice_mesh_plane_split(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
break;
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_EDGE_SPLIT:
MeshEditingLibrary::slice_mesh_edge_split(current_state);
break;
if (MeshEditingLibrary::slice_mesh_edge_split(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
break;
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_APPLY_CAP:
MeshEditingLibrary::slice_mesh_apply_cap(current_state);
break;
if (MeshEditingLibrary::slice_mesh_apply_cap(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
break;
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_COMPLETE:
this->_slice_complete(current_state->output);
this->_input_queue.erase(this->_input_queue.begin());
@@ -58,3 +63,22 @@ void IDamageable::_slice_loop()
else
this->_is_slicing = false;
}
bool IDamageable::_validate_input(Ref<MeshEditSliceInput> input)
{
if (this->_input_queue.size() >= MAX_SLICE_QUEUE_SIZE)
{
return false;
}
for (Ref<MeshEditSliceInput> &queued_input : this->_input_queue)
{
if (queued_input->skeleton == input->skeleton)
{
return false;
}
}
return true;
}
+4
View File
@@ -12,6 +12,8 @@
#include "godot_cpp/classes/node.hpp"
using namespace godot;
#define MAX_SLICE_QUEUE_SIZE 3
class IDamageable : public Node3D
{
@@ -27,6 +29,8 @@ private:
void _new_slice_loop();
void _slice_loop();
bool _validate_input(Ref<MeshEditSliceInput> input);
bool _is_slicing = false;
std::vector<Ref<MeshSliceState>> _slice_state_queue;
@@ -132,8 +132,8 @@ void Character3D::_slice_complete(Ref<MeshEditSliceOutput> data)
if (other_half_meshes_to_add.size() > 0)
{
RandomNumberGenerator *rng = memnew(RandomNumberGenerator);
const float random_x = rng->randf_range(-0.05f, 0.05f);
const float random_z = rng->randf_range(-0.05f, 0.05f);
const float random_x = rng->randf_range(-0.01f, 0.01f);
const float random_z = rng->randf_range(-0.01f, 0.01f);
CharacterSkeleton3D *new_character_skeleton = cast_to<CharacterSkeleton3D>(this->character_skeleton->duplicate());
this->character_skeleton->add_sibling(new_character_skeleton);
+42 -21
View File
@@ -31,18 +31,17 @@ Ref<MeshSliceState> MeshEditingLibrary::slice_mesh(const Ref<MeshEditSliceInput>
return fresh_state;
}
void MeshEditingLibrary::slice_mesh_init(Ref<MeshSliceState> state)
float MeshEditingLibrary::slice_mesh_init(Ref<MeshSliceState> state)
{
const Time *time = Time::get_singleton();
const float start_time = time->get_ticks_msec();
{ // Initialise the state here
// const Time *time = Time::get_singleton();
// PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms");
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms");
state->original_mesh = state->input->mesh_instance->get_mesh();
state->num_surfaces = state->original_mesh->get_surface_count();
// PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Got skinned vertices at ", time->get_ticks_msec(), "ms");
state->surface_arrays_list.resize(state->num_surfaces);
state->skinned_vertex_positions.resize(state->num_surfaces);
state->skinned_vertex_transforms.resize(state->num_surfaces);
@@ -90,7 +89,8 @@ void MeshEditingLibrary::slice_mesh_init(Ref<MeshSliceState> state)
for (state->surface; state->surface < state->num_surfaces; state->surface++)
{
state->skinned_vertex_positions[state->surface] = MeshEditingLibrary::get_skinned_vertex_positions(state->surface, state->original_mesh, state->input->skeleton, state->skinned_vertex_transforms[state->surface]);
// if ((time->get_ticks_msec() - start_time) > MESH_EDITING_SLICE_LOOP_LIMIT)
// return time->get_ticks_msec() - start_time;
state->surface_arrays_list[state->surface] = state->original_mesh->surface_get_arrays(state->surface);
const PackedVector3Array &surface_vertex_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_VERTEX];
@@ -127,15 +127,24 @@ void MeshEditingLibrary::slice_mesh_init(Ref<MeshSliceState> state)
state->num_custom0_per_vertex[state->surface] = surface_num_custom0_per_vertex;
state->vertex_distances[state->surface].resize(num_vertices);
state->skinned_vertex_positions[state->surface] = MeshEditingLibrary::get_skinned_vertex_positions(state->surface, state->original_mesh, state->input->skeleton, state->skinned_vertex_transforms[state->surface]);
}
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Got skinned vertices at ", time->get_ticks_msec(), "ms");
state->surface = 0;
state->element = 0;
state->current_stage = MeshEditSliceStage::SLICE_STAGE_PLANE_SPLIT;
return time->get_ticks_msec() - start_time;
}
void MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
float MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
{
const Time *time = Time::get_singleton();
const float start_time = time->get_ticks_msec();
for (state->surface; state->surface < state->num_surfaces; state->surface++)
{
const PackedVector3Array &surface_vertex_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_VERTEX];
@@ -170,6 +179,9 @@ void MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
for (state->element; state->element < num_vertices; state->element++)
{
if ((time->get_ticks_msec() - start_time) > MESH_EDITING_SLICE_LOOP_LIMIT)
return time->get_ticks_msec() - start_time;
vertex_distances[state->element] = state->input->local_plane.distance_to(state->skinned_vertex_positions[state->surface][state->element]);
if (vertex_distances[state->element] >= 0.0f)
@@ -246,7 +258,7 @@ void MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
}
}
// PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " sorted by plane distance at ", time->get_ticks_msec(), "ms");
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", state->surface, " sorted by plane distance at ", time->get_ticks_msec(), "ms");
state->element = 0;
}
@@ -255,14 +267,17 @@ void MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
state->surface = 0;
state->current_stage = MeshEditSliceStage::SLICE_STAGE_EDGE_SPLIT;
return time->get_ticks_msec() - start_time;
}
void MeshEditingLibrary::slice_mesh_edge_split(Ref<MeshSliceState> state)
float MeshEditingLibrary::slice_mesh_edge_split(Ref<MeshSliceState> state)
{
const Time *time = Time::get_singleton();
const float start_time = time->get_ticks_msec();
for (state->surface; state->surface < state->num_surfaces; state->surface++)
{
Ref<Material> original_material = state->original_mesh->surface_get_material(state->surface);
const PackedVector3Array &surface_vertex_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_VERTEX];
const PackedVector3Array &surface_normal_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_NORMAL];
const PackedFloat32Array &surface_tangent_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_TANGENT];
@@ -307,6 +322,9 @@ void MeshEditingLibrary::slice_mesh_edge_split(Ref<MeshSliceState> state)
const uint32_t num_triangles = surface_index_array.size();
for (state->element; state->element < num_triangles; state->element += 3)
{
if ((time->get_ticks_msec() - start_time) > MESH_EDITING_SLICE_LOOP_LIMIT)
return time->get_ticks_msec() - start_time;
uint32_t base_v[3];
std::map<uint32_t, uint32_t>::iterator sliced_v[3];
std::map<uint32_t, uint32_t>::iterator sliced_other_v[3];
@@ -570,6 +588,8 @@ void MeshEditingLibrary::slice_mesh_edge_split(Ref<MeshSliceState> state)
state->element = 0;
}
Ref<Material> original_material = state->original_mesh->surface_get_material(state->surface);
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;
@@ -621,28 +641,29 @@ void MeshEditingLibrary::slice_mesh_edge_split(Ref<MeshSliceState> state)
state->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 ", state->surface, " split edges at ", time->get_ticks_msec(), "ms");
}
state->surface = 0;
state->current_stage = MeshEditSliceStage::SLICE_STAGE_APPLY_CAP;
return time->get_ticks_msec() - start_time;
}
void MeshEditingLibrary::slice_mesh_apply_cap(Ref<MeshSliceState> state)
float MeshEditingLibrary::slice_mesh_apply_cap(Ref<MeshSliceState> state)
{
const Time *time = Time::get_singleton();
const float start_time = time->get_ticks_msec();
if (state->clip_edges.size() > 0)
{
MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z;
const Basis &mesh_instance_basis = state->input->mesh_instance->get_basis();
const Vector3 &local_plane_normal = state->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;
}
else if (UtilityFunctions::absf(local_plane_normal.dot(mesh_instance_basis.xform(Vector3(1.0f, 0.0f, 0.0f)))) > 0.5f)
{
uv_plane = MeshSlicePlaneOrientation::X;
}
SurfaceTool *surface_tool_first_half = memnew(SurfaceTool);
SurfaceTool *surface_tool_other_half = memnew(SurfaceTool);
@@ -770,17 +791,17 @@ void MeshEditingLibrary::slice_mesh_apply_cap(Ref<MeshSliceState> state)
memdelete(surface_tool_first_half);
memdelete(surface_tool_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");
PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Generated final cap surface at ", time->get_ticks_msec(), "ms");
state->output->original_skeleton = state->input->skeleton;
state->output->main_half = state->first_half;
state->output->secondary_half = state->other_half;
state->current_stage = MeshEditSliceStage::SLICE_STAGE_COMPLETE;
return time->get_ticks_msec() - start_time;
}
+6 -4
View File
@@ -18,6 +18,8 @@ using namespace godot;
#include <map>
#include <vector>
#define MESH_EDITING_SLICE_LOOP_LIMIT 5.555555555555555f
#define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary"
typedef PackedVector3Array SkinnedVertices;
@@ -87,10 +89,10 @@ public:
static Ref<class MeshSliceState> slice_mesh(const Ref<class MeshEditSliceInput> input);
static void slice_mesh_init(Ref<class MeshSliceState> state);
static void slice_mesh_plane_split(Ref<class MeshSliceState> state);
static void slice_mesh_edge_split(Ref<class MeshSliceState> state);
static void slice_mesh_apply_cap(Ref<class MeshSliceState> state);
static float slice_mesh_init(Ref<class MeshSliceState> state);
static float slice_mesh_plane_split(Ref<class MeshSliceState> state);
static float slice_mesh_edge_split(Ref<class MeshSliceState> state);
static float slice_mesh_apply_cap(Ref<class MeshSliceState> state);
protected:
enum MeshSlicePlaneOrientation