mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3
This commit is contained in:
		
							parent
							
								
									e630332e24
								
							
						
					
					
						commit
						7f2d1522ce
					
				
					 6 changed files with 351 additions and 13 deletions
				
			
		|  | @ -37,24 +37,33 @@ | |||
| 
 | ||||
| 
 | ||||
| //====================
 | ||||
| // 2.4.0.alpha0 techs
 | ||||
| // 2.4.0.alpha1 techs
 | ||||
| //====================
 | ||||
| #define ENABLE_2_4_0_ALPHA0 1 | ||||
| #define ENABLE_2_4_0_ALPHA1 1 | ||||
| 
 | ||||
| // Enable delayed rendering of transparent volumes
 | ||||
| #define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable the fix of importing color print view from gcode files into GCodeViewer
 | ||||
| #define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable drawing contours, at cut level, for sinking volumes
 | ||||
| #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable implementation of retract acceleration in gcode processor
 | ||||
| #define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable the fix for exporting and importing to/from 3mf file of mirrored volumes
 | ||||
| #define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable rendering seams (and other options) in preview using models
 | ||||
| #define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA1) | ||||
| // Enable save and save as commands to be enabled also when the plater is empty and allow to load empty projects
 | ||||
| #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) | ||||
| #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA1) | ||||
| 
 | ||||
| 
 | ||||
| //====================
 | ||||
| // 2.4.0.alpha2 techs
 | ||||
| //====================
 | ||||
| #define ENABLE_2_4_0_ALPHA2 1 | ||||
| 
 | ||||
| // Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3
 | ||||
| #define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) | ||||
| 
 | ||||
| 
 | ||||
| #endif // _prusaslicer_technologies_h_
 | ||||
|  |  | |||
|  | @ -807,6 +807,25 @@ void GCodeViewer::render() | |||
|             case EMoveType::Unretract: | ||||
|             case EMoveType::Seam: { | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|                 if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { | ||||
|                     buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; | ||||
|                     buffer.shader = "gouraud_light_instanced"; | ||||
|                     buffer.model.model.init_from(diamond(16)); | ||||
|                     buffer.model.color = option_color(type); | ||||
|                     buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; | ||||
|                 } | ||||
|                 else { | ||||
|                     buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; | ||||
|                     buffer.vertices.format = VBuffer::EFormat::PositionNormal3; | ||||
|                     buffer.shader = "gouraud_light"; | ||||
| 
 | ||||
|                     buffer.model.data = diamond(16); | ||||
|                     buffer.model.color = option_color(type); | ||||
|                     buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; | ||||
|                 } | ||||
|                 break; | ||||
| #else | ||||
|                 if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { | ||||
|                     buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; | ||||
|                     buffer.shader = "gouraud_light_instanced"; | ||||
|  | @ -819,6 +838,7 @@ void GCodeViewer::render() | |||
|                     buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; | ||||
|                 } | ||||
|                 break; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #else | ||||
|                 buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; | ||||
|                 buffer.vertices.format = VBuffer::EFormat::Position; | ||||
|  | @ -1221,7 +1241,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|         unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { | ||||
|             if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { | ||||
|                 // add starting index
 | ||||
|                 indices.push_back(static_cast<unsigned int>(indices.size())); | ||||
|                 indices.push_back(static_cast<IBufferType>(indices.size())); | ||||
|                 buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1); | ||||
|                 buffer.paths.back().sub_paths.front().first.position = prev.position; | ||||
|             } | ||||
|  | @ -1229,11 +1249,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             Path& last_path = buffer.paths.back(); | ||||
|             if (last_path.sub_paths.front().first.i_id != last_path.sub_paths.back().last.i_id) { | ||||
|                 // add previous index
 | ||||
|                 indices.push_back(static_cast<unsigned int>(indices.size())); | ||||
|                 indices.push_back(static_cast<IBufferType>(indices.size())); | ||||
|             } | ||||
| 
 | ||||
|             // add current index
 | ||||
|             indices.push_back(static_cast<unsigned int>(indices.size())); | ||||
|             indices.push_back(static_cast<IBufferType>(indices.size())); | ||||
|             last_path.sub_paths.back().last = { ibuffer_id, indices.size() - 1, move_id, curr.position }; | ||||
|     }; | ||||
| 
 | ||||
|  | @ -1436,7 +1456,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|     }; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|     // format data into the buffers to be rendered as model
 | ||||
|     // format data into the buffers to be rendered as instanced model
 | ||||
|     auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { | ||||
|         // append position
 | ||||
|         instances.push_back(curr.position.x()); | ||||
|  | @ -1450,6 +1470,49 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|         // append id
 | ||||
|         instances_ids.push_back(move_id); | ||||
|     }; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|     // format data into the buffers to be rendered as batched model
 | ||||
|     auto add_vertices_as_model_batch = [](const GCodeProcessor::MoveVertex& curr, const GLModel::InitializationData& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { | ||||
|         const double width = static_cast<double>(1.5f * curr.width); | ||||
|         const double height = static_cast<double>(1.5f * curr.height); | ||||
| 
 | ||||
|         const Transform3d trafo = Geometry::assemble_transform(curr.position.cast<double>(), Vec3d::Zero(), { width, width, height }); | ||||
|         const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); | ||||
| 
 | ||||
|         for (const auto& entity : data.entities) { | ||||
|             // append vertices
 | ||||
|             for (size_t i = 0; i < entity.positions.size(); ++i) { | ||||
|                 // append position
 | ||||
|                 const Vec3d position = trafo * entity.positions[i].cast<double>(); | ||||
|                 vertices.push_back(static_cast<float>(position.x())); | ||||
|                 vertices.push_back(static_cast<float>(position.y())); | ||||
|                 vertices.push_back(static_cast<float>(position.z())); | ||||
| 
 | ||||
|                 // append normal
 | ||||
|                 const Vec3d normal = normal_matrix * entity.normals[i].cast<double>(); | ||||
|                 vertices.push_back(static_cast<float>(normal.x())); | ||||
|                 vertices.push_back(static_cast<float>(normal.y())); | ||||
|                 vertices.push_back(static_cast<float>(normal.z())); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // append instance position
 | ||||
|         instances.push_back(curr.position.x()); | ||||
|         instances.push_back(curr.position.y()); | ||||
|         instances.push_back(curr.position.z()); | ||||
|         // append instance id
 | ||||
|         instances_ids.push_back(move_id); | ||||
|     }; | ||||
| 
 | ||||
|     auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { | ||||
|         for (const auto& entity : data.entities) { | ||||
|             for (size_t i = 0; i < entity.indices.size(); ++i) { | ||||
|                 indices.push_back(static_cast<IBufferType>(entity.indices[i] + base_index)); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
| 
 | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|  | @ -1533,7 +1596,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
| 
 | ||||
|         // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer
 | ||||
|         // add another vertex buffer
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); | ||||
|         if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { | ||||
| #else | ||||
|         if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             v_multibuffer.push_back(VertexBuffer()); | ||||
|             if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { | ||||
|                 Path& last_path = t_buffer.paths.back(); | ||||
|  | @ -1550,6 +1618,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|         case TBuffer::ERenderPrimitiveType::Line:     { add_vertices_as_line(prev, curr, v_buffer); break; } | ||||
|         case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, i); break; } | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         case TBuffer::ERenderPrimitiveType::InstancedModel: | ||||
|         { | ||||
|             add_model_instance(curr, inst_buffer, inst_id_buffer, i); | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|             ++m_statistics.instances_count; | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
|             break; | ||||
|         } | ||||
|         case TBuffer::ERenderPrimitiveType::BatchedModel: | ||||
|         { | ||||
|             add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|             ++m_statistics.batched_count; | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
|             break; | ||||
|         } | ||||
| #else | ||||
|         case TBuffer::ERenderPrimitiveType::Model: | ||||
|         { | ||||
|             add_model_instance(curr, inst_buffer, inst_id_buffer, i); | ||||
|  | @ -1559,6 +1645,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             break; | ||||
|         } | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|         } | ||||
| 
 | ||||
|         // collect options zs for later use
 | ||||
|  | @ -1741,6 +1828,23 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|     for (size_t i = 0; i < m_buffers.size(); ++i) { | ||||
|         TBuffer& t_buffer = m_buffers[i]; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { | ||||
|             const InstanceBuffer& inst_buffer = instances[i]; | ||||
|             if (!inst_buffer.empty()) { | ||||
|                 t_buffer.model.instances.buffer = inst_buffer; | ||||
|                 t_buffer.model.instances.s_ids = instances_ids[i]; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
|                 const InstanceBuffer& inst_buffer = instances[i]; | ||||
|                 if (!inst_buffer.empty()) { | ||||
|                     t_buffer.model.instances.buffer = inst_buffer; | ||||
|                     t_buffer.model.instances.s_ids = instances_ids[i]; | ||||
|                 } | ||||
|             } | ||||
| #else | ||||
|         if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { | ||||
|             const InstanceBuffer& inst_buffer = instances[i]; | ||||
|             if (!inst_buffer.empty()) { | ||||
|  | @ -1749,6 +1853,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             } | ||||
|         } | ||||
|         else { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|             const MultiVertexBuffer& v_multibuffer = vertices[i]; | ||||
|             for (const VertexBuffer& v_buffer : v_multibuffer) { | ||||
|  | @ -1842,10 +1947,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
| 
 | ||||
|         // if adding the indices for the current segment exceeds the threshold size of the current index buffer
 | ||||
|         // create another index buffer
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         size_t indiced_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.indices_size_bytes() : t_buffer.max_indices_per_segment_size_bytes(); | ||||
|         if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - indiced_size_to_add) { | ||||
| #else | ||||
|         if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.max_indices_per_segment_size_bytes()) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             i_multibuffer.push_back(IndexBuffer()); | ||||
|             vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && | ||||
|                 t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
| #else | ||||
|             if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 Path& last_path = t_buffer.paths.back(); | ||||
|                 last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1); | ||||
|             } | ||||
|  | @ -1853,14 +1968,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
| 
 | ||||
|         // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer
 | ||||
|         // create another index buffer
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); | ||||
|         if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { | ||||
| #else | ||||
|         if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             i_multibuffer.push_back(IndexBuffer()); | ||||
| 
 | ||||
|             ++curr_vertex_buffer.first; | ||||
|             curr_vertex_buffer.second = 0; | ||||
|             vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && | ||||
|                 t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
| #else | ||||
|             if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 Path& last_path = t_buffer.paths.back(); | ||||
|                 last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1); | ||||
|             } | ||||
|  | @ -1884,6 +2009,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|             add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i); | ||||
|             break; | ||||
|         } | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         case TBuffer::ERenderPrimitiveType::BatchedModel: { | ||||
|             add_indices_as_model_batch(t_buffer.model.data, i_buffer, curr_vertex_buffer.second); | ||||
|             curr_vertex_buffer.second += t_buffer.model.data.vertices_count(); | ||||
|             break; | ||||
|         } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|         default: { break; } | ||||
|         } | ||||
|     } | ||||
|  | @ -1898,7 +2030,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) | |||
|     for (size_t i = 0; i < m_buffers.size(); ++i) { | ||||
|         TBuffer& t_buffer = m_buffers[i]; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel) { | ||||
| #else | ||||
|         if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|             const MultiIndexBuffer& i_multibuffer = indices[i]; | ||||
|             for (const IndexBuffer& i_buffer : i_multibuffer) { | ||||
|  | @ -2174,7 +2310,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool | |||
|             continue; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || | ||||
|             buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
| #else | ||||
|         if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             for (size_t id : buffer.model.instances.s_ids) { | ||||
|                 if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) | ||||
|                     continue; | ||||
|  | @ -2239,7 +2380,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool | |||
|     bool found = false; | ||||
|     for (const TBuffer& buffer : m_buffers) { | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || | ||||
|             buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
| #else | ||||
|         if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { | ||||
|                 if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { | ||||
|                     size_t offset = i * buffer.model.instances.instance_size_floats(); | ||||
|  | @ -2400,10 +2546,19 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool | |||
|     } | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|     // second pass: for buffers using instanced and batched models, update the instances render ranges
 | ||||
| #else | ||||
|     // second pass: for buffers using instanced models, update the instances render ranges
 | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|     for (size_t b = 0; b < m_buffers.size(); ++b) { | ||||
|         TBuffer& buffer = const_cast<TBuffer&>(m_buffers[b]); | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel && | ||||
|             buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) | ||||
| #else | ||||
|         if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             continue; | ||||
| 
 | ||||
|         buffer.model.instances.render_ranges.reset(); | ||||
|  | @ -2689,6 +2844,66 @@ void GCodeViewer::render_toolpaths() | |||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|     auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { | ||||
| #else | ||||
|     auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
| 
 | ||||
|         struct Range | ||||
|         { | ||||
|             unsigned int first; | ||||
|             unsigned int last; | ||||
|             bool intersects(const Range& other) const { return (other.last < first || other.first > last) ? false : true; } | ||||
|         }; | ||||
|         Range buffer_range = { 0, 0 }; | ||||
|         size_t indices_per_instance = buffer.model.data.indices_count(); | ||||
| 
 | ||||
|         for (size_t j = 0; j < buffer.indices.size(); ++j) { | ||||
|             const IBuffer& i_buffer = buffer.indices[j]; | ||||
|             buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; | ||||
|             glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); | ||||
|             glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); | ||||
|             glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); | ||||
|             bool has_normals = buffer.vertices.normal_size_floats() > 0; | ||||
|             if (has_normals) { | ||||
|                 glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); | ||||
|                 glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); | ||||
|             } | ||||
| 
 | ||||
|             glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); | ||||
| 
 | ||||
|             for (auto& range : buffer.model.instances.render_ranges.ranges) { | ||||
|                 Range range_range = { range.offset, range.offset + range.count }; | ||||
|                 if (range_range.intersects(buffer_range)) { | ||||
|                     shader.set_uniform("uniform_color", range.color); | ||||
|                     unsigned int offset = (range_range.first > buffer_range.first) ? range_range.first - buffer_range.first : 0; | ||||
|                     size_t offset_bytes = static_cast<size_t>(offset) * indices_per_instance * sizeof(IBufferType); | ||||
|                     Range render_range = { std::max(range_range.first, buffer_range.first), std::min(range_range.last, buffer_range.last) }; | ||||
|                     size_t count = static_cast<size_t>(render_range.last - render_range.first) * indices_per_instance; | ||||
|                     if (count > 0) { | ||||
|                         glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)count, GL_UNSIGNED_SHORT, (const void*)offset_bytes)); | ||||
| #if ENABLE_GCODE_VIEWER_STATISTICS | ||||
|                         ++m_statistics.gl_batched_models_calls_count; | ||||
| #endif // ENABLE_GCODE_VIEWER_STATISTICS
 | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); | ||||
| 
 | ||||
|             if (has_normals) | ||||
|                 glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); | ||||
| 
 | ||||
|             glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); | ||||
|             glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); | ||||
| 
 | ||||
|             buffer_range.first = buffer_range.last; | ||||
|         } | ||||
|     }; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
| 
 | ||||
|     auto line_width = [](double zoom) { | ||||
|  | @ -2712,11 +2927,22 @@ void GCodeViewer::render_toolpaths() | |||
|             shader->start_using(); | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { | ||||
| #else | ||||
|             if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 shader->set_uniform("emission_factor", 0.25f); | ||||
|                 render_as_instanced_model(buffer, *shader); | ||||
|                 shader->set_uniform("emission_factor", 0.0f); | ||||
|             } | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { | ||||
|                 shader->set_uniform("emission_factor", 0.25f); | ||||
|                 render_as_batched_model(buffer, *shader); | ||||
|                 shader->set_uniform("emission_factor", 0.0f); | ||||
|             } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             else { | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|                 for (size_t j = 0; j < buffer.indices.size(); ++j) { | ||||
|  | @ -2882,6 +3108,7 @@ void GCodeViewer::render_legend(float& legend_height) | |||
|         } | ||||
|         case EItemType::Circle: { | ||||
|             ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); | ||||
| #if !ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             if (m_buffers[buffer_id(EMoveType::Retract)].shader == "options_120") { | ||||
|                 draw_list->AddCircleFilled(center, 0.5f * icon_size, | ||||
|                     ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); | ||||
|  | @ -2891,6 +3118,7 @@ void GCodeViewer::render_legend(float& legend_height) | |||
|                 draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); | ||||
|             } | ||||
|             else | ||||
| #endif // !ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|                 draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); | ||||
| 
 | ||||
|             break; | ||||
|  | @ -3756,7 +3984,11 @@ void GCodeViewer::render_statistics() | |||
|         add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); | ||||
|         add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|         ImGui::Separator(); | ||||
|         add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         add_counter(std::string("Batched models:"), m_statistics.gl_batched_models_calls_count); | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -3788,6 +4020,9 @@ void GCodeViewer::render_statistics() | |||
|         add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count); | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|         add_counter(std::string("Instances count:"), m_statistics.instances_count); | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         add_counter(std::string("Batched count:"), m_statistics.batched_count); | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|         ImGui::Separator(); | ||||
|         add_counter(std::string("VBuffers count:"), m_statistics.vbuffers_count); | ||||
|  |  | |||
|  | @ -105,9 +105,16 @@ class GCodeViewer | |||
|     }; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|     // buffer containing instances data used to render a toolpaths using instanced or batched models
 | ||||
|     // instance record format:
 | ||||
|     // instanced models: 5 floats -> position.x|position.y|position.z|width|height (which are sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced())
 | ||||
|     // batched models:   3 floats -> position.x|position.y|position.z
 | ||||
| #else | ||||
|     // buffer containing instances data used to render a toolpaths using instanced models
 | ||||
|     // instance record format: 5 floats -> position.x|position.y|position.z|width|height
 | ||||
|     // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced()
 | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|     struct InstanceVBuffer | ||||
|     { | ||||
|         // ranges used to render only subparts of the intances
 | ||||
|  | @ -130,6 +137,16 @@ class GCodeViewer | |||
|             void reset(); | ||||
|         }; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         enum class EFormat : unsigned char | ||||
|         { | ||||
|             InstancedModel, | ||||
|             BatchedModel | ||||
|         }; | ||||
| 
 | ||||
|         EFormat format; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| 
 | ||||
|         // cpu-side buffer containing all instances data
 | ||||
|         InstanceBuffer buffer; | ||||
|         // indices of the moves for all instances
 | ||||
|  | @ -138,7 +155,18 @@ class GCodeViewer | |||
| 
 | ||||
|         size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         size_t instance_size_floats() const { | ||||
|             switch (format) | ||||
|             { | ||||
|             case EFormat::InstancedModel: { return 5; } | ||||
|             case EFormat::BatchedModel: { return 3; } | ||||
|             default: { return 0; } | ||||
|             } | ||||
|         } | ||||
| #else | ||||
|         size_t instance_size_floats() const { return 5; } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|         size_t instance_size_bytes() const { return instance_size_floats() * sizeof(float); } | ||||
| 
 | ||||
|         void reset(); | ||||
|  | @ -280,7 +308,12 @@ class GCodeViewer | |||
|             Line, | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|             Triangle, | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             InstancedModel, | ||||
|             BatchedModel | ||||
| #else | ||||
|             Model | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #else | ||||
|             Triangle | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|  | @ -298,6 +331,9 @@ class GCodeViewer | |||
|             GLModel model; | ||||
|             Color color; | ||||
|             InstanceVBuffer instances; | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             GLModel::InitializationData data; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| 
 | ||||
|             void reset(); | ||||
|         }; | ||||
|  | @ -362,7 +398,15 @@ class GCodeViewer | |||
|             case ERenderPrimitiveType::Triangle: { | ||||
|                 return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; | ||||
|             } | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } | ||||
|             case ERenderPrimitiveType::BatchedModel: { | ||||
|                 return model.data.vertices_count() > 0 && model.data.indices_count() && | ||||
|                     !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; | ||||
|             } | ||||
| #else | ||||
|             case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|             default: { return false; } | ||||
|             } | ||||
|         } | ||||
|  | @ -520,6 +564,9 @@ class GCodeViewer | |||
|         int64_t gl_triangles_calls_count{ 0 }; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|         int64_t gl_instanced_models_calls_count{ 0 }; | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         int64_t gl_batched_models_calls_count{ 0 }; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|         // memory
 | ||||
|         int64_t results_size{ 0 }; | ||||
|  | @ -541,6 +588,9 @@ class GCodeViewer | |||
|         int64_t extrude_segments_count{ 0 }; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|         int64_t instances_count{ 0 }; | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|         int64_t batched_count{ 0 }; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|         int64_t vbuffers_count{ 0 }; | ||||
|         int64_t ibuffers_count{ 0 }; | ||||
|  | @ -569,6 +619,9 @@ class GCodeViewer | |||
|             gl_triangles_calls_count = 0; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|             gl_instanced_models_calls_count = 0; | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             gl_batched_models_calls_count = 0; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|         } | ||||
| 
 | ||||
|  | @ -594,6 +647,9 @@ class GCodeViewer | |||
|             extrude_segments_count =  0; | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|             instances_count = 0; | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             batched_count = 0; | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
|             vbuffers_count = 0; | ||||
|             ibuffers_count = 0; | ||||
|  |  | |||
|  | @ -19,6 +19,26 @@ | |||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
| size_t GLModel::InitializationData::vertices_count() const | ||||
| { | ||||
|     size_t ret = 0; | ||||
|     for (const Entity& entity : entities) { | ||||
|         ret += entity.positions.size(); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| size_t GLModel::InitializationData::indices_count() const | ||||
| { | ||||
|     size_t ret = 0; | ||||
|     for (const Entity& entity : entities) { | ||||
|         ret += entity.indices.size(); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
| 
 | ||||
| void GLModel::init_from(const InitializationData& data) | ||||
| { | ||||
|     if (!m_render_data.empty()) // call reset() if you want to reuse this model
 | ||||
|  |  | |||
|  | @ -48,6 +48,15 @@ namespace GUI { | |||
|             }; | ||||
| 
 | ||||
|             std::vector<Entity> entities; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|             size_t vertices_count() const; | ||||
|             size_t vertices_size_floats() const { return vertices_count() * 6; } | ||||
|             size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } | ||||
| 
 | ||||
|             size_t indices_count() const; | ||||
|             size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|         }; | ||||
| 
 | ||||
|     private: | ||||
|  |  | |||
|  | @ -33,11 +33,19 @@ std::pair<bool, std::string> GLShadersManager::init() | |||
| 
 | ||||
|     bool valid = true; | ||||
| 
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|     // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
 | ||||
| #else | ||||
|     // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells
 | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|     valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); | ||||
|     // used to render printbed
 | ||||
|     valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); | ||||
|     // used to render options in gcode preview
 | ||||
| #if ENABLE_SEAMS_USING_BATCHED_MODELS | ||||
|     if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) | ||||
|         valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); | ||||
| #else | ||||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|     if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) | ||||
|         valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); | ||||
|  | @ -49,6 +57,7 @@ std::pair<bool, std::string> GLShadersManager::init() | |||
| #if ENABLE_SEAMS_USING_MODELS | ||||
|     } | ||||
| #endif // ENABLE_SEAMS_USING_MODELS
 | ||||
| #endif // ENABLE_SEAMS_USING_BATCHED_MODELS
 | ||||
|     // used to render extrusion and travel paths as lines in gcode preview
 | ||||
|     valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); | ||||
|     // used to render objects in 3d editor
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 enricoturri1966
						enricoturri1966