diff --git a/src/liborng/interfaces/i_damageable.cpp b/src/liborng/interfaces/i_damageable.cpp index b06ecc2..8b59532 100644 --- a/src/liborng/interfaces/i_damageable.cpp +++ b/src/liborng/interfaces/i_damageable.cpp @@ -16,14 +16,19 @@ void IDamageable::_slice_meshes(Ref 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 next_in_queue = this->_input_queue.front(); + Ref 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 input) +{ + if (this->_input_queue.size() >= MAX_SLICE_QUEUE_SIZE) + { + return false; + } + + for (Ref &queued_input : this->_input_queue) + { + if (queued_input->skeleton == input->skeleton) + { + return false; + } + } + + return true; +} diff --git a/src/liborng/interfaces/i_damageable.h b/src/liborng/interfaces/i_damageable.h index 735b9b3..bb097db 100644 --- a/src/liborng/interfaces/i_damageable.h +++ b/src/liborng/interfaces/i_damageable.h @@ -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 input); + bool _is_slicing = false; std::vector> _slice_state_queue; diff --git a/src/liborng/nodes/character_nodes/character_3d.cpp b/src/liborng/nodes/character_nodes/character_3d.cpp index dc52176..2251faf 100644 --- a/src/liborng/nodes/character_nodes/character_3d.cpp +++ b/src/liborng/nodes/character_nodes/character_3d.cpp @@ -132,8 +132,8 @@ void Character3D::_slice_complete(Ref 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(this->character_skeleton->duplicate()); this->character_skeleton->add_sibling(new_character_skeleton); diff --git a/src/liborng/nodes/mesh_editing_library.cpp b/src/liborng/nodes/mesh_editing_library.cpp index c9fc234..69bd558 100644 --- a/src/liborng/nodes/mesh_editing_library.cpp +++ b/src/liborng/nodes/mesh_editing_library.cpp @@ -31,18 +31,17 @@ Ref MeshEditingLibrary::slice_mesh(const Ref return fresh_state; } -void MeshEditingLibrary::slice_mesh_init(Ref state) +float MeshEditingLibrary::slice_mesh_init(Ref 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 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 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 state) +float MeshEditingLibrary::slice_mesh_plane_split(Ref 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 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 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 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 state) +float MeshEditingLibrary::slice_mesh_edge_split(Ref 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 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 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::iterator sliced_v[3]; std::map::iterator sliced_other_v[3]; @@ -570,6 +588,8 @@ void MeshEditingLibrary::slice_mesh_edge_split(Ref state) state->element = 0; } + Ref 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 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 state) +float MeshEditingLibrary::slice_mesh_apply_cap(Ref 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 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; } diff --git a/src/liborng/nodes/mesh_editing_library.h b/src/liborng/nodes/mesh_editing_library.h index d085f11..2a4854f 100644 --- a/src/liborng/nodes/mesh_editing_library.h +++ b/src/liborng/nodes/mesh_editing_library.h @@ -18,6 +18,8 @@ using namespace godot; #include #include +#define MESH_EDITING_SLICE_LOOP_LIMIT 5.555555555555555f + #define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary" typedef PackedVector3Array SkinnedVertices; @@ -87,10 +89,10 @@ public: static Ref slice_mesh(const Ref input); - static void slice_mesh_init(Ref state); - static void slice_mesh_plane_split(Ref state); - static void slice_mesh_edge_split(Ref state); - static void slice_mesh_apply_cap(Ref state); + static float slice_mesh_init(Ref state); + static float slice_mesh_plane_split(Ref state); + static float slice_mesh_edge_split(Ref state); + static float slice_mesh_apply_cap(Ref state); protected: enum MeshSlicePlaneOrientation