mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	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; | ||||
|     } | ||||
| 
 | ||||
|     // indices of triangle vertices
 | ||||
|     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
 | ||||
|     // Save how the triangle will be split. Second argument makes sense only for one
 | ||||
|     // or two split sides, otherwise the value is ignored.
 | ||||
|     tr->set_division(sides_to_split.size(), | ||||
|         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.
 | ||||
|     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); | ||||
|     } | ||||
|     perform_split(facet_idx, old_type); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1253,22 +1202,45 @@ void TriangleSelector::render(ImGuiWrapper* imgui) | |||
|     ::glScalef(1.005f, 1.005f, 1.005f); | ||||
| 
 | ||||
| 
 | ||||
|     ::glBegin( GL_TRIANGLES); | ||||
|     int enf_cnt = 0; | ||||
|     int blc_cnt = 0; | ||||
| 
 | ||||
|     for (const Triangle& tr : m_triangles) { | ||||
|         if (! tr.valid || tr.is_split() || tr.get_state() == FacetSupportType::NONE) | ||||
|             continue; | ||||
| 
 | ||||
|         if (tr.get_state() == FacetSupportType::ENFORCER) | ||||
|             ::glColor4f(0.f, 0.f, 1.f, 0.2f); | ||||
|         else | ||||
|             ::glColor4f(1.f, 0.f, 0.f, 0.2f); | ||||
|         GLIndexedVertexArray& va = tr.get_state() == FacetSupportType::ENFORCER | ||||
|                                    ? m_iva_enforcers | ||||
|                                    : m_iva_blockers; | ||||
|         int& cnt = tr.get_state() == FacetSupportType::ENFORCER | ||||
|                 ? enf_cnt | ||||
|                 : blc_cnt; | ||||
| 
 | ||||
|         for (int i=0; i<3; ++i) | ||||
|             ::glVertex3f(m_vertices[tr.verts_idxs[i]].v[0], | ||||
|                          m_vertices[tr.verts_idxs[i]].v[1], | ||||
|                          m_vertices[tr.verts_idxs[i]].v[2]); | ||||
|             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; | ||||
|     } | ||||
|     ::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 | ||||
|     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 | ||||
| void TriangleSelector::render_debug(ImGuiWrapper* imgui) | ||||
| { | ||||
|  | @ -1323,33 +1399,74 @@ void TriangleSelector::render_debug(ImGuiWrapper* imgui) | |||
|     if (imgui->button("Force garbage collection")) | ||||
|         garbage_collect(); | ||||
| 
 | ||||
|     if (imgui->button("Serialize")) { | ||||
|         auto map = serialize(); | ||||
|         for (auto& [idx, data] : map) | ||||
|             std::cout << idx << "\t" << data << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     imgui->end(); | ||||
| 
 | ||||
|     if (m_show_triangles) { | ||||
|         ::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); | ||||
|     if (! m_show_triangles) | ||||
|         return; | ||||
| 
 | ||||
|         ::glBegin( GL_TRIANGLES); | ||||
|         for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) { | ||||
|             const Triangle& tr = m_triangles[tr_id]; | ||||
|             if (! m_show_invalid && ! tr.valid) | ||||
|                 continue; | ||||
|     enum vtype { | ||||
|         ORIGINAL = 0, | ||||
|         SPLIT, | ||||
|         INVALID | ||||
|     }; | ||||
| 
 | ||||
|             if (tr.valid) | ||||
|                 ::glColor3f(1.f, 0.f, 0.f); | ||||
|             else | ||||
|                 ::glColor3f(1.f, 1.f, 0.f); | ||||
|     for (auto& va : m_varrays) | ||||
|         va.release_geometry(); | ||||
| 
 | ||||
|             if (tr_id < m_orig_size_indices) | ||||
|                 ::glColor3f(0.f, 0.f, 1.f); | ||||
|     std::array<int, 3> cnts; | ||||
| 
 | ||||
|             for (int i=0; i<3; ++i) | ||||
|                 ::glVertex3f(m_vertices[tr.verts_idxs[i]].v[0], | ||||
|                              m_vertices[tr.verts_idxs[i]].v[1], | ||||
|                              m_vertices[tr.verts_idxs[i]].v[2]); | ||||
|     ::glScalef(1.01f, 1.01f, 1.01f); | ||||
| 
 | ||||
|     for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) { | ||||
|         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(); | ||||
|         ::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); | ||||
|         else if (tr.valid) { | ||||
|             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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,6 +48,9 @@ public: | |||
|     // Remove all unnecessary data.
 | ||||
|     void garbage_collect(); | ||||
| 
 | ||||
|     // Store the division trees in compact form.
 | ||||
|     std::map<int, int64_t> serialize() const; | ||||
| 
 | ||||
| #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG | ||||
|     void render_debug(ImGuiWrapper* imgui); | ||||
|     bool m_show_triangles{true}; | ||||
|  | @ -86,8 +89,7 @@ private: | |||
|         // Get info on how it's split.
 | ||||
|         bool is_split() const { return number_of_split_sides() != 0; } | ||||
|         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 side_to_split() const { assert(number_of_split_sides() == 1); return special_side_idx; } | ||||
|         int special_side() const  { assert(is_split()); return special_side_idx; } | ||||
|         bool was_split_before() const { return old_number_of_splits != 0; } | ||||
|         void forget_history() { old_number_of_splits = 0; } | ||||
| 
 | ||||
|  | @ -115,6 +117,10 @@ private: | |||
|     std::vector<Triangle> m_triangles; | ||||
|     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).
 | ||||
|     int m_invalid_triangles; | ||||
| 
 | ||||
|  | @ -147,6 +153,7 @@ private: | |||
|     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); | ||||
|     void perform_split(int facet_idx, FacetSupportType old_state); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Matena
						Lukas Matena