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)
|
void IDamageable::_slice_meshes(Ref<MeshEditSliceInput> data)
|
||||||
{
|
{
|
||||||
this->_is_slicing = true;
|
this->_is_slicing = true;
|
||||||
this->_input_queue.emplace_back(data);
|
if (this->_validate_input(data))
|
||||||
if (this->_slice_state_queue.empty())
|
{
|
||||||
this->_new_slice_loop();
|
this->_input_queue.emplace_back(data);
|
||||||
|
if (this->_slice_state_queue.empty())
|
||||||
|
this->_new_slice_loop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDamageable::_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();
|
this->_slice_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,17 +38,17 @@ void IDamageable::_slice_loop()
|
|||||||
switch(current_state->current_stage)
|
switch(current_state->current_stage)
|
||||||
{
|
{
|
||||||
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_INIT:
|
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_INIT:
|
||||||
MeshEditingLibrary::slice_mesh_init(current_state);
|
if (MeshEditingLibrary::slice_mesh_init(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
|
||||||
break;
|
break;
|
||||||
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_PLANE_SPLIT:
|
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_PLANE_SPLIT:
|
||||||
MeshEditingLibrary::slice_mesh_plane_split(current_state);
|
if (MeshEditingLibrary::slice_mesh_plane_split(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
|
||||||
break;
|
break;
|
||||||
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_EDGE_SPLIT:
|
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_EDGE_SPLIT:
|
||||||
MeshEditingLibrary::slice_mesh_edge_split(current_state);
|
if (MeshEditingLibrary::slice_mesh_edge_split(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
|
||||||
break;
|
break;
|
||||||
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_APPLY_CAP:
|
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_APPLY_CAP:
|
||||||
MeshEditingLibrary::slice_mesh_apply_cap(current_state);
|
if (MeshEditingLibrary::slice_mesh_apply_cap(current_state) > MESH_EDITING_SLICE_LOOP_LIMIT)
|
||||||
break;
|
break;
|
||||||
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_COMPLETE:
|
case MeshEditingLibrary::MeshEditSliceStage::SLICE_STAGE_COMPLETE:
|
||||||
this->_slice_complete(current_state->output);
|
this->_slice_complete(current_state->output);
|
||||||
this->_input_queue.erase(this->_input_queue.begin());
|
this->_input_queue.erase(this->_input_queue.begin());
|
||||||
@@ -58,3 +63,22 @@ void IDamageable::_slice_loop()
|
|||||||
else
|
else
|
||||||
this->_is_slicing = false;
|
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"
|
#include "godot_cpp/classes/node.hpp"
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
|
#define MAX_SLICE_QUEUE_SIZE 3
|
||||||
|
|
||||||
|
|
||||||
class IDamageable : public Node3D
|
class IDamageable : public Node3D
|
||||||
{
|
{
|
||||||
@@ -27,6 +29,8 @@ private:
|
|||||||
void _new_slice_loop();
|
void _new_slice_loop();
|
||||||
void _slice_loop();
|
void _slice_loop();
|
||||||
|
|
||||||
|
bool _validate_input(Ref<MeshEditSliceInput> input);
|
||||||
|
|
||||||
bool _is_slicing = false;
|
bool _is_slicing = false;
|
||||||
|
|
||||||
std::vector<Ref<MeshSliceState>> _slice_state_queue;
|
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)
|
if (other_half_meshes_to_add.size() > 0)
|
||||||
{
|
{
|
||||||
RandomNumberGenerator *rng = memnew(RandomNumberGenerator);
|
RandomNumberGenerator *rng = memnew(RandomNumberGenerator);
|
||||||
const float random_x = 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.05f, 0.05f);
|
const float random_z = rng->randf_range(-0.01f, 0.01f);
|
||||||
|
|
||||||
CharacterSkeleton3D *new_character_skeleton = cast_to<CharacterSkeleton3D>(this->character_skeleton->duplicate());
|
CharacterSkeleton3D *new_character_skeleton = cast_to<CharacterSkeleton3D>(this->character_skeleton->duplicate());
|
||||||
this->character_skeleton->add_sibling(new_character_skeleton);
|
this->character_skeleton->add_sibling(new_character_skeleton);
|
||||||
|
|||||||
@@ -31,18 +31,17 @@ Ref<MeshSliceState> MeshEditingLibrary::slice_mesh(const Ref<MeshEditSliceInput>
|
|||||||
return fresh_state;
|
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->original_mesh = state->input->mesh_instance->get_mesh();
|
||||||
state->num_surfaces = state->original_mesh->get_surface_count();
|
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->surface_arrays_list.resize(state->num_surfaces);
|
||||||
state->skinned_vertex_positions.resize(state->num_surfaces);
|
state->skinned_vertex_positions.resize(state->num_surfaces);
|
||||||
state->skinned_vertex_transforms.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++)
|
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);
|
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];
|
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->num_custom0_per_vertex[state->surface] = surface_num_custom0_per_vertex;
|
||||||
|
|
||||||
state->vertex_distances[state->surface].resize(num_vertices);
|
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->surface = 0;
|
||||||
state->element = 0;
|
state->element = 0;
|
||||||
state->current_stage = MeshEditSliceStage::SLICE_STAGE_PLANE_SPLIT;
|
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++)
|
for (state->surface; state->surface < state->num_surfaces; state->surface++)
|
||||||
{
|
{
|
||||||
const PackedVector3Array &surface_vertex_array = state->surface_arrays_list[state->surface][ArrayMesh::ARRAY_VERTEX];
|
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++)
|
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]);
|
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)
|
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;
|
state->element = 0;
|
||||||
}
|
}
|
||||||
@@ -255,14 +267,17 @@ void MeshEditingLibrary::slice_mesh_plane_split(Ref<MeshSliceState> state)
|
|||||||
|
|
||||||
state->surface = 0;
|
state->surface = 0;
|
||||||
state->current_stage = MeshEditSliceStage::SLICE_STAGE_EDGE_SPLIT;
|
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++)
|
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_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 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];
|
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();
|
const uint32_t num_triangles = surface_index_array.size();
|
||||||
for (state->element; state->element < num_triangles; state->element += 3)
|
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];
|
uint32_t base_v[3];
|
||||||
std::map<uint32_t, uint32_t>::iterator sliced_v[3];
|
std::map<uint32_t, uint32_t>::iterator sliced_v[3];
|
||||||
std::map<uint32_t, uint32_t>::iterator sliced_other_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;
|
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;
|
int64_t array_format_bit_mask = Mesh::ARRAY_FORMAT_VERTEX;
|
||||||
if (has_normal) array_format_bit_mask |= Mesh::ARRAY_FORMAT_NORMAL;
|
if (has_normal) array_format_bit_mask |= Mesh::ARRAY_FORMAT_NORMAL;
|
||||||
if (has_tangent) array_format_bit_mask |= Mesh::ARRAY_FORMAT_TANGENT;
|
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);
|
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->surface = 0;
|
||||||
state->current_stage = MeshEditSliceStage::SLICE_STAGE_APPLY_CAP;
|
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)
|
if (state->clip_edges.size() > 0)
|
||||||
{
|
{
|
||||||
MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z;
|
MeshSlicePlaneOrientation uv_plane = MeshSlicePlaneOrientation::Z;
|
||||||
const Basis &mesh_instance_basis = state->input->mesh_instance->get_basis();
|
const Basis &mesh_instance_basis = state->input->mesh_instance->get_basis();
|
||||||
const Vector3 &local_plane_normal = state->input->local_plane.get_normal();
|
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)
|
if (UtilityFunctions::absf(local_plane_normal.dot(mesh_instance_basis.xform(Vector3(0.0f, 1.0f, 0.0f)))) > 0.5f)
|
||||||
{
|
|
||||||
uv_plane = MeshSlicePlaneOrientation::Y;
|
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)
|
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;
|
uv_plane = MeshSlicePlaneOrientation::X;
|
||||||
}
|
|
||||||
|
|
||||||
SurfaceTool *surface_tool_first_half = memnew(SurfaceTool);
|
SurfaceTool *surface_tool_first_half = memnew(SurfaceTool);
|
||||||
SurfaceTool *surface_tool_other_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_first_half);
|
||||||
memdelete(surface_tool_other_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->original_skeleton = state->input->skeleton;
|
||||||
state->output->main_half = state->first_half;
|
state->output->main_half = state->first_half;
|
||||||
state->output->secondary_half = state->other_half;
|
state->output->secondary_half = state->other_half;
|
||||||
|
|
||||||
state->current_stage = MeshEditSliceStage::SLICE_STAGE_COMPLETE;
|
state->current_stage = MeshEditSliceStage::SLICE_STAGE_COMPLETE;
|
||||||
|
|
||||||
|
return time->get_ticks_msec() - start_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ using namespace godot;
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#define MESH_EDITING_SLICE_LOOP_LIMIT 5.555555555555555f
|
||||||
|
|
||||||
#define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary"
|
#define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary"
|
||||||
|
|
||||||
typedef PackedVector3Array SkinnedVertices;
|
typedef PackedVector3Array SkinnedVertices;
|
||||||
@@ -87,10 +89,10 @@ public:
|
|||||||
|
|
||||||
static Ref<class MeshSliceState> slice_mesh(const Ref<class MeshEditSliceInput> input);
|
static Ref<class MeshSliceState> slice_mesh(const Ref<class MeshEditSliceInput> input);
|
||||||
|
|
||||||
static void slice_mesh_init(Ref<class MeshSliceState> state);
|
static float slice_mesh_init(Ref<class MeshSliceState> state);
|
||||||
static void slice_mesh_plane_split(Ref<class MeshSliceState> state);
|
static float slice_mesh_plane_split(Ref<class MeshSliceState> state);
|
||||||
static void slice_mesh_edge_split(Ref<class MeshSliceState> state);
|
static float slice_mesh_edge_split(Ref<class MeshSliceState> state);
|
||||||
static void slice_mesh_apply_cap(Ref<class MeshSliceState> state);
|
static float slice_mesh_apply_cap(Ref<class MeshSliceState> state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum MeshSlicePlaneOrientation
|
enum MeshSlicePlaneOrientation
|
||||||
|
|||||||
Reference in New Issue
Block a user