TriangleSelector: remerging triangles, bugfixes
This commit is contained in:
parent
bed28bb2ff
commit
fb73bb1c66
2 changed files with 140 additions and 80 deletions
|
@ -95,7 +95,10 @@ void GLGizmoFdmSupports::on_render() const
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
//render_triangles(selection);
|
//render_triangles(selection);
|
||||||
m_triangle_selector->render();
|
|
||||||
|
if (m_triangle_selector && ! m_setting_angle)
|
||||||
|
m_triangle_selector->render(m_imgui);
|
||||||
|
|
||||||
m_c->object_clipper()->render_cut();
|
m_c->object_clipper()->render_cut();
|
||||||
render_cursor_circle();
|
render_cursor_circle();
|
||||||
|
|
||||||
|
@ -569,12 +572,6 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
if (! m_c->selection_info()->model_object())
|
if (! m_c->selection_info()->model_object())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_imgui->begin(std::string("TriangleSelector DEBUG"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
|
||||||
static float edge_limit = 1.f;
|
|
||||||
m_imgui->slider_float("Edge limit (mm): ", &edge_limit, 0.1f, 8.f);
|
|
||||||
m_triangle_selector->set_edge_limit(edge_limit);
|
|
||||||
m_imgui->end();
|
|
||||||
|
|
||||||
const float approx_height = m_imgui->scaled(18.0f);
|
const float approx_height = m_imgui->scaled(18.0f);
|
||||||
y = std::min(y, bottom_limit - approx_height);
|
y = std::min(y, bottom_limit - approx_height);
|
||||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||||
|
@ -740,9 +737,7 @@ CommonGizmosDataID GLGizmoFdmSupports::on_get_requirements() const
|
||||||
int(CommonGizmosDataID::SelectionInfo)
|
int(CommonGizmosDataID::SelectionInfo)
|
||||||
| int(CommonGizmosDataID::InstancesHider)
|
| int(CommonGizmosDataID::InstancesHider)
|
||||||
| int(CommonGizmosDataID::Raycaster)
|
| int(CommonGizmosDataID::Raycaster)
|
||||||
| int(CommonGizmosDataID::HollowedMesh)
|
| int(CommonGizmosDataID::ObjectClipper));
|
||||||
| int(CommonGizmosDataID::ObjectClipper)
|
|
||||||
| int(CommonGizmosDataID::SupportsClipper));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -872,7 +867,7 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
||||||
while (facet_idx < int(facets_to_check.size())) {
|
while (facet_idx < int(facets_to_check.size())) {
|
||||||
int facet = facets_to_check[facet_idx];
|
int facet = facets_to_check[facet_idx];
|
||||||
if (! visited[facet]) {
|
if (! visited[facet]) {
|
||||||
if (select_triangle(facet, new_state, facet == facet_start)) {
|
if (select_triangle(facet, new_state)) {
|
||||||
// add neighboring facets to list to be proccessed later
|
// add neighboring facets to list to be proccessed later
|
||||||
for (int n=0; n<3; ++n) {
|
for (int n=0; n<3; ++n) {
|
||||||
if (faces_camera(m_mesh->stl.neighbors_start[facet].neighbor[n]))
|
if (faces_camera(m_mesh->stl.neighbors_start[facet].neighbor[n]))
|
||||||
|
@ -891,49 +886,54 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
||||||
// the triangle recursively, selecting just subtriangles truly inside the circle.
|
// the triangle recursively, selecting just subtriangles truly inside the circle.
|
||||||
// This is done by an actual recursive call. Returns false if the triangle is
|
// This is done by an actual recursive call. Returns false if the triangle is
|
||||||
// outside the cursor.
|
// outside the cursor.
|
||||||
bool TriangleSelector::select_triangle(int facet_idx, FacetSupportType type, bool cursor_inside)
|
bool TriangleSelector::select_triangle(int facet_idx, FacetSupportType type, bool recursive_call)
|
||||||
{
|
{
|
||||||
assert(facet_idx < int(m_triangles.size()));
|
assert(facet_idx < int(m_triangles.size()));
|
||||||
|
|
||||||
Triangle& tr = m_triangles[facet_idx];
|
Triangle* tr = &m_triangles[facet_idx];
|
||||||
if (! tr.valid)
|
if (! tr->valid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cursor_inside = is_pointer_in_triangle(facet_idx);
|
|
||||||
|
|
||||||
int num_of_inside_vertices = vertices_inside(facet_idx);
|
int num_of_inside_vertices = vertices_inside(facet_idx);
|
||||||
|
|
||||||
if (num_of_inside_vertices == 0
|
if (num_of_inside_vertices == 0
|
||||||
&& ! cursor_inside
|
&& ! is_pointer_in_triangle(facet_idx)
|
||||||
&& ! is_edge_inside_cursor(facet_idx))
|
&& ! is_edge_inside_cursor(facet_idx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (vertices_inside(facet_idx) == 3) {
|
if (num_of_inside_vertices == 3) {
|
||||||
// dump any subdivision and select whole triangle
|
// dump any subdivision and select whole triangle
|
||||||
undivide_triangle(facet_idx);
|
undivide_triangle(facet_idx);
|
||||||
tr.set_state(type);
|
tr->set_state(type);
|
||||||
} else {
|
} else {
|
||||||
// the triangle is partially inside, let's recursively divide it
|
// the triangle is partially inside, let's recursively divide it
|
||||||
// (if not already) and try selecting its children.
|
// (if not already) and try selecting its children.
|
||||||
|
|
||||||
if (! tr.is_split() && tr.get_state() == type) {
|
if (! tr->is_split() && tr->get_state() == type) {
|
||||||
// This is leaf triangle that is already of correct type as a whole.
|
// This is leaf triangle that is already of correct type as a whole.
|
||||||
// No need to split, all children would end up selected anyway.
|
// No need to split, all children would end up selected anyway.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
split_triangle(facet_idx);
|
split_triangle(facet_idx);
|
||||||
assert(facet_idx < int(m_triangles.size()));
|
tr = &m_triangles[facet_idx]; // might have been invalidated
|
||||||
int num_of_children = tr.number_of_split_sides() + 1;
|
|
||||||
if (num_of_children != 1) {
|
|
||||||
for (int i=0; i<num_of_children; ++i)
|
|
||||||
select_triangle(tr.children[i], type, cursor_inside);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case that all siblings are leafs and have the same state now,
|
|
||||||
|
int num_of_children = tr->number_of_split_sides() + 1;
|
||||||
|
if (num_of_children != 1) {
|
||||||
|
for (int i=0; i<num_of_children; ++i) {
|
||||||
|
assert(i < int(tr->children.size()));
|
||||||
|
assert(tr->children[i] < int(m_triangles.size()));
|
||||||
|
|
||||||
|
select_triangle(tr->children[i], type, true);
|
||||||
|
tr = &m_triangles[facet_idx]; // might have been invalidated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// In case that all children are leafs and have the same state now,
|
||||||
// they may be removed and substituted by the parent triangle.
|
// they may be removed and substituted by the parent triangle.
|
||||||
//remove_if_needless(facet_idx);
|
if (! recursive_call)
|
||||||
|
remove_useless_children(facet_idx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,13 +945,13 @@ bool TriangleSelector::split_triangle(int facet_idx)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Triangle& tr = m_triangles[facet_idx];
|
Triangle* tr = &m_triangles[facet_idx];
|
||||||
|
|
||||||
FacetSupportType old_type = tr.get_state();
|
FacetSupportType old_type = tr->get_state();
|
||||||
|
|
||||||
const double limit_squared = m_edge_limit_sqr;
|
const double limit_squared = m_edge_limit_sqr;
|
||||||
|
|
||||||
stl_triangle_vertex_indices& facet = tr.verts_idxs;
|
stl_triangle_vertex_indices& facet = tr->verts_idxs;
|
||||||
const stl_vertex* pts[3] = { &m_vertices[facet[0]], &m_vertices[facet[1]], &m_vertices[facet[2]]};
|
const stl_vertex* pts[3] = { &m_vertices[facet[0]], &m_vertices[facet[1]], &m_vertices[facet[2]]};
|
||||||
double sides[3] = { (*pts[2]-*pts[1]).squaredNorm(), (*pts[0]-*pts[2]).squaredNorm(), (*pts[1]-*pts[0]).squaredNorm() };
|
double sides[3] = { (*pts[2]-*pts[1]).squaredNorm(), (*pts[0]-*pts[2]).squaredNorm(), (*pts[1]-*pts[0]).squaredNorm() };
|
||||||
|
|
||||||
|
@ -964,7 +964,7 @@ bool TriangleSelector::split_triangle(int facet_idx)
|
||||||
side_to_keep = pt_idx;
|
side_to_keep = pt_idx;
|
||||||
}
|
}
|
||||||
if (sides_to_split.empty()) {
|
if (sides_to_split.empty()) {
|
||||||
tr.set_division(0);
|
tr->set_division(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,17 +1012,19 @@ bool TriangleSelector::split_triangle(int facet_idx)
|
||||||
m_triangles.emplace_back(verts_idxs[1], verts_idxs[3], verts_idxs[5]);
|
m_triangles.emplace_back(verts_idxs[1], verts_idxs[3], verts_idxs[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr = &m_triangles[facet_idx]; // may have been invalidated
|
||||||
|
|
||||||
// Save how the triangle was split. Second argument makes sense only for one
|
// Save how the triangle was split. Second argument makes sense only for one
|
||||||
// or two split sides, otherwise the value is ignored.
|
// or two split sides, otherwise the value is ignored.
|
||||||
tr.set_division(sides_to_split.size(),
|
tr->set_division(sides_to_split.size(),
|
||||||
sides_to_split.size() == 2 ? side_to_keep : sides_to_split[0]);
|
sides_to_split.size() == 2 ? side_to_keep : sides_to_split[0]);
|
||||||
|
|
||||||
// And save the children. All children should start in the same state as the triangle we just split.
|
// And save the children. All children should start in the same state as the triangle we just split.
|
||||||
assert(! sides_to_split.empty() && int(sides_to_split.size()) <= 3);
|
assert(! sides_to_split.empty() && int(sides_to_split.size()) <= 3);
|
||||||
for (int i=0; i<=int(sides_to_split.size()); ++i) {
|
for (int i=0; i<=int(sides_to_split.size()); ++i) {
|
||||||
tr.children[i] = m_triangles.size()-1-i;
|
tr->children[i] = m_triangles.size()-1-i;
|
||||||
m_triangles[tr.children[i]].parent = facet_idx;
|
m_triangles[tr->children[i]].parent = facet_idx;
|
||||||
m_triangles[tr.children[i]].set_state(old_type);
|
m_triangles[tr->children[i]].set_state(old_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1097,7 +1099,10 @@ bool TriangleSelector::is_edge_inside_cursor(int facet_idx) const
|
||||||
Vec3f s = (b-a).normalized();
|
Vec3f s = (b-a).normalized();
|
||||||
float t = (p-a).dot(s);
|
float t = (p-a).dot(s);
|
||||||
Vec3f vector = a+t*s - p;
|
Vec3f vector = a+t*s - p;
|
||||||
float dist_sqr = vector.squaredNorm();
|
|
||||||
|
// vector is 3D vector from center to the intersection. What we want to
|
||||||
|
// measure is length of its projection onto plane perpendicular to dir.
|
||||||
|
float dist_sqr = vector.squaredNorm() - std::pow(vector.dot(m_cursor.dir), 2.f);
|
||||||
if (dist_sqr < m_cursor.radius_sqr && t>=0.f && t<=(b-a).norm())
|
if (dist_sqr < m_cursor.radius_sqr && t>=0.f && t<=(b-a).norm())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1117,33 +1122,47 @@ void TriangleSelector::undivide_triangle(int facet_idx)
|
||||||
undivide_triangle(tr.children[i]);
|
undivide_triangle(tr.children[i]);
|
||||||
m_triangles[tr.children[i]].valid = false;
|
m_triangles[tr.children[i]].valid = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tr.set_division(0); // not split
|
tr.set_division(0); // not split
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TriangleSelector::remove_if_needless(int child_facet)
|
void TriangleSelector::remove_useless_children(int facet_idx)
|
||||||
{
|
{
|
||||||
if (m_triangles[child_facet].is_split() || ! m_triangles[child_facet].valid)
|
// Check that all children are leafs of the same type. If not, try to
|
||||||
|
// make them (recursive call). Remove them if sucessful.
|
||||||
|
|
||||||
|
assert(facet_idx < int(m_triangles.size()) && m_triangles[facet_idx].valid);
|
||||||
|
Triangle& tr = m_triangles[facet_idx];
|
||||||
|
|
||||||
|
if (! tr.is_split()) {
|
||||||
|
// This is a leaf, there nothing to do. This can happen during the
|
||||||
|
// first (non-recursive call). Shouldn't otherwise.
|
||||||
return;
|
return;
|
||||||
int parent = m_triangles[child_facet].parent;
|
}
|
||||||
if (parent == -1)
|
|
||||||
return; // root
|
|
||||||
FacetSupportType child_type = m_triangles[child_facet].get_state();
|
|
||||||
|
|
||||||
// Check type of all valid children, if they're same, they are needless.
|
// Call this for all non-leaf children.
|
||||||
for (int i=0; i<=m_triangles[parent].number_of_split_sides(); ++i)
|
for (int child_idx=0; child_idx<=tr.number_of_split_sides(); ++child_idx) {
|
||||||
if (m_triangles[m_triangles[parent].children[i]].is_split()
|
assert(child_idx < int(m_triangles.size()) && m_triangles[child_idx].valid);
|
||||||
|| m_triangles[m_triangles[parent].children[i]].get_state() != child_type)
|
if (m_triangles[tr.children[child_idx]].is_split())
|
||||||
return; // not all children are the same
|
remove_useless_children(tr.children[child_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
// All children are the same, kill them.
|
|
||||||
undivide_triangle(parent);
|
|
||||||
m_triangles[parent].set_state(child_type);
|
|
||||||
|
|
||||||
// And now try the same for parent (which has just become leaf).
|
// Return if a child is not leaf or two children differ in type.
|
||||||
remove_if_needless(parent);
|
FacetSupportType first_child_type;
|
||||||
|
for (int child_idx=0; child_idx<=tr.number_of_split_sides(); ++child_idx) {
|
||||||
|
if (m_triangles[tr.children[child_idx]].is_split())
|
||||||
|
return;
|
||||||
|
if (child_idx == 0)
|
||||||
|
first_child_type = m_triangles[tr.children[0]].get_state();
|
||||||
|
else if (m_triangles[tr.children[child_idx]].get_state() != first_child_type)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got here, the children can be removed.
|
||||||
|
undivide_triangle(facet_idx);
|
||||||
|
tr.set_state(first_child_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1158,33 +1177,12 @@ TriangleSelector::TriangleSelector(const TriangleMesh& mesh)
|
||||||
m_mesh = &mesh;
|
m_mesh = &mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TriangleSelector::render(ImGuiWrapper* imgui)
|
||||||
void TriangleSelector::render() const
|
|
||||||
{
|
{
|
||||||
::glColor3f(0.f, 0.f, 1.f);
|
|
||||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
|
||||||
|
|
||||||
Vec3d offset = wxGetApp().model().objects.front()->instances.front()->get_transformation().get_offset();
|
Vec3d offset = wxGetApp().model().objects.front()->instances.front()->get_transformation().get_offset();
|
||||||
::glTranslatef(offset.x(), offset.y(), offset.z());
|
::glTranslatef(offset.x(), offset.y(), offset.z());
|
||||||
::glScalef(1.01f, 1.01f, 1.01f);
|
::glScalef(1.005f, 1.005f, 1.005f);
|
||||||
|
|
||||||
::glBegin( GL_TRIANGLES);
|
|
||||||
for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) {
|
|
||||||
const Triangle& tr = m_triangles[tr_id];
|
|
||||||
if (! tr.valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (tr_id == m_orig_size_indices-1)
|
|
||||||
::glColor3f(1.f, 0.f, 0.f);
|
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
|
||||||
::glVertex3f(m_vertices[tr.verts_idxs[i]][0],
|
|
||||||
m_vertices[tr.verts_idxs[i]][1],
|
|
||||||
m_vertices[tr.verts_idxs[i]][2]);
|
|
||||||
}
|
|
||||||
::glEnd();
|
|
||||||
|
|
||||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
|
||||||
|
|
||||||
::glBegin( GL_TRIANGLES);
|
::glBegin( GL_TRIANGLES);
|
||||||
for (const Triangle& tr : m_triangles) {
|
for (const Triangle& tr : m_triangles) {
|
||||||
|
@ -1202,7 +1200,57 @@ void TriangleSelector::render() const
|
||||||
m_vertices[tr.verts_idxs[i]][2]);
|
m_vertices[tr.verts_idxs[i]][2]);
|
||||||
}
|
}
|
||||||
::glEnd();
|
::glEnd();
|
||||||
|
|
||||||
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
|
if (imgui)
|
||||||
|
render_debug(imgui);
|
||||||
|
else
|
||||||
|
assert(false); // If you want debug output, pass ptr to ImGuiWrapper.
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
|
void TriangleSelector::render_debug(ImGuiWrapper* imgui)
|
||||||
|
{
|
||||||
|
imgui->begin(std::string("TriangleSelector dialog (DEV ONLY)"),
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
static float edge_limit = 1.f;
|
||||||
|
imgui->text("Edge limit (mm): ");
|
||||||
|
imgui->slider_float("", &edge_limit, 0.1f, 8.f);
|
||||||
|
set_edge_limit(edge_limit);
|
||||||
|
imgui->checkbox("Show triangles: ", m_show_triangles);
|
||||||
|
|
||||||
|
int valid_triangles = std::count_if(m_triangles.begin(), m_triangles.end(),
|
||||||
|
[](const Triangle& tr) { return tr.valid; });
|
||||||
|
imgui->text("Valid triangles: " + std::to_string(valid_triangles) +
|
||||||
|
"/" + std::to_string(m_triangles.size()));
|
||||||
|
imgui->text("Number of vertices: " + std::to_string(m_vertices.size()));
|
||||||
|
|
||||||
|
imgui->end();
|
||||||
|
|
||||||
|
if (m_show_triangles) {
|
||||||
|
::glColor3f(0.f, 0.f, 1.f);
|
||||||
|
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
|
||||||
|
::glBegin( GL_TRIANGLES);
|
||||||
|
for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) {
|
||||||
|
const Triangle& tr = m_triangles[tr_id];
|
||||||
|
if (! tr.valid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (tr_id == m_orig_size_indices-1)
|
||||||
|
::glColor3f(1.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
::glVertex3f(m_vertices[tr.verts_idxs[i]][0],
|
||||||
|
m_vertices[tr.verts_idxs[i]][1],
|
||||||
|
m_vertices[tr.verts_idxs[i]][2]);
|
||||||
|
}
|
||||||
|
::glEnd();
|
||||||
|
::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#define PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
enum class FacetSupportType : int8_t;
|
enum class FacetSupportType : int8_t;
|
||||||
|
@ -25,7 +28,7 @@ class ClippingPlane;
|
||||||
class TriangleSelector {
|
class TriangleSelector {
|
||||||
public:
|
public:
|
||||||
void set_edge_limit(float edge_limit) { m_edge_limit_sqr = std::pow(edge_limit, 2.f); }
|
void set_edge_limit(float edge_limit) { m_edge_limit_sqr = std::pow(edge_limit, 2.f); }
|
||||||
void render() const;
|
|
||||||
// Create new object on a TriangleMesh. The referenced mesh must
|
// Create new object on a TriangleMesh. The referenced mesh must
|
||||||
// stay valid, a ptr to it is saved and used.
|
// stay valid, a ptr to it is saved and used.
|
||||||
explicit TriangleSelector(const TriangleMesh& mesh);
|
explicit TriangleSelector(const TriangleMesh& mesh);
|
||||||
|
@ -40,10 +43,19 @@ public:
|
||||||
|
|
||||||
void unselect_all();
|
void unselect_all();
|
||||||
|
|
||||||
|
// Render current selection. Transformation matrices are supposed
|
||||||
|
// to be already set.
|
||||||
|
void render(ImGuiWrapper* imgui = nullptr);
|
||||||
|
|
||||||
// Remove all unnecessary data (such as vertices that are not needed
|
// Remove all unnecessary data (such as vertices that are not needed
|
||||||
// because the selection has been made larger.
|
// because the selection has been made larger.
|
||||||
void garbage_collect();
|
void garbage_collect();
|
||||||
|
|
||||||
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
|
void render_debug(ImGuiWrapper* imgui);
|
||||||
|
bool m_show_triangles{true};
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Triangle and info about how it's split.
|
// Triangle and info about how it's split.
|
||||||
struct Triangle {
|
struct Triangle {
|
||||||
|
@ -112,13 +124,13 @@ private:
|
||||||
|
|
||||||
// Private functions:
|
// Private functions:
|
||||||
bool select_triangle(int facet_idx, FacetSupportType type,
|
bool select_triangle(int facet_idx, FacetSupportType type,
|
||||||
bool cursor_inside = false);
|
bool recursive_call = false);
|
||||||
bool is_point_inside_cursor(const Vec3f& point) const;
|
bool is_point_inside_cursor(const Vec3f& point) const;
|
||||||
int vertices_inside(int facet_idx) const;
|
int vertices_inside(int facet_idx) const;
|
||||||
bool faces_camera(int facet) const;
|
bool faces_camera(int facet) const;
|
||||||
void undivide_triangle(int facet_idx);
|
void undivide_triangle(int facet_idx);
|
||||||
bool split_triangle(int facet_idx);
|
bool split_triangle(int facet_idx);
|
||||||
void remove_if_needless(int child_facet);
|
void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant.
|
||||||
bool is_pointer_in_triangle(int facet_idx) const;
|
bool is_pointer_in_triangle(int facet_idx) const;
|
||||||
bool is_edge_inside_cursor(int facet_idx) const;
|
bool is_edge_inside_cursor(int facet_idx) const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue