TriangleSelector - some memory optimization.

Don't store traingle normal, but reference the source triangle,
which stores its normal.
This commit is contained in:
Vojtech Bubnik 2021-06-11 12:27:58 +02:00
parent 74ab3e108e
commit 6bade1b24a
5 changed files with 49 additions and 59 deletions

View file

@ -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;

View file

@ -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);
}; };

View file

@ -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) {

View file

@ -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;
} }

View file

@ -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;
} }