TriangleSelector: getting ready for frontend/backend separation
This commit is contained in:
parent
da6acd73e2
commit
814f8be92f
2 changed files with 207 additions and 83 deletions
|
@ -972,63 +972,12 @@ void TriangleSelector::split_triangle(int facet_idx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// indices of triangle vertices
|
// Save how the triangle will be split. Second argument makes sense only for one
|
||||||
std::vector<int> verts_idxs;
|
|
||||||
int idx = sides_to_split.size() == 2 ? side_to_keep : sides_to_split[0];
|
|
||||||
for (int j=0; j<3; ++j) {
|
|
||||||
verts_idxs.push_back(facet[idx++]);
|
|
||||||
if (idx == 3)
|
|
||||||
idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (sides_to_split.size() == 1) {
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[1]].v + m_vertices[verts_idxs[2]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+2, m_vertices.size() - 1);
|
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2]);
|
|
||||||
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sides_to_split.size() == 2) {
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[1]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+1, m_vertices.size() - 1);
|
|
||||||
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[3]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+4, m_vertices.size() - 1);
|
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4]);
|
|
||||||
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4]);
|
|
||||||
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sides_to_split.size() == 3) {
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[1]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+1, m_vertices.size() - 1);
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[2]].v + m_vertices[verts_idxs[3]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+3, m_vertices.size() - 1);
|
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[4]].v + m_vertices[verts_idxs[0]].v)/2.);
|
|
||||||
verts_idxs.insert(verts_idxs.begin()+5, m_vertices.size() - 1);
|
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5]);
|
|
||||||
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3]);
|
|
||||||
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5]);
|
|
||||||
push_triangle(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
|
|
||||||
// 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.
|
perform_split(facet_idx, old_type);
|
||||||
assert(! sides_to_split.empty() && int(sides_to_split.size()) <= 3);
|
|
||||||
for (int i=0; i<=int(sides_to_split.size()); ++i) {
|
|
||||||
tr->children[i] = m_triangles.size()-1-i;
|
|
||||||
m_triangles[tr->children[i]].set_state(old_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1253,22 +1202,45 @@ void TriangleSelector::render(ImGuiWrapper* imgui)
|
||||||
::glScalef(1.005f, 1.005f, 1.005f);
|
::glScalef(1.005f, 1.005f, 1.005f);
|
||||||
|
|
||||||
|
|
||||||
::glBegin( GL_TRIANGLES);
|
int enf_cnt = 0;
|
||||||
|
int blc_cnt = 0;
|
||||||
|
|
||||||
for (const Triangle& tr : m_triangles) {
|
for (const Triangle& tr : m_triangles) {
|
||||||
if (! tr.valid || tr.is_split() || tr.get_state() == FacetSupportType::NONE)
|
if (! tr.valid || tr.is_split() || tr.get_state() == FacetSupportType::NONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tr.get_state() == FacetSupportType::ENFORCER)
|
GLIndexedVertexArray& va = tr.get_state() == FacetSupportType::ENFORCER
|
||||||
::glColor4f(0.f, 0.f, 1.f, 0.2f);
|
? m_iva_enforcers
|
||||||
else
|
: m_iva_blockers;
|
||||||
::glColor4f(1.f, 0.f, 0.f, 0.2f);
|
int& cnt = tr.get_state() == FacetSupportType::ENFORCER
|
||||||
|
? enf_cnt
|
||||||
|
: blc_cnt;
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
::glVertex3f(m_vertices[tr.verts_idxs[i]].v[0],
|
va.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
||||||
m_vertices[tr.verts_idxs[i]].v[1],
|
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
||||||
m_vertices[tr.verts_idxs[i]].v[2]);
|
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
||||||
|
0., 0., 1.);
|
||||||
|
va.push_triangle(cnt,
|
||||||
|
cnt+1,
|
||||||
|
cnt+2);
|
||||||
|
cnt += 3;
|
||||||
}
|
}
|
||||||
::glEnd();
|
|
||||||
|
m_iva_enforcers.finalize_geometry(true);
|
||||||
|
m_iva_blockers.finalize_geometry(true);
|
||||||
|
|
||||||
|
if (m_iva_enforcers.has_VBOs()) {
|
||||||
|
::glColor4f(0.f, 0.f, 1.f, 0.2f);
|
||||||
|
m_iva_enforcers.render();
|
||||||
|
}
|
||||||
|
m_iva_enforcers.release_geometry();
|
||||||
|
|
||||||
|
if (m_iva_blockers.has_VBOs()) {
|
||||||
|
::glColor4f(1.f, 0.f, 0.f, 0.2f);
|
||||||
|
m_iva_blockers.render();
|
||||||
|
}
|
||||||
|
m_iva_blockers.release_geometry();
|
||||||
|
|
||||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
if (imgui)
|
if (imgui)
|
||||||
|
@ -1304,6 +1276,110 @@ void TriangleSelector::push_triangle(int a, int b, int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TriangleSelector::perform_split(int facet_idx, FacetSupportType old_state)
|
||||||
|
{
|
||||||
|
Triangle* tr = &m_triangles[facet_idx];
|
||||||
|
|
||||||
|
assert(tr->is_split());
|
||||||
|
|
||||||
|
// Read info about how to split this triangle.
|
||||||
|
int sides_to_split = tr->number_of_split_sides();
|
||||||
|
|
||||||
|
// indices of triangle vertices
|
||||||
|
std::vector<int> verts_idxs;
|
||||||
|
int idx = tr->special_side();
|
||||||
|
for (int j=0; j<3; ++j) {
|
||||||
|
verts_idxs.push_back(tr->verts_idxs[idx++]);
|
||||||
|
if (idx == 3)
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sides_to_split == 1) {
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[1]].v + m_vertices[verts_idxs[2]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+2, m_vertices.size() - 1);
|
||||||
|
|
||||||
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2]);
|
||||||
|
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sides_to_split == 2) {
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[1]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+1, m_vertices.size() - 1);
|
||||||
|
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[3]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+4, m_vertices.size() - 1);
|
||||||
|
|
||||||
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4]);
|
||||||
|
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4]);
|
||||||
|
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sides_to_split == 3) {
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[1]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+1, m_vertices.size() - 1);
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[2]].v + m_vertices[verts_idxs[3]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+3, m_vertices.size() - 1);
|
||||||
|
m_vertices.emplace_back((m_vertices[verts_idxs[4]].v + m_vertices[verts_idxs[0]].v)/2.);
|
||||||
|
verts_idxs.insert(verts_idxs.begin()+5, m_vertices.size() - 1);
|
||||||
|
|
||||||
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5]);
|
||||||
|
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3]);
|
||||||
|
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5]);
|
||||||
|
push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr = &m_triangles[facet_idx]; // may have been invalidated
|
||||||
|
|
||||||
|
// And save the children. All children should start in the same state as the triangle we just split.
|
||||||
|
assert(sides_to_split <= 3);
|
||||||
|
for (int i=0; i<=sides_to_split; ++i) {
|
||||||
|
tr->children[i] = m_triangles.size()-1-i;
|
||||||
|
m_triangles[tr->children[i]].set_state(old_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::map<int, int64_t> TriangleSelector::serialize() const
|
||||||
|
{
|
||||||
|
std::map<int, int64_t> out;
|
||||||
|
for (int i=0; i<m_orig_size_indices; ++i) {
|
||||||
|
const Triangle& tr = m_triangles[i];
|
||||||
|
FacetSupportType state = tr.get_state();
|
||||||
|
if (! tr.is_split() && state == FacetSupportType::NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int64_t data = 0;
|
||||||
|
int8_t stored_triangles = 0;
|
||||||
|
|
||||||
|
std::function<void(int)> serialize_recursive;
|
||||||
|
serialize_recursive = [this, &stored_triangles, &data, &serialize_recursive](int facet_idx) {
|
||||||
|
const Triangle& tr = m_triangles[facet_idx];
|
||||||
|
int split_sides = tr.number_of_split_sides();
|
||||||
|
assert( split_sides > 0 && split_sides <= 3);
|
||||||
|
data |= (split_sides << (stored_triangles * 4));
|
||||||
|
|
||||||
|
if (tr.is_split()) {
|
||||||
|
assert(split_sides > 0);
|
||||||
|
assert(tr.special_side() >= 0 && tr.special_side() <= 3);
|
||||||
|
data |= (tr.special_side() << (stored_triangles * 4 + 2));
|
||||||
|
++stored_triangles;
|
||||||
|
for (int child_idx=0; child_idx<=split_sides; ++child_idx)
|
||||||
|
serialize_recursive(tr.children[child_idx]);
|
||||||
|
} else {
|
||||||
|
assert(int8_t(tr.get_state()) <= 3);
|
||||||
|
data |= (int8_t(tr.get_state()) << (stored_triangles * 4 + 2));
|
||||||
|
++stored_triangles;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_recursive(i);
|
||||||
|
out[i] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
void TriangleSelector::render_debug(ImGuiWrapper* imgui)
|
void TriangleSelector::render_debug(ImGuiWrapper* imgui)
|
||||||
{
|
{
|
||||||
|
@ -1323,33 +1399,74 @@ void TriangleSelector::render_debug(ImGuiWrapper* imgui)
|
||||||
if (imgui->button("Force garbage collection"))
|
if (imgui->button("Force garbage collection"))
|
||||||
garbage_collect();
|
garbage_collect();
|
||||||
|
|
||||||
|
if (imgui->button("Serialize")) {
|
||||||
|
auto map = serialize();
|
||||||
|
for (auto& [idx, data] : map)
|
||||||
|
std::cout << idx << "\t" << data << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
imgui->end();
|
imgui->end();
|
||||||
|
|
||||||
if (m_show_triangles) {
|
if (! m_show_triangles)
|
||||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
return;
|
||||||
|
|
||||||
::glBegin( GL_TRIANGLES);
|
enum vtype {
|
||||||
for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) {
|
ORIGINAL = 0,
|
||||||
const Triangle& tr = m_triangles[tr_id];
|
SPLIT,
|
||||||
if (! m_show_invalid && ! tr.valid)
|
INVALID
|
||||||
continue;
|
};
|
||||||
|
|
||||||
if (tr.valid)
|
for (auto& va : m_varrays)
|
||||||
::glColor3f(1.f, 0.f, 0.f);
|
va.release_geometry();
|
||||||
else
|
|
||||||
::glColor3f(1.f, 1.f, 0.f);
|
|
||||||
|
|
||||||
if (tr_id < m_orig_size_indices)
|
std::array<int, 3> cnts;
|
||||||
::glColor3f(0.f, 0.f, 1.f);
|
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
::glScalef(1.01f, 1.01f, 1.01f);
|
||||||
::glVertex3f(m_vertices[tr.verts_idxs[i]].v[0],
|
|
||||||
m_vertices[tr.verts_idxs[i]].v[1],
|
for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) {
|
||||||
m_vertices[tr.verts_idxs[i]].v[2]);
|
const Triangle& tr = m_triangles[tr_id];
|
||||||
|
GLIndexedVertexArray* va = nullptr;
|
||||||
|
int* cnt = nullptr;
|
||||||
|
if (tr_id < m_orig_size_indices) {
|
||||||
|
va = &m_varrays[ORIGINAL];
|
||||||
|
cnt = &cnts[ORIGINAL];
|
||||||
}
|
}
|
||||||
::glEnd();
|
else if (tr.valid) {
|
||||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
va = &m_varrays[SPLIT];
|
||||||
|
cnt = &cnts[SPLIT];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (! m_show_invalid)
|
||||||
|
continue;
|
||||||
|
va = &m_varrays[INVALID];
|
||||||
|
cnt = &cnts[INVALID];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
va->push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
||||||
|
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
||||||
|
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
||||||
|
0., 0., 1.);
|
||||||
|
va->push_triangle(*cnt,
|
||||||
|
*cnt+1,
|
||||||
|
*cnt+2);
|
||||||
|
*cnt += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
for (vtype i : {ORIGINAL, SPLIT, INVALID}) {
|
||||||
|
GLIndexedVertexArray& va = m_varrays[i];
|
||||||
|
va.finalize_geometry(true);
|
||||||
|
if (va.has_VBOs()) {
|
||||||
|
switch (i) {
|
||||||
|
case ORIGINAL : ::glColor3f(0.f, 0.f, 1.f); break;
|
||||||
|
case SPLIT : ::glColor3f(1.f, 0.f, 0.f); break;
|
||||||
|
case INVALID : ::glColor3f(1.f, 1.f, 0.f); break;
|
||||||
|
}
|
||||||
|
va.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,9 @@ public:
|
||||||
// Remove all unnecessary data.
|
// Remove all unnecessary data.
|
||||||
void garbage_collect();
|
void garbage_collect();
|
||||||
|
|
||||||
|
// Store the division trees in compact form.
|
||||||
|
std::map<int, int64_t> serialize() const;
|
||||||
|
|
||||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||||
void render_debug(ImGuiWrapper* imgui);
|
void render_debug(ImGuiWrapper* imgui);
|
||||||
bool m_show_triangles{true};
|
bool m_show_triangles{true};
|
||||||
|
@ -86,8 +89,7 @@ private:
|
||||||
// Get info on how it's split.
|
// Get info on how it's split.
|
||||||
bool is_split() const { return number_of_split_sides() != 0; }
|
bool is_split() const { return number_of_split_sides() != 0; }
|
||||||
int number_of_split_sides() const { return number_of_splits; }
|
int number_of_split_sides() const { return number_of_splits; }
|
||||||
int side_to_keep() const { assert(number_of_split_sides() == 2); return special_side_idx; }
|
int special_side() const { assert(is_split()); return special_side_idx; }
|
||||||
int side_to_split() const { assert(number_of_split_sides() == 1); return special_side_idx; }
|
|
||||||
bool was_split_before() const { return old_number_of_splits != 0; }
|
bool was_split_before() const { return old_number_of_splits != 0; }
|
||||||
void forget_history() { old_number_of_splits = 0; }
|
void forget_history() { old_number_of_splits = 0; }
|
||||||
|
|
||||||
|
@ -115,6 +117,10 @@ private:
|
||||||
std::vector<Triangle> m_triangles;
|
std::vector<Triangle> m_triangles;
|
||||||
const TriangleMesh* m_mesh;
|
const TriangleMesh* m_mesh;
|
||||||
|
|
||||||
|
GLIndexedVertexArray m_iva_enforcers;
|
||||||
|
GLIndexedVertexArray m_iva_blockers;
|
||||||
|
std::array<GLIndexedVertexArray, 3> m_varrays;
|
||||||
|
|
||||||
// Number of invalid triangles (to trigger garbage collection).
|
// Number of invalid triangles (to trigger garbage collection).
|
||||||
int m_invalid_triangles;
|
int m_invalid_triangles;
|
||||||
|
|
||||||
|
@ -147,6 +153,7 @@ private:
|
||||||
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;
|
||||||
void push_triangle(int a, int b, int c);
|
void push_triangle(int a, int b, int c);
|
||||||
|
void perform_split(int facet_idx, FacetSupportType old_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue