TriangleSelector - some memory optimization.
Don't store traingle normal, but reference the source triangle, which stores its normal.
This commit is contained in:
parent
74ab3e108e
commit
6bade1b24a
5 changed files with 49 additions and 59 deletions
|
@ -112,8 +112,9 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f& hit, int facet_st
|
||||||
assert(neighbor_idx >= 0);
|
assert(neighbor_idx >= 0);
|
||||||
if (neighbor_idx >= 0 && !visited[neighbor_idx]) {
|
if (neighbor_idx >= 0 && !visited[neighbor_idx]) {
|
||||||
// Check if neighbour_facet_idx is satisfies angle in seed_fill_angle and append it to facet_queue if it do.
|
// Check if neighbour_facet_idx is satisfies angle in seed_fill_angle and append it to facet_queue if it do.
|
||||||
double dot_product = m_triangles[neighbor_idx].normal.dot(m_triangles[current_facet].normal);
|
const Vec3f &n1 = m_mesh->stl.facet_start[m_triangles[neighbor_idx].source_triangle].normal;
|
||||||
if (std::clamp(dot_product, 0., 1.) >= facet_angle_limit)
|
const Vec3f &n2 = m_mesh->stl.facet_start[m_triangles[current_facet].source_triangle].normal;
|
||||||
|
if (std::clamp(n1.dot(n2), 0.f, 1.f) >= facet_angle_limit)
|
||||||
facet_queue.push(neighbor_idx);
|
facet_queue.push(neighbor_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,6 +202,8 @@ void TriangleSelector::set_facet(int facet_idx, EnforcerBlockerType state)
|
||||||
m_triangles[facet_idx].set_state(state);
|
m_triangles[facet_idx].set_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called by select_patch()->select_triangle()
|
||||||
|
// to decide which sides of the traingle to split and to actually split it calling set_division() and perform_split().
|
||||||
void TriangleSelector::split_triangle(int facet_idx)
|
void TriangleSelector::split_triangle(int facet_idx)
|
||||||
{
|
{
|
||||||
if (m_triangles[facet_idx].is_split()) {
|
if (m_triangles[facet_idx].is_split()) {
|
||||||
|
@ -475,8 +478,7 @@ void TriangleSelector::reset(const EnforcerBlockerType reset_state)
|
||||||
m_triangles.reserve(m_mesh->its.indices.size());
|
m_triangles.reserve(m_mesh->its.indices.size());
|
||||||
for (size_t i=0; i<m_mesh->its.indices.size(); ++i) {
|
for (size_t i=0; i<m_mesh->its.indices.size(); ++i) {
|
||||||
const stl_triangle_vertex_indices& ind = m_mesh->its.indices[i];
|
const stl_triangle_vertex_indices& ind = m_mesh->its.indices[i];
|
||||||
const Vec3f& normal = m_mesh->stl.facet_start[i].normal;
|
push_triangle(ind[0], ind[1], ind[2], i, reset_state);
|
||||||
push_triangle(ind[0], ind[1], ind[2], normal, reset_state);
|
|
||||||
}
|
}
|
||||||
m_orig_size_vertices = m_vertices.size();
|
m_orig_size_vertices = m_vertices.size();
|
||||||
m_orig_size_indices = m_triangles.size();
|
m_orig_size_indices = m_triangles.size();
|
||||||
|
@ -503,20 +505,20 @@ void TriangleSelector::set_edge_limit(float edge_limit)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TriangleSelector::push_triangle(int a, int b, int c, const Vec3f& normal, const EnforcerBlockerType state)
|
void TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state)
|
||||||
{
|
{
|
||||||
for (int i : {a, b, c}) {
|
for (int i : {a, b, c}) {
|
||||||
assert(i >= 0 && i < int(m_vertices.size()));
|
assert(i >= 0 && i < int(m_vertices.size()));
|
||||||
++m_vertices[i].ref_cnt;
|
++m_vertices[i].ref_cnt;
|
||||||
}
|
}
|
||||||
m_triangles.emplace_back(a, b, c, normal, state);
|
m_triangles.emplace_back(a, b, c, source_triangle, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called by deserialize() and select_patch()->select_triangle()->split_triangle()
|
||||||
void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_state)
|
void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_state)
|
||||||
{
|
{
|
||||||
Triangle* tr = &m_triangles[facet_idx];
|
Triangle* tr = &m_triangles[facet_idx];
|
||||||
const Vec3f normal = tr->normal;
|
int source_triangle = tr->source_triangle;
|
||||||
|
|
||||||
assert(tr->is_split());
|
assert(tr->is_split());
|
||||||
|
|
||||||
|
@ -524,7 +526,7 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat
|
||||||
int sides_to_split = tr->number_of_split_sides();
|
int sides_to_split = tr->number_of_split_sides();
|
||||||
|
|
||||||
// indices of triangle vertices
|
// indices of triangle vertices
|
||||||
std::vector<int> verts_idxs;
|
boost::container::small_vector<int, 6> verts_idxs;
|
||||||
int idx = tr->special_side();
|
int idx = tr->special_side();
|
||||||
for (int j=0; j<3; ++j) {
|
for (int j=0; j<3; ++j) {
|
||||||
verts_idxs.push_back(tr->verts_idxs[idx++]);
|
verts_idxs.push_back(tr->verts_idxs[idx++]);
|
||||||
|
@ -537,8 +539,8 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[1]].v + m_vertices[verts_idxs[2]].v)/2.);
|
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);
|
verts_idxs.insert(verts_idxs.begin()+2, m_vertices.size() - 1);
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2], normal);
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[2], source_triangle);
|
||||||
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0], normal);
|
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[0], source_triangle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -548,9 +550,9 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[0]].v + m_vertices[verts_idxs[3]].v)/2.);
|
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);
|
verts_idxs.insert(verts_idxs.begin()+4, m_vertices.size() - 1);
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4], normal);
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[4], source_triangle);
|
||||||
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4], normal);
|
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[4], source_triangle);
|
||||||
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4], normal);
|
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4], source_triangle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -561,10 +563,10 @@ void TriangleSelector::perform_split(int facet_idx, EnforcerBlockerType old_stat
|
||||||
m_vertices.emplace_back((m_vertices[verts_idxs[4]].v + m_vertices[verts_idxs[0]].v)/2.);
|
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);
|
verts_idxs.insert(verts_idxs.begin()+5, m_vertices.size() - 1);
|
||||||
|
|
||||||
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5], normal);
|
push_triangle(verts_idxs[0], verts_idxs[1], verts_idxs[5], source_triangle);
|
||||||
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3], normal);
|
push_triangle(verts_idxs[1], verts_idxs[2], verts_idxs[3], source_triangle);
|
||||||
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5], normal);
|
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5], source_triangle);
|
||||||
push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5], normal);
|
push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5], source_triangle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -694,6 +696,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
||||||
int processed_children = 0;
|
int processed_children = 0;
|
||||||
int total_children = 0;
|
int total_children = 0;
|
||||||
};
|
};
|
||||||
|
// Depth-first queue of a source mesh triangle and its childern.
|
||||||
// kept outside of the loop to avoid re-allocating inside the loop.
|
// kept outside of the loop to avoid re-allocating inside the loop.
|
||||||
std::vector<ProcessingInfo> parents;
|
std::vector<ProcessingInfo> parents;
|
||||||
|
|
||||||
|
|
|
@ -76,19 +76,21 @@ protected:
|
||||||
public:
|
public:
|
||||||
// Use TriangleSelector::push_triangle to create a new triangle.
|
// Use TriangleSelector::push_triangle to create a new triangle.
|
||||||
// It increments/decrements reference counter on vertices.
|
// It increments/decrements reference counter on vertices.
|
||||||
Triangle(int a, int b, int c, const Vec3f& normal_, const EnforcerBlockerType init_state)
|
Triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType init_state)
|
||||||
: verts_idxs{a, b, c},
|
: verts_idxs{a, b, c},
|
||||||
normal{normal_},
|
source_triangle{source_triangle},
|
||||||
state{init_state},
|
state{init_state}
|
||||||
number_of_splits{0},
|
{
|
||||||
special_side_idx{0},
|
// Initialize bit fields. Default member initializers are not supported by C++17.
|
||||||
old_number_of_splits{0}
|
m_selected_by_seed_fill = false;
|
||||||
{}
|
m_valid = true;
|
||||||
|
old_number_of_splits = 0;
|
||||||
|
}
|
||||||
// Indices into m_vertices.
|
// Indices into m_vertices.
|
||||||
std::array<int, 3> verts_idxs;
|
std::array<int, 3> verts_idxs;
|
||||||
|
|
||||||
// Triangle normal (a shader might need it).
|
// Index of the source triangle at the initial (unsplit) mesh.
|
||||||
Vec3f normal;
|
int source_triangle;
|
||||||
|
|
||||||
// Children triangles.
|
// Children triangles.
|
||||||
std::array<int, 4> children;
|
std::array<int, 4> children;
|
||||||
|
@ -118,16 +120,20 @@ protected:
|
||||||
private:
|
private:
|
||||||
friend TriangleSelector;
|
friend TriangleSelector;
|
||||||
|
|
||||||
int number_of_splits;
|
// Packing the rest of member variables into 4 bytes, aligned to 4 bytes boundary.
|
||||||
int special_side_idx;
|
char number_of_splits { 0 };
|
||||||
|
// Index of a vertex opposite to the split edge (for number_of_splits == 1)
|
||||||
|
// or index of a vertex shared by the two split edges (for number_of_splits == 2).
|
||||||
|
// For number_of_splits == 3, special_side_idx is always zero.
|
||||||
|
char special_side_idx { 0 };
|
||||||
EnforcerBlockerType state;
|
EnforcerBlockerType state;
|
||||||
bool m_selected_by_seed_fill = false;
|
bool m_selected_by_seed_fill : 1;
|
||||||
// Is this triangle valid or marked to be removed?
|
// Is this triangle valid or marked to be removed?
|
||||||
bool m_valid{true};
|
bool m_valid : 1;
|
||||||
|
|
||||||
// How many children were spawned during last split?
|
// How many children were spawned during last split?
|
||||||
// Is not reset on remerging the triangle.
|
// Is not reset on remerging the triangle.
|
||||||
int old_number_of_splits;
|
char old_number_of_splits : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
|
@ -185,7 +191,7 @@ private:
|
||||||
void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant.
|
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;
|
||||||
void push_triangle(int a, int b, int c, const Vec3f &normal, const EnforcerBlockerType state = EnforcerBlockerType{0});
|
void push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state = EnforcerBlockerType{0});
|
||||||
void perform_split(int facet_idx, EnforcerBlockerType old_state);
|
void perform_split(int facet_idx, EnforcerBlockerType old_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -154,8 +154,9 @@ public:
|
||||||
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_geometry(const Vec3d& p, const Vec3d& n) {
|
template<typename Derived, typename Derived2>
|
||||||
push_geometry(p(0), p(1), p(2), n(0), n(1), n(2));
|
inline void push_geometry(const Eigen::MatrixBase<Derived>& p, const Eigen::MatrixBase<Derived2>& n) {
|
||||||
|
push_geometry(float(p(0)), float(p(1)), float(p(2)), float(n(0)), float(n(1)), float(n(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_triangle(int idx1, int idx2, int idx3) {
|
inline void push_triangle(int idx1, int idx2, int idx3) {
|
||||||
|
|
|
@ -434,12 +434,7 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
m_iva_colors[color_idx].push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
m_iva_colors[color_idx].push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
|
||||||
double(tr.normal[0]),
|
|
||||||
double(tr.normal[1]),
|
|
||||||
double(tr.normal[2]));
|
|
||||||
m_iva_colors[color_idx].push_triangle(color_cnt[color_idx], color_cnt[color_idx] + 1, color_cnt[color_idx] + 2);
|
m_iva_colors[color_idx].push_triangle(color_cnt[color_idx], color_cnt[color_idx] + 1, color_cnt[color_idx] + 2);
|
||||||
color_cnt[color_idx] += 3;
|
color_cnt[color_idx] += 3;
|
||||||
}
|
}
|
||||||
|
@ -449,12 +444,7 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui)
|
||||||
if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) continue;
|
if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) continue;
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
m_iva_seed_fill.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
|
||||||
double(tr.normal[0]),
|
|
||||||
double(tr.normal[1]),
|
|
||||||
double(tr.normal[2]));
|
|
||||||
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
|
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
|
||||||
seed_fill_cnt += 3;
|
seed_fill_cnt += 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,12 +598,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||||
: blc_cnt;
|
: blc_cnt;
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
va.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
va.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
|
||||||
double(tr.normal[0]),
|
|
||||||
double(tr.normal[1]),
|
|
||||||
double(tr.normal[2]));
|
|
||||||
va.push_triangle(cnt, cnt + 1, cnt + 2);
|
va.push_triangle(cnt, cnt + 1, cnt + 2);
|
||||||
cnt += 3;
|
cnt += 3;
|
||||||
}
|
}
|
||||||
|
@ -613,12 +608,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
m_iva_seed_fill.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
|
||||||
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
|
||||||
double(tr.normal[0]),
|
|
||||||
double(tr.normal[1]),
|
|
||||||
double(tr.normal[2]));
|
|
||||||
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
|
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
|
||||||
seed_fill_cnt += 3;
|
seed_fill_cnt += 3;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue