mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-29 19:53:44 -06:00 
			
		
		
		
	ENH: enable wireframe
This reverts commit ed6e149381240fd83b61da70891127d400f30a39. Change-Id: I010871fcf22322214c627fe907539c0916fa6ff5
This commit is contained in:
		
							parent
							
								
									5e024f75b9
								
							
						
					
					
						commit
						79b5c94f4f
					
				
					 10 changed files with 263 additions and 38 deletions
				
			
		
							
								
								
									
										103
									
								
								resources/shaders/mm_gouraud_130.fs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								resources/shaders/mm_gouraud_130.fs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | ||||||
|  | #version 130 | ||||||
|  | 
 | ||||||
|  | #define INTENSITY_CORRECTION 0.6 | ||||||
|  | 
 | ||||||
|  | // normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) | ||||||
|  | const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); | ||||||
|  | #define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION) | ||||||
|  | #define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION) | ||||||
|  | #define LIGHT_TOP_SHININESS  20.0 | ||||||
|  | 
 | ||||||
|  | // normalized values for (1./1.43, 0.2/1.43, 1./1.43) | ||||||
|  | const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); | ||||||
|  | #define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION) | ||||||
|  | 
 | ||||||
|  | #define INTENSITY_AMBIENT    0.3 | ||||||
|  | 
 | ||||||
|  | const vec3  ZERO    = vec3(0.0, 0.0, 0.0); | ||||||
|  | const float EPSILON = 0.0001; | ||||||
|  | //BBS: add grey and orange | ||||||
|  | //const vec3 GREY = vec3(0.9, 0.9, 0.9); | ||||||
|  | const vec3 ORANGE = vec3(0.8, 0.4, 0.0); | ||||||
|  | 
 | ||||||
|  | uniform vec4 uniform_color; | ||||||
|  | 
 | ||||||
|  | varying vec3 clipping_planes_dots; | ||||||
|  | varying vec4 model_pos; | ||||||
|  | 
 | ||||||
|  | uniform bool volume_mirrored; | ||||||
|  | 
 | ||||||
|  | struct SlopeDetection | ||||||
|  | { | ||||||
|  |     bool actived; | ||||||
|  | 	 float normal_z; | ||||||
|  |     mat3 volume_world_normal_matrix; | ||||||
|  | }; | ||||||
|  | uniform SlopeDetection slope; | ||||||
|  | 
 | ||||||
|  | //BBS: add wireframe logic | ||||||
|  | varying vec3 barycentric_coordinates; | ||||||
|  | float edgeFactor(float lineWidth) { | ||||||
|  |     vec3 d = fwidth(barycentric_coordinates); | ||||||
|  |     vec3 a3 = smoothstep(vec3(0.0), d * lineWidth, barycentric_coordinates); | ||||||
|  |     return min(min(a3.x, a3.y), a3.z); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vec3 wireframe(vec3 fill, vec3 stroke, float lineWidth) { | ||||||
|  |     return mix(stroke, fill, edgeFactor(lineWidth)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vec3 getWireframeColor(vec3 fill) { | ||||||
|  |     float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b; | ||||||
|  |     return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988); | ||||||
|  | } | ||||||
|  | uniform bool show_wireframe; | ||||||
|  | 
 | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     if (any(lessThan(clipping_planes_dots, ZERO))) | ||||||
|  |         discard; | ||||||
|  |     vec3  color = uniform_color.rgb; | ||||||
|  |     float alpha = uniform_color.a; | ||||||
|  | 
 | ||||||
|  |     vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz))); | ||||||
|  | #ifdef FLIP_TRIANGLE_NORMALS | ||||||
|  |     triangle_normal = -triangle_normal; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     vec3 transformed_normal = normalize(slope.volume_world_normal_matrix * triangle_normal); | ||||||
|  |     if (slope.actived && transformed_normal.z < slope.normal_z - EPSILON) { | ||||||
|  |         //color = vec3(0.7, 0.7, 1.0); | ||||||
|  |         color = color * 0.5 + ORANGE * 0.5; | ||||||
|  |         alpha = 1.0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (volume_mirrored) | ||||||
|  |         triangle_normal = -triangle_normal; | ||||||
|  | 
 | ||||||
|  |     // First transform the normal into camera space and normalize the result. | ||||||
|  |     vec3 eye_normal = normalize(gl_NormalMatrix * triangle_normal); | ||||||
|  | 
 | ||||||
|  |     // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. | ||||||
|  |     // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. | ||||||
|  |     float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); | ||||||
|  | 
 | ||||||
|  |     // x = diffuse, y = specular; | ||||||
|  |     vec2 intensity = vec2(0.0, 0.0); | ||||||
|  |     intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; | ||||||
|  |     vec3 position = (gl_ModelViewMatrix * model_pos).xyz; | ||||||
|  |     intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); | ||||||
|  | 
 | ||||||
|  |     // Perform the same lighting calculation for the 2nd light source (no specular applied). | ||||||
|  |     NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); | ||||||
|  |     intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; | ||||||
|  | 
 | ||||||
|  |     if (show_wireframe) { | ||||||
|  |         vec3 wireframeColor = show_wireframe ? getWireframeColor(color) : color; | ||||||
|  |         vec3 triangleColor = wireframe(color, wireframeColor, 1.0); | ||||||
|  |         gl_FragColor = vec4(vec3(intensity.y) + triangleColor * intensity.x, alpha); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								resources/shaders/mm_gouraud_130.vs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								resources/shaders/mm_gouraud_130.vs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | #version 130 | ||||||
|  | 
 | ||||||
|  | const vec3 ZERO = vec3(0.0, 0.0, 0.0); | ||||||
|  | 
 | ||||||
|  | uniform mat4 volume_world_matrix; | ||||||
|  | // Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. | ||||||
|  | uniform vec2 z_range; | ||||||
|  | // Clipping plane - general orientation. Used by the SLA gizmo. | ||||||
|  | uniform vec4 clipping_plane; | ||||||
|  | 
 | ||||||
|  | varying vec3 clipping_planes_dots; | ||||||
|  | varying vec4 model_pos; | ||||||
|  | 
 | ||||||
|  | varying vec3 barycentric_coordinates; | ||||||
|  | 
 | ||||||
|  | struct SlopeDetection | ||||||
|  | { | ||||||
|  |     bool actived; | ||||||
|  | 	float normal_z; | ||||||
|  |     mat3 volume_world_normal_matrix; | ||||||
|  | }; | ||||||
|  | uniform SlopeDetection slope; | ||||||
|  | void main() | ||||||
|  | { | ||||||
|  |     model_pos = gl_Vertex; | ||||||
|  |     // Point in homogenous coordinates. | ||||||
|  |     vec4 world_pos = volume_world_matrix * gl_Vertex; | ||||||
|  | 
 | ||||||
|  |     gl_Position = ftransform(); | ||||||
|  |     // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. | ||||||
|  |     clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); | ||||||
|  | 	 | ||||||
|  |     //compute the Barycentric Coordinates | ||||||
|  |     int vertexMod3 = gl_VertexID % 3; | ||||||
|  |     barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); | ||||||
|  | } | ||||||
|  | @ -869,10 +869,6 @@ void GLVolume::render(bool with_outline) const | ||||||
|             std::array<float, 4> body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
 |             std::array<float, 4> body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
 | ||||||
| 
 | 
 | ||||||
|             shader->set_uniform("uniform_color", body_color); |             shader->set_uniform("uniform_color", body_color); | ||||||
|             //if (GUI::wxGetApp().plater()->is_show_wireframe())
 |  | ||||||
|             //    shader->set_uniform("show_wireframe", true);
 |  | ||||||
|             //else
 |  | ||||||
|             //    shader->set_uniform("show_wireframe", false);
 |  | ||||||
|             shader->set_uniform("is_outline", true); |             shader->set_uniform("is_outline", true); | ||||||
|             glsafe(::glPopMatrix()); |             glsafe(::glPopMatrix()); | ||||||
|             glsafe(::glPushMatrix()); |             glsafe(::glPushMatrix()); | ||||||
|  |  | ||||||
|  | @ -731,6 +731,8 @@ bool GLCanvas3D::init() | ||||||
|     Bed3D::load_render_colors(); |     Bed3D::load_render_colors(); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |     if (wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) | ||||||
|  |         wxGetApp().plater()->enable_wireframe(true); | ||||||
|     m_initialized = true; |     m_initialized = true; | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
|  | @ -2670,10 +2672,8 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) | ||||||
| #endif | #endif | ||||||
|                 } |                 } | ||||||
|                 else  if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_RETURN) { |                 else  if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_RETURN) { | ||||||
| #if !BBL_RELEASE_TO_PUBLIC |  | ||||||
|                     wxGetApp().plater()->toggle_show_wireframe(); |                     wxGetApp().plater()->toggle_show_wireframe(); | ||||||
|                     m_dirty = true; |                     m_dirty = true; | ||||||
| #endif |  | ||||||
|                 } |                 } | ||||||
|                 else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { |                 else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { | ||||||
|                     // Enable switching between 3D and Preview with Tab
 |                     // Enable switching between 3D and Preview with Tab
 | ||||||
|  | @ -5762,6 +5762,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with | ||||||
|             //                GLGizmosManager::EType type = gm.get_current_type();
 |             //                GLGizmosManager::EType type = gm.get_current_type();
 | ||||||
|             if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current()) == nullptr) |             if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current()) == nullptr) | ||||||
|             { |             { | ||||||
|  |                 if (wxGetApp().plater()->is_wireframe_enabled()) { | ||||||
|  |                     if (wxGetApp().plater()->is_show_wireframe()) | ||||||
|  |                         shader->set_uniform("show_wireframe", true); | ||||||
|  |                     else | ||||||
|  |                         shader->set_uniform("show_wireframe", false); | ||||||
|  |                 } | ||||||
|                 //BBS:add assemble view related logic
 |                 //BBS:add assemble view related logic
 | ||||||
|                 // do not cull backfaces to show broken geometry, if any
 |                 // do not cull backfaces to show broken geometry, if any
 | ||||||
|                 m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { |                 m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { | ||||||
|  | @ -5777,7 +5783,6 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with | ||||||
|                 // In case a painting gizmo is open, it should render the painted triangles
 |                 // In case a painting gizmo is open, it should render the painted triangles
 | ||||||
|                 // before transparent objects are rendered. Otherwise they would not be
 |                 // before transparent objects are rendered. Otherwise they would not be
 | ||||||
|                 // visible when inside modifier meshes etc.
 |                 // visible when inside modifier meshes etc.
 | ||||||
| 
 |  | ||||||
| //                GLGizmosManager::EType type = gm.get_current_type();
 | //                GLGizmosManager::EType type = gm.get_current_type();
 | ||||||
|                 if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current())) { |                 if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current())) { | ||||||
|                     shader->stop_using(); |                     shader->stop_using(); | ||||||
|  | @ -5790,6 +5795,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with | ||||||
|         } |         } | ||||||
|         case GLVolumeCollection::ERenderType::Transparent: |         case GLVolumeCollection::ERenderType::Transparent: | ||||||
|         { |         { | ||||||
|  |             if (wxGetApp().plater()->is_wireframe_enabled()) { | ||||||
|  |                 if (wxGetApp().plater()->is_show_wireframe()) | ||||||
|  |                     shader->set_uniform("show_wireframe", true); | ||||||
|  |                 else | ||||||
|  |                     shader->set_uniform("show_wireframe", false); | ||||||
|  |             } | ||||||
|             //BBS:add assemble view related logic
 |             //BBS:add assemble view related logic
 | ||||||
|             m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { |             m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { | ||||||
|                 if (canvas_type == ECanvasType::CanvasAssembleView) { |                 if (canvas_type == ECanvasType::CanvasAssembleView) { | ||||||
|  | @ -5809,6 +5820,10 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with | ||||||
|         } |         } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if (wxGetApp().plater()->is_wireframe_enabled()) { | ||||||
|  |             shader->set_uniform("show_wireframe", false); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         shader->stop_using(); |         shader->stop_using(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ std::pair<bool, std::string> GLShadersManager::init() | ||||||
|     // used to render extrusion and travel paths as lines in gcode preview
 |     // used to render extrusion and travel paths as lines in gcode preview
 | ||||||
|     valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); |     valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); | ||||||
|     // used to render objects in 3d editor
 |     // used to render objects in 3d editor
 | ||||||
|     if (0) { |     if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) { | ||||||
|         valid &= append_shader("gouraud", { "gouraud_130.vs", "gouraud_130.fs" } |         valid &= append_shader("gouraud", { "gouraud_130.vs", "gouraud_130.fs" } | ||||||
| #if ENABLE_ENVIRONMENT_MAP | #if ENABLE_ENVIRONMENT_MAP | ||||||
|             , { "ENABLE_ENVIRONMENT_MAP"sv } |             , { "ENABLE_ENVIRONMENT_MAP"sv } | ||||||
|  | @ -69,10 +69,18 @@ std::pair<bool, std::string> GLShadersManager::init() | ||||||
|     // Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU.
 |     // Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU.
 | ||||||
|     // Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed
 |     // Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed
 | ||||||
|     // triangle normals inside fragment shader have the right direction.
 |     // triangle normals inside fragment shader have the right direction.
 | ||||||
|     if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) |     if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) { | ||||||
|         valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); |         if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) | ||||||
|     else |             valid &= append_shader("mm_gouraud", {"mm_gouraud_130.vs", "mm_gouraud_130.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); | ||||||
|         valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}); |         else | ||||||
|  |             valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |          if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) | ||||||
|  |             valid &= append_shader("mm_gouraud", {"mm_gouraud_130.vs", "mm_gouraud_130.fs"}); | ||||||
|  |         else | ||||||
|  |             valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     //BBS: add shader for outline
 |     //BBS: add shader for outline
 | ||||||
|     valid &= append_shader("outline", { "outline.vs", "outline.fs" }); |     valid &= append_shader("outline", { "outline.vs", "outline.fs" }); | ||||||
|  |  | ||||||
|  | @ -1076,6 +1076,12 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui) | ||||||
|     if (!shader) |     if (!shader) | ||||||
|         return; |         return; | ||||||
|     assert(shader->get_name() == "mm_gouraud"); |     assert(shader->get_name() == "mm_gouraud"); | ||||||
|  |     if (wxGetApp().plater()->is_wireframe_enabled()) { | ||||||
|  |         if (wxGetApp().plater()->is_show_wireframe()) | ||||||
|  |             shader->set_uniform("show_wireframe", true); | ||||||
|  |         else | ||||||
|  |             shader->set_uniform("show_wireframe", false); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { |     for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { | ||||||
|         if (this->has_VBOs(buffer_idx)) { |         if (this->has_VBOs(buffer_idx)) { | ||||||
|  | @ -1130,7 +1136,15 @@ void TriangleSelectorPatch::update_triangles_per_type() | ||||||
| 
 | 
 | ||||||
|         int state = (int)triangle.get_state(); |         int state = (int)triangle.get_state(); | ||||||
|         auto& patch = m_triangle_patches[state]; |         auto& patch = m_triangle_patches[state]; | ||||||
|         patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); |         //patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end());
 | ||||||
|  |         for (int i = 0; i < 3; ++i) { | ||||||
|  |             int j = triangle.verts_idxs[i]; | ||||||
|  |             int index = int(patch.patch_vertices.size()/3); | ||||||
|  |             patch.patch_vertices.emplace_back(m_vertices[j].v(0)); | ||||||
|  |             patch.patch_vertices.emplace_back(m_vertices[j].v(1)); | ||||||
|  |             patch.patch_vertices.emplace_back(m_vertices[j].v(2)); | ||||||
|  |             patch.triangle_indices.emplace_back( index); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1202,7 +1216,15 @@ void TriangleSelectorPatch::update_triangles_per_patch() | ||||||
| 
 | 
 | ||||||
|             if (!visited[current_facet]) { |             if (!visited[current_facet]) { | ||||||
|                 Triangle& triangle = m_triangles[current_facet]; |                 Triangle& triangle = m_triangles[current_facet]; | ||||||
|                 patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); |                 for (int i = 0; i < 3; ++i) { | ||||||
|  |                     int j = triangle.verts_idxs[i]; | ||||||
|  |                     int index = int(patch.patch_vertices.size()/3); | ||||||
|  |                     patch.patch_vertices.emplace_back(m_vertices[j].v(0)); | ||||||
|  |                     patch.patch_vertices.emplace_back(m_vertices[j].v(1)); | ||||||
|  |                     patch.patch_vertices.emplace_back(m_vertices[j].v(2)); | ||||||
|  |                     patch.triangle_indices.emplace_back( index); | ||||||
|  |                 } | ||||||
|  |                 //patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end());
 | ||||||
|                 patch.facet_indices.push_back(current_facet); |                 patch.facet_indices.push_back(current_facet); | ||||||
| 
 | 
 | ||||||
|                 std::vector<int> touching_triangles = get_all_touching_triangles(current_facet, neighbors[current_facet], neighbors_propagated[current_facet]); |                 std::vector<int> touching_triangles = get_all_touching_triangles(current_facet, neighbors[current_facet], neighbors_propagated[current_facet]); | ||||||
|  | @ -1246,16 +1268,16 @@ void TriangleSelectorPatch::set_filter_state(bool is_filter_state) | ||||||
| 
 | 
 | ||||||
| void TriangleSelectorPatch::update_render_data() | void TriangleSelectorPatch::update_render_data() | ||||||
| { | { | ||||||
|     if (m_paint_changed || m_vertices_VBO_id == 0) { |     if (m_paint_changed || (m_triangle_patches.size() == 0)) { | ||||||
|         this->release_geometry(); |         this->release_geometry(); | ||||||
| 
 | 
 | ||||||
|         m_patch_vertices.reserve(m_vertices.size() * 3); |         /*m_patch_vertices.reserve(m_vertices.size() * 3);
 | ||||||
|         for (const Vertex& vr : m_vertices) { |         for (const Vertex& vr : m_vertices) { | ||||||
|             m_patch_vertices.emplace_back(vr.v.x()); |             m_patch_vertices.emplace_back(vr.v.x()); | ||||||
|             m_patch_vertices.emplace_back(vr.v.y()); |             m_patch_vertices.emplace_back(vr.v.y()); | ||||||
|             m_patch_vertices.emplace_back(vr.v.z()); |             m_patch_vertices.emplace_back(vr.v.z()); | ||||||
|         } |         } | ||||||
|         this->finalize_vertices(); |         this->finalize_vertices();*/ | ||||||
| 
 | 
 | ||||||
|         if (m_filter_state) |         if (m_filter_state) | ||||||
|             update_triangles_per_patch(); |             update_triangles_per_patch(); | ||||||
|  | @ -1290,11 +1312,17 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) | ||||||
| { | { | ||||||
|     assert(triangle_indices_idx < this->m_triangle_indices_VBO_ids.size()); |     assert(triangle_indices_idx < this->m_triangle_indices_VBO_ids.size()); | ||||||
|     assert(this->m_triangle_patches.size() == this->m_triangle_indices_VBO_ids.size()); |     assert(this->m_triangle_patches.size() == this->m_triangle_indices_VBO_ids.size()); | ||||||
|     assert(this->m_vertices_VBO_id != 0); |     //assert(this->m_vertices_VBO_id != 0);
 | ||||||
|  |     assert(this->m_triangle_patches.size() == this->m_vertices_VBO_ids.size()); | ||||||
|  |     assert(this->m_vertices_VBO_ids[triangle_indices_idx] != 0); | ||||||
|     assert(this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0); |     assert(this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0); | ||||||
| 
 | 
 | ||||||
|     glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); |     //glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id));
 | ||||||
|     glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float)))); |     //glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float))));
 | ||||||
|  |     if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) { | ||||||
|  |         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_ids[triangle_indices_idx])); | ||||||
|  |         glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); |     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); | ||||||
| 
 | 
 | ||||||
|  | @ -1307,14 +1335,19 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) | ||||||
| 
 | 
 | ||||||
|     glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); |     glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); | ||||||
| 
 | 
 | ||||||
|     glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); |     if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) | ||||||
|  |         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TriangleSelectorPatch::release_geometry() | void TriangleSelectorPatch::release_geometry() | ||||||
| { | { | ||||||
|     if (m_vertices_VBO_id) { |     /*if (m_vertices_VBO_id) {
 | ||||||
|         glsafe(::glDeleteBuffers(1, &m_vertices_VBO_id)); |         glsafe(::glDeleteBuffers(1, &m_vertices_VBO_id)); | ||||||
|         m_vertices_VBO_id = 0; |         m_vertices_VBO_id = 0; | ||||||
|  |     }*/ | ||||||
|  |     for (auto& vertice_VBO_id : m_vertices_VBO_ids) { | ||||||
|  |         glsafe(::glDeleteBuffers(1, &vertice_VBO_id)); | ||||||
|  |         vertice_VBO_id = 0; | ||||||
|     } |     } | ||||||
|     for (auto& triangle_indices_VBO_id : m_triangle_indices_VBO_ids) { |     for (auto& triangle_indices_VBO_id : m_triangle_indices_VBO_ids) { | ||||||
|         glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); |         glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); | ||||||
|  | @ -1325,23 +1358,33 @@ void TriangleSelectorPatch::release_geometry() | ||||||
| 
 | 
 | ||||||
| void TriangleSelectorPatch::finalize_vertices() | void TriangleSelectorPatch::finalize_vertices() | ||||||
| { | { | ||||||
|     assert(m_vertices_VBO_id == 0); |     /*assert(m_vertices_VBO_id == 0);
 | ||||||
|     if (!this->m_patch_vertices.empty()) { |     if (!this->m_patch_vertices.empty()) { | ||||||
|         glsafe(::glGenBuffers(1, &this->m_vertices_VBO_id)); |         glsafe(::glGenBuffers(1, &this->m_vertices_VBO_id)); | ||||||
|         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); |         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); | ||||||
|         glsafe(::glBufferData(GL_ARRAY_BUFFER, this->m_patch_vertices.size() * sizeof(float), this->m_patch_vertices.data(), GL_STATIC_DRAW)); |         glsafe(::glBufferData(GL_ARRAY_BUFFER, this->m_patch_vertices.size() * sizeof(float), this->m_patch_vertices.data(), GL_STATIC_DRAW)); | ||||||
|         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); |         glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); | ||||||
|         this->m_patch_vertices.clear(); |         this->m_patch_vertices.clear(); | ||||||
|     } |     }*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TriangleSelectorPatch::finalize_triangle_indices() | void TriangleSelectorPatch::finalize_triangle_indices() | ||||||
| { | { | ||||||
|  |     m_vertices_VBO_ids.resize(m_triangle_patches.size()); | ||||||
|     m_triangle_indices_VBO_ids.resize(m_triangle_patches.size()); |     m_triangle_indices_VBO_ids.resize(m_triangle_patches.size()); | ||||||
|     m_triangle_indices_sizes.resize(m_triangle_patches.size()); |     m_triangle_indices_sizes.resize(m_triangle_patches.size()); | ||||||
|     assert(std::all_of(m_triangle_indices_VBO_ids.cbegin(), m_triangle_indices_VBO_ids.cend(), [](const auto& ti_VBO_id) { return ti_VBO_id == 0; })); |     assert(std::all_of(m_triangle_indices_VBO_ids.cbegin(), m_triangle_indices_VBO_ids.cend(), [](const auto& ti_VBO_id) { return ti_VBO_id == 0; })); | ||||||
| 
 | 
 | ||||||
|     for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { |     for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { | ||||||
|  |         std::vector<float>& patch_vertices = m_triangle_patches[buffer_idx].patch_vertices; | ||||||
|  |         if (!patch_vertices.empty()) { | ||||||
|  |             glsafe(::glGenBuffers(1, &m_vertices_VBO_ids[buffer_idx])); | ||||||
|  |             glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices_VBO_ids[buffer_idx])); | ||||||
|  |             glsafe(::glBufferData(GL_ARRAY_BUFFER, patch_vertices.size() * sizeof(float), patch_vertices.data(), GL_STATIC_DRAW)); | ||||||
|  |             glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); | ||||||
|  |             patch_vertices.clear(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         std::vector<int>& triangle_indices = m_triangle_patches[buffer_idx].triangle_indices; |         std::vector<int>& triangle_indices = m_triangle_patches[buffer_idx].triangle_indices; | ||||||
|         m_triangle_indices_sizes[buffer_idx] = triangle_indices.size(); |         m_triangle_indices_sizes[buffer_idx] = triangle_indices.size(); | ||||||
|         if (!triangle_indices.empty()) { |         if (!triangle_indices.empty()) { | ||||||
|  |  | ||||||
|  | @ -112,6 +112,7 @@ protected: | ||||||
| 
 | 
 | ||||||
| // BBS
 | // BBS
 | ||||||
| struct TrianglePatch { | struct TrianglePatch { | ||||||
|  |     std::vector<float>  patch_vertices; | ||||||
|     std::vector<int> triangle_indices; |     std::vector<int> triangle_indices; | ||||||
|     std::vector<int> facet_indices; |     std::vector<int> facet_indices; | ||||||
|     EnforcerBlockerType type = EnforcerBlockerType::NONE; |     EnforcerBlockerType type = EnforcerBlockerType::NONE; | ||||||
|  | @ -160,11 +161,15 @@ protected: | ||||||
|     void clear() |     void clear() | ||||||
|     { |     { | ||||||
|         // BBS
 |         // BBS
 | ||||||
|  |         this->m_vertices_VBO_ids.clear(); | ||||||
|         this->m_triangle_indices_VBO_ids.clear(); |         this->m_triangle_indices_VBO_ids.clear(); | ||||||
|         this->m_triangle_indices_sizes.clear(); |         this->m_triangle_indices_sizes.clear(); | ||||||
| 
 | 
 | ||||||
|         for (TrianglePatch& patch : this->m_triangle_patches) |         for (TrianglePatch& patch : this->m_triangle_patches) | ||||||
|  |         { | ||||||
|  |             patch.patch_vertices.clear(); | ||||||
|             patch.triangle_indices.clear(); |             patch.triangle_indices.clear(); | ||||||
|  |         } | ||||||
|         this->m_triangle_patches.clear(); |         this->m_triangle_patches.clear(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -174,7 +179,7 @@ protected: | ||||||
|         return this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0; |         return this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::vector<float>          m_patch_vertices; |     //std::vector<float>          m_patch_vertices;
 | ||||||
|     std::vector<TrianglePatch>  m_triangle_patches; |     std::vector<TrianglePatch>  m_triangle_patches; | ||||||
| 
 | 
 | ||||||
|     // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects,
 |     // When the triangle indices are loaded into the graphics card as Vertex Buffer Objects,
 | ||||||
|  | @ -183,7 +188,8 @@ protected: | ||||||
| 
 | 
 | ||||||
|     // IDs of the Vertex Array Objects, into which the geometry has been loaded.
 |     // IDs of the Vertex Array Objects, into which the geometry has been loaded.
 | ||||||
|     // Zero if the VBOs are not sent to GPU yet.
 |     // Zero if the VBOs are not sent to GPU yet.
 | ||||||
|     unsigned int                m_vertices_VBO_id{ 0 }; |     //unsigned int                m_vertices_VBO_id{ 0 };
 | ||||||
|  |     std::vector<unsigned int>   m_vertices_VBO_ids; | ||||||
|     std::vector<unsigned int>   m_triangle_indices_VBO_ids; |     std::vector<unsigned int>   m_triangle_indices_VBO_ids; | ||||||
| 
 | 
 | ||||||
|     std::vector<std::array<float, 4>> m_ebt_colors; |     std::vector<std::array<float, 4>> m_ebt_colors; | ||||||
|  |  | ||||||
|  | @ -512,9 +512,9 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         if (evt.CmdDown() && evt.GetKeyCode() == 'Q') { wxPostEvent(this, wxCloseEvent(wxEVT_CLOSE_WINDOW)); return;} |         if (evt.CmdDown() && evt.GetKeyCode() == 'Q') { wxPostEvent(this, wxCloseEvent(wxEVT_CLOSE_WINDOW)); return;} | ||||||
|         if (evt.CmdDown() && evt.RawControlDown() && evt.GetKeyCode() == 'F') {  |         if (evt.CmdDown() && evt.RawControlDown() && evt.GetKeyCode() == 'F') { | ||||||
|             EnableFullScreenView(true); |             EnableFullScreenView(true); | ||||||
|             if (IsFullScreen()) {  |             if (IsFullScreen()) { | ||||||
|                 ShowFullScreen(false); |                 ShowFullScreen(false); | ||||||
|             } else { |             } else { | ||||||
|                 ShowFullScreen(true); |                 ShowFullScreen(true); | ||||||
|  | @ -530,7 +530,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
|         if (evt.CmdDown() && evt.GetKeyCode() == ',') |         if (evt.CmdDown() && evt.GetKeyCode() == ',') | ||||||
| #else | #else | ||||||
|         if (evt.CmdDown() && evt.GetKeyCode() == 'P')  |         if (evt.CmdDown() && evt.GetKeyCode() == 'P') | ||||||
| #endif | #endif | ||||||
|         { |         { | ||||||
|             PreferencesDialog dlg(this); |             PreferencesDialog dlg(this); | ||||||
|  | @ -793,10 +793,10 @@ void MainFrame::shutdown() | ||||||
| 
 | 
 | ||||||
| void MainFrame::update_title() | void MainFrame::update_title() | ||||||
| { | { | ||||||
|     return;  |     return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainFrame::update_title_colour_after_set_title()  | void MainFrame::update_title_colour_after_set_title() | ||||||
| { | { | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
|     set_title_colour_after_set_title(GetHandle()); |     set_title_colour_after_set_title(GetHandle()); | ||||||
|  | @ -1241,7 +1241,7 @@ bool MainFrame::can_deselect() const | ||||||
| 
 | 
 | ||||||
| bool MainFrame::can_delete() const | bool MainFrame::can_delete() const | ||||||
| { | { | ||||||
|     return (m_plater != nullptr) && (m_tabpanel->GetSelection() == TabPosition::tp3DEditor) && !m_plater->is_selection_empty();  |     return (m_plater != nullptr) && (m_tabpanel->GetSelection() == TabPosition::tp3DEditor) && !m_plater->is_selection_empty(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MainFrame::can_delete_all() const | bool MainFrame::can_delete_all() const | ||||||
|  | @ -1929,9 +1929,9 @@ void MainFrame::init_menubar_as_editor() | ||||||
|             [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(false); }, "menu_export_gcode", nullptr, |             [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(false); }, "menu_export_gcode", nullptr, | ||||||
|             [this]() {return can_export_gcode(); }, this); |             [this]() {return can_export_gcode(); }, this); | ||||||
|         append_menu_item( |         append_menu_item( | ||||||
|             export_menu, wxID_ANY, _L("Export &Configs") + dots /* + "\tCtrl+E"*/, _L("Export current configuration to files"),  |             export_menu, wxID_ANY, _L("Export &Configs") + dots /* + "\tCtrl+E"*/, _L("Export current configuration to files"), | ||||||
|             [this](wxCommandEvent &) { export_config(); }, |             [this](wxCommandEvent &) { export_config(); }, | ||||||
|             "menu_export_config", nullptr,  |             "menu_export_config", nullptr, | ||||||
|             []() { return true; }, this); |             []() { return true; }, this); | ||||||
| 
 | 
 | ||||||
|         append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), ""); |         append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), ""); | ||||||
|  | @ -2093,6 +2093,11 @@ void MainFrame::init_menubar_as_editor() | ||||||
|             [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, |             [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, | ||||||
|             [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); |             [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); | ||||||
| 
 | 
 | ||||||
|  |         viewMenu->AppendSeparator(); | ||||||
|  |         append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene"), | ||||||
|  |             [this](wxCommandEvent&) { m_plater->toggle_show_wireframe(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this, | ||||||
|  |             [this]() { return m_plater->is_wireframe_enabled(); }, [this]() { return m_plater->is_show_wireframe(); }, this); | ||||||
|  | 
 | ||||||
|         //viewMenu->AppendSeparator();
 |         //viewMenu->AppendSeparator();
 | ||||||
|         ////BBS orthogonal view
 |         ////BBS orthogonal view
 | ||||||
|         //append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"),
 |         //append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"),
 | ||||||
|  | @ -2232,7 +2237,7 @@ void MainFrame::init_menubar_as_editor() | ||||||
|     // Help menu
 |     // Help menu
 | ||||||
|     auto helpMenu = generate_help_menu(); |     auto helpMenu = generate_help_menu(); | ||||||
| 
 | 
 | ||||||
|          | 
 | ||||||
| #ifndef __APPLE__ | #ifndef __APPLE__ | ||||||
|     m_topbar->SetFileMenu(fileMenu); |     m_topbar->SetFileMenu(fileMenu); | ||||||
|     if (editMenu) |     if (editMenu) | ||||||
|  | @ -2240,7 +2245,7 @@ void MainFrame::init_menubar_as_editor() | ||||||
|     if (viewMenu) |     if (viewMenu) | ||||||
|         m_topbar->AddDropDownSubMenu(viewMenu, _L("View")); |         m_topbar->AddDropDownSubMenu(viewMenu, _L("View")); | ||||||
|     //BBS add Preference
 |     //BBS add Preference
 | ||||||
|      | 
 | ||||||
|     append_menu_item( |     append_menu_item( | ||||||
|         m_topbar->GetTopMenu(), wxID_ANY, _L("Preferences") + "\tCtrl+P", _L(""), |         m_topbar->GetTopMenu(), wxID_ANY, _L("Preferences") + "\tCtrl+P", _L(""), | ||||||
|         [this](wxCommandEvent &) { |         [this](wxCommandEvent &) { | ||||||
|  | @ -2424,7 +2429,7 @@ void MainFrame::export_config() | ||||||
|             }, false); |             }, false); | ||||||
|             if (!files.empty()) |             if (!files.empty()) | ||||||
|                 m_last_config = from_u8(files.back()); |                 m_last_config = from_u8(files.back()); | ||||||
|             MessageDialog dlg(this, wxString::Format(_L_PLURAL("There is %d config exported. (Only non-system configs)",  |             MessageDialog dlg(this, wxString::Format(_L_PLURAL("There is %d config exported. (Only non-system configs)", | ||||||
|                 "There are %d configs exported. (Only non-system configs)", files.size()), files.size()), |                 "There are %d configs exported. (Only non-system configs)", files.size()), files.size()), | ||||||
|                               _L("Export result"), wxOK); |                               _L("Export result"), wxOK); | ||||||
|             dlg.ShowModal(); |             dlg.ShowModal(); | ||||||
|  | @ -2464,7 +2469,7 @@ void MainFrame::load_config_file() | ||||||
|         wxGetApp().app_config->update_config_dir(get_dir_name(cfiles.back())); |         wxGetApp().app_config->update_config_dir(get_dir_name(cfiles.back())); | ||||||
|         wxGetApp().load_current_presets(); |         wxGetApp().load_current_presets(); | ||||||
|     } |     } | ||||||
|     MessageDialog dlg2(this, wxString::Format(_L_PLURAL("There is %d config imported. (Only non-system and compatible configs)",  |     MessageDialog dlg2(this, wxString::Format(_L_PLURAL("There is %d config imported. (Only non-system and compatible configs)", | ||||||
|         "There are %d configs imported. (Only non-system and compatible configs)", cfiles.size()), cfiles.size()), |         "There are %d configs imported. (Only non-system and compatible configs)", cfiles.size()), cfiles.size()), | ||||||
|                         _L("Import result"), wxOK); |                         _L("Import result"), wxOK); | ||||||
|     dlg2.ShowModal(); |     dlg2.ShowModal(); | ||||||
|  |  | ||||||
|  | @ -1632,6 +1632,7 @@ struct Plater::priv | ||||||
| 
 | 
 | ||||||
|     bool                        show_render_statistic_dialog{ false }; |     bool                        show_render_statistic_dialog{ false }; | ||||||
|     bool                        show_wireframe{ false }; |     bool                        show_wireframe{ false }; | ||||||
|  |     bool                        wireframe_enabled{ false }; | ||||||
| 
 | 
 | ||||||
|     static const std::regex pattern_bundle; |     static const std::regex pattern_bundle; | ||||||
|     static const std::regex pattern_3mf; |     static const std::regex pattern_3mf; | ||||||
|  | @ -10603,6 +10604,16 @@ bool Plater::is_show_wireframe() const | ||||||
|     return p->show_wireframe; |     return p->show_wireframe; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Plater::enable_wireframe(bool status) | ||||||
|  | { | ||||||
|  |     p->wireframe_enabled = status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Plater::is_wireframe_enabled() const | ||||||
|  | { | ||||||
|  |     return p->wireframe_enabled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /*Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name)
 | /*Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name)
 | ||||||
| : TakeSnapshot(plater, from_u8(snapshot_name)) {} | : TakeSnapshot(plater, from_u8(snapshot_name)) {} | ||||||
|  |  | ||||||
|  | @ -624,6 +624,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void toggle_show_wireframe(); |     void toggle_show_wireframe(); | ||||||
|     bool is_show_wireframe() const; |     bool is_show_wireframe() const; | ||||||
|  |     void enable_wireframe(bool status); | ||||||
|  |     bool is_wireframe_enabled() const; | ||||||
| 
 | 
 | ||||||
| 	// Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu.
 | 	// Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu.
 | ||||||
| 	bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition); | 	bool PopupMenu(wxMenu *menu, const wxPoint& pos = wxDefaultPosition); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 lane.wei
						lane.wei