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);
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.
double dot_product = m_triangles[neighbor_idx].normal.dot(m_triangles[current_facet].normal);
if (std::clamp(dot_product, 0., 1.) >= facet_angle_limit)
const Vec3f &n1 = m_mesh->stl.facet_start[m_triangles[neighbor_idx].source_triangle].normal;
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);
}
}
@ -201,6 +202,8 @@ void TriangleSelector::set_facet(int facet_idx, EnforcerBlockerType 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)
{
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());
for (size_t i=0; i<m_mesh->its.indices.size(); ++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], normal, reset_state);
push_triangle(ind[0], ind[1], ind[2], i, reset_state);
}
m_orig_size_vertices = m_vertices.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}) {
assert(i >= 0 && i < int(m_vertices.size()));
++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)
{
Triangle* tr = &m_triangles[facet_idx];
const Vec3f normal = tr->normal;
int source_triangle = tr->source_triangle;
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();
// indices of triangle vertices
std::vector<int> verts_idxs;
boost::container::small_vector<int, 6> verts_idxs;
int idx = tr->special_side();
for (int j=0; j<3; ++j) {
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.);
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[2], verts_idxs[3], verts_idxs[0], 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], source_triangle);
break;
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.);
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[1], verts_idxs[2], verts_idxs[4], normal);
push_triangle(verts_idxs[2], verts_idxs[3], 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], source_triangle);
push_triangle(verts_idxs[2], verts_idxs[3], verts_idxs[4], source_triangle);
break;
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.);
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[1], verts_idxs[2], verts_idxs[3], normal);
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5], normal);
push_triangle(verts_idxs[1], verts_idxs[3], 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], source_triangle);
push_triangle(verts_idxs[3], verts_idxs[4], verts_idxs[5], source_triangle);
push_triangle(verts_idxs[1], verts_idxs[3], verts_idxs[5], source_triangle);
break;
default:
@ -694,6 +696,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
int processed_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.
std::vector<ProcessingInfo> parents;

View file

@ -76,19 +76,21 @@ protected:
public:
// Use TriangleSelector::push_triangle to create a new triangle.
// 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},
normal{normal_},
state{init_state},
number_of_splits{0},
special_side_idx{0},
old_number_of_splits{0}
{}
source_triangle{source_triangle},
state{init_state}
{
// Initialize bit fields. Default member initializers are not supported by C++17.
m_selected_by_seed_fill = false;
m_valid = true;
old_number_of_splits = 0;
}
// Indices into m_vertices.
std::array<int, 3> verts_idxs;
// Triangle normal (a shader might need it).
Vec3f normal;
// Index of the source triangle at the initial (unsplit) mesh.
int source_triangle;
// Children triangles.
std::array<int, 4> children;
@ -118,16 +120,20 @@ protected:
private:
friend TriangleSelector;
int number_of_splits;
int special_side_idx;
// Packing the rest of member variables into 4 bytes, aligned to 4 bytes boundary.
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;
bool m_selected_by_seed_fill = false;
bool m_selected_by_seed_fill : 1;
// 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?
// Is not reset on remerging the triangle.
int old_number_of_splits;
char old_number_of_splits : 2;
};
struct Vertex {
@ -185,7 +191,7 @@ private:
void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant.
bool is_pointer_in_triangle(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);
};

View file

@ -154,8 +154,9 @@ public:
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
}
inline void push_geometry(const Vec3d& p, const Vec3d& n) {
push_geometry(p(0), p(1), p(2), n(0), n(1), n(2));
template<typename Derived, typename Derived2>
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) {

View file

@ -434,12 +434,7 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui)
continue;
for (int i = 0; i < 3; ++i)
m_iva_colors[color_idx].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]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
m_iva_colors[color_idx].push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
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;
}
@ -449,12 +444,7 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui)
if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) continue;
for (int i = 0; i < 3; ++i)
m_iva_seed_fill.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]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
seed_fill_cnt += 3;
}

View file

@ -598,12 +598,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
: blc_cnt;
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]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
va.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
va.push_triangle(cnt, cnt + 1, cnt + 2);
cnt += 3;
}
@ -613,12 +608,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
continue;
for (int i = 0; i < 3; ++i)
m_iva_seed_fill.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]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
seed_fill_cnt += 3;
}