Slice performance improved by setting time limits on loops.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
{ // Initialise the state here
|
||||
// const Time *time = Time::get_singleton();
|
||||
const Time *time = Time::get_singleton();
|
||||
const float start_time = time->get_ticks_msec();
|
||||
|
||||
// PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms");
|
||||
{ // Initialise the state here
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user