2020-04-14 08:02:08 +00:00
# ifndef slic3r_GCodeViewer_hpp_
# define slic3r_GCodeViewer_hpp_
2020-04-15 12:31:39 +00:00
# include "3DScene.hpp"
2020-04-14 08:02:08 +00:00
# include "libslic3r/GCode/GCodeProcessor.hpp"
2020-05-11 14:26:35 +00:00
# include "GLModel.hpp"
2020-04-14 08:02:08 +00:00
2020-12-10 07:40:08 +00:00
# include <cstdint>
2020-04-20 08:52:16 +00:00
# include <float.h>
2021-01-06 14:32:22 +00:00
# include <set>
# include <unordered_set>
2020-04-20 08:52:16 +00:00
2020-04-14 08:02:08 +00:00
namespace Slic3r {
2020-05-11 11:09:26 +00:00
2020-04-15 12:31:39 +00:00
class Print ;
2020-05-11 11:09:26 +00:00
class TriangleMesh ;
2020-04-14 08:02:08 +00:00
namespace GUI {
class GCodeViewer
{
2021-01-26 12:32:27 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
2021-01-20 12:47:48 +00:00
using IBufferType = unsigned short ;
2021-01-26 12:32:27 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-05-05 10:09:11 +00:00
using Color = std : : array < float , 3 > ;
2021-01-07 10:13:07 +00:00
using VertexBuffer = std : : vector < float > ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
using MultiVertexBuffer = std : : vector < VertexBuffer > ;
2021-01-20 12:47:48 +00:00
using IndexBuffer = std : : vector < IBufferType > ;
# else
2020-09-16 13:45:53 +00:00
using IndexBuffer = std : : vector < unsigned int > ;
2021-01-26 12:32:27 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-09-16 13:45:53 +00:00
using MultiIndexBuffer = std : : vector < IndexBuffer > ;
2020-05-05 10:09:11 +00:00
static const std : : vector < Color > Extrusion_Role_Colors ;
2020-05-22 09:52:07 +00:00
static const std : : vector < Color > Options_Colors ;
2020-05-05 10:09:11 +00:00
static const std : : vector < Color > Travel_Colors ;
2020-11-21 09:36:10 +00:00
static const Color Wipe_Color ;
2020-05-05 10:09:11 +00:00
static const std : : vector < Color > Range_Colors ;
2020-04-16 13:09:04 +00:00
2020-05-22 09:52:07 +00:00
enum class EOptionsColors : unsigned char
{
Retractions ,
Unretractions ,
ToolChanges ,
ColorChanges ,
PausePrints ,
CustomGCodes
} ;
2021-01-12 08:03:35 +00:00
// vbo buffer containing vertices data used to render a specific toolpath type
2020-04-15 14:29:11 +00:00
struct VBuffer
2020-04-14 08:02:08 +00:00
{
2020-06-29 12:00:08 +00:00
enum class EFormat : unsigned char
{
2020-08-26 13:29:33 +00:00
// vertex format: 3 floats -> position.x|position.y|position.z
2020-06-29 12:00:08 +00:00
Position ,
2020-08-26 13:29:33 +00:00
// vertex format: 4 floats -> position.x|position.y|position.z|normal.x
PositionNormal1 ,
// vertex format: 6 floats -> position.x|position.y|position.z|normal.x|normal.y|normal.z
PositionNormal3
2020-06-29 12:00:08 +00:00
} ;
EFormat format { EFormat : : Position } ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
// vbos id
2021-01-13 09:45:52 +00:00
std : : vector < unsigned int > vbos ;
// sizes of the buffers, in bytes, used in export to obj
std : : vector < size_t > sizes ;
2021-01-12 08:03:35 +00:00
# else
2020-06-29 12:00:08 +00:00
// vbo id
unsigned int id { 0 } ;
2021-01-12 08:03:35 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-06-29 12:00:08 +00:00
// count of vertices, updated after data are sent to gpu
size_t count { 0 } ;
2020-04-15 14:29:11 +00:00
2020-06-29 12:00:08 +00:00
size_t data_size_bytes ( ) const { return count * vertex_size_bytes ( ) ; }
2021-01-26 12:32:27 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
2021-01-20 12:47:48 +00:00
// We set 65536 as max count of vertices inside a vertex buffer to allow
// to use unsigned short in place of unsigned int for indices in the index buffer, to save memory
size_t max_size_bytes ( ) const { return 65536 * vertex_size_bytes ( ) ; }
2021-01-26 12:32:27 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-08-26 13:29:33 +00:00
size_t vertex_size_floats ( ) const { return position_size_floats ( ) + normal_size_floats ( ) ; }
size_t vertex_size_bytes ( ) const { return vertex_size_floats ( ) * sizeof ( float ) ; }
size_t position_offset_floats ( ) const { return 0 ; }
size_t position_offset_size ( ) const { return position_offset_floats ( ) * sizeof ( float ) ; }
2021-01-12 08:03:35 +00:00
size_t position_size_floats ( ) const {
2020-06-29 12:00:08 +00:00
switch ( format )
{
2020-08-26 13:29:33 +00:00
case EFormat : : Position :
case EFormat : : PositionNormal3 : { return 3 ; }
case EFormat : : PositionNormal1 : { return 4 ; }
2021-01-12 08:03:35 +00:00
default : { return 0 ; }
2020-06-29 12:00:08 +00:00
}
}
2020-08-26 13:29:33 +00:00
size_t position_size_bytes ( ) const { return position_size_floats ( ) * sizeof ( float ) ; }
2021-01-12 08:03:35 +00:00
size_t normal_offset_floats ( ) const {
2020-08-26 13:29:33 +00:00
switch ( format )
{
case EFormat : : Position :
case EFormat : : PositionNormal1 : { return 0 ; }
case EFormat : : PositionNormal3 : { return 3 ; }
2021-01-12 08:03:35 +00:00
default : { return 0 ; }
2020-08-26 13:29:33 +00:00
}
}
size_t normal_offset_size ( ) const { return normal_offset_floats ( ) * sizeof ( float ) ; }
size_t normal_size_floats ( ) const {
switch ( format )
{
default :
case EFormat : : Position :
case EFormat : : PositionNormal1 : { return 0 ; }
case EFormat : : PositionNormal3 : { return 3 ; }
}
}
size_t normal_size_bytes ( ) const { return normal_size_floats ( ) * sizeof ( float ) ; }
2020-04-14 08:02:08 +00:00
2020-04-14 14:40:08 +00:00
void reset ( ) ;
2020-06-29 12:00:08 +00:00
} ;
2021-01-12 08:03:35 +00:00
// ibo buffer containing indices data (for lines/triangles) used to render a specific toolpath type
2020-06-29 12:00:08 +00:00
struct IBuffer
{
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
// id of the associated vertex buffer
unsigned int vbo { 0 } ;
// ibo id
unsigned int ibo { 0 } ;
# else
2020-06-29 12:00:08 +00:00
// ibo id
unsigned int id { 0 } ;
2021-01-12 08:03:35 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-06-29 12:00:08 +00:00
// count of indices, updated after data are sent to gpu
size_t count { 0 } ;
2020-04-14 14:40:08 +00:00
2020-06-29 12:00:08 +00:00
void reset ( ) ;
2020-04-14 08:02:08 +00:00
} ;
2020-04-20 08:52:16 +00:00
// Used to identify different toolpath sub-types inside a IBuffer
2020-04-16 13:09:04 +00:00
struct Path
{
2020-04-28 10:24:03 +00:00
struct Endpoint
{
2021-01-18 10:37:23 +00:00
// index of the buffer in the multibuffer vector
// the buffer type may change:
// it is the vertex buffer while extracting vertices data,
// the index buffer while extracting indices data
2020-09-16 13:45:53 +00:00
unsigned int b_id { 0 } ;
2021-01-18 10:37:23 +00:00
// index into the buffer
2020-09-16 13:45:53 +00:00
size_t i_id { 0 } ;
2021-01-12 13:03:58 +00:00
// move id
2020-09-16 13:45:53 +00:00
size_t s_id { 0 } ;
2020-05-04 07:37:06 +00:00
Vec3f position { Vec3f : : Zero ( ) } ;
2020-04-28 10:24:03 +00:00
} ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
struct Sub_Path
{
Endpoint first ;
Endpoint last ;
bool contains ( size_t s_id ) const {
return first . s_id < = s_id & & s_id < = last . s_id ;
}
} ;
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-08-03 11:57:10 +00:00
EMoveType type { EMoveType : : Noop } ;
2020-04-16 13:09:04 +00:00
ExtrusionRole role { erNone } ;
2021-01-12 08:03:35 +00:00
# if !ENABLE_SPLITTED_VERTEX_BUFFER
2020-04-28 10:24:03 +00:00
Endpoint first ;
Endpoint last ;
2021-01-12 08:03:35 +00:00
# endif // !ENABLE_SPLITTED_VERTEX_BUFFER
2020-04-24 06:46:31 +00:00
float delta_extruder { 0.0f } ;
2020-04-20 08:52:16 +00:00
float height { 0.0f } ;
2020-04-20 11:24:25 +00:00
float width { 0.0f } ;
2020-04-20 14:04:59 +00:00
float feedrate { 0.0f } ;
2020-04-21 07:06:43 +00:00
float fan_speed { 0.0f } ;
2020-04-21 09:38:42 +00:00
float volumetric_rate { 0.0f } ;
2020-04-21 13:55:26 +00:00
unsigned char extruder_id { 0 } ;
2020-04-22 14:29:07 +00:00
unsigned char cp_color_id { 0 } ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
std : : vector < Sub_Path > sub_paths ;
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-04-16 13:09:04 +00:00
2020-05-04 07:37:06 +00:00
bool matches ( const GCodeProcessor : : MoveVertex & move ) const ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
size_t vertices_count ( ) const {
return sub_paths . empty ( ) ? 0 : sub_paths . back ( ) . last . s_id - sub_paths . front ( ) . first . s_id + 1 ;
}
bool contains ( size_t s_id ) const {
return sub_paths . empty ( ) ? false : sub_paths . front ( ) . first . s_id < = s_id & & s_id < = sub_paths . back ( ) . last . s_id ;
}
int get_id_of_sub_path_containing ( size_t s_id ) const {
if ( sub_paths . empty ( ) )
return - 1 ;
else {
for ( int i = 0 ; i < static_cast < int > ( sub_paths . size ( ) ) ; + + i ) {
if ( sub_paths [ i ] . contains ( s_id ) )
return i ;
}
return - 1 ;
}
}
void add_sub_path ( const GCodeProcessor : : MoveVertex & move , unsigned int b_id , size_t i_id , size_t s_id ) {
Endpoint endpoint = { b_id , i_id , s_id , move . position } ;
sub_paths . push_back ( { endpoint , endpoint } ) ;
}
# else
2020-08-28 10:28:21 +00:00
size_t vertices_count ( ) const { return last . s_id - first . s_id + 1 ; }
2020-09-16 13:45:53 +00:00
bool contains ( size_t id ) const { return first . s_id < = id & & id < = last . s_id ; }
2021-01-12 08:03:35 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-04-16 13:09:04 +00:00
} ;
2021-01-12 08:03:35 +00:00
// Used to batch the indices needed to render the paths
2020-04-28 13:08:36 +00:00
struct RenderPath
{
2021-02-22 14:27:40 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
// Index of the parent tbuffer
unsigned char tbuffer_id ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2021-01-06 14:32:22 +00:00
// Render path property
Color color ;
2021-01-21 08:44:02 +00:00
// Index of the buffer in TBuffer::indices
2021-02-22 14:27:40 +00:00
unsigned int ibuffer_id ;
2021-01-06 14:32:22 +00:00
// Render path content
2021-02-22 14:27:40 +00:00
// Index of the path in TBuffer::paths
2021-01-06 14:32:22 +00:00
unsigned int path_id ;
std : : vector < unsigned int > sizes ;
2021-02-22 14:27:40 +00:00
std : : vector < size_t > offsets ; // use size_t because we need an unsigned integer whose size matches pointer's size (used in the call glMultiDrawElements())
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
bool contains ( size_t offset ) const {
for ( size_t i = 0 ; i < offsets . size ( ) ; + + i ) {
if ( offsets [ i ] < = offset & & offset < = offsets [ i ] + static_cast < size_t > ( sizes [ i ] * sizeof ( IBufferType ) ) )
return true ;
}
return false ;
}
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2021-01-06 14:32:22 +00:00
} ;
2021-02-22 14:27:40 +00:00
// // for unordered_set implementation of render_paths
// struct RenderPathPropertyHash {
// size_t operator() (const RenderPath &p) const {
// // Convert the RGB value to an integer hash.
//// return (size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) * 7919) ^ size_t(p.ibuffer_id);
// return size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) ^ size_t(p.ibuffer_id);
// }
// };
2021-01-06 14:32:22 +00:00
struct RenderPathPropertyLower {
bool operator ( ) ( const RenderPath & l , const RenderPath & r ) const {
2021-02-22 14:27:40 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
if ( l . tbuffer_id < r . tbuffer_id )
return true ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
for ( int i = 0 ; i < 3 ; + + i ) {
2021-01-06 14:32:22 +00:00
if ( l . color [ i ] < r . color [ i ] )
return true ;
else if ( l . color [ i ] > r . color [ i ] )
return false ;
2021-02-22 14:27:40 +00:00
}
return l . ibuffer_id < r . ibuffer_id ;
2021-01-06 14:32:22 +00:00
}
} ;
struct RenderPathPropertyEqual {
bool operator ( ) ( const RenderPath & l , const RenderPath & r ) const {
2021-02-22 14:27:40 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
return l . tbuffer_id = = r . tbuffer_id & & l . ibuffer_id = = r . ibuffer_id & & l . color = = r . color ;
# else
return l . color = = r . color & & l . ibuffer_id = = r . ibuffer_id ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2021-01-06 14:32:22 +00:00
}
2020-04-28 13:08:36 +00:00
} ;
2020-06-29 12:00:08 +00:00
// buffer containing data for rendering a specific toolpath type
struct TBuffer
2020-04-15 14:29:11 +00:00
{
2020-09-01 06:29:06 +00:00
enum class ERenderPrimitiveType : unsigned char
2020-08-26 13:29:33 +00:00
{
Point ,
Line ,
Triangle
} ;
2020-09-01 06:29:06 +00:00
ERenderPrimitiveType render_primitive_type ;
2020-06-29 12:00:08 +00:00
VBuffer vertices ;
2020-09-16 13:45:53 +00:00
std : : vector < IBuffer > indices ;
2020-06-29 12:00:08 +00:00
2020-05-20 12:11:22 +00:00
std : : string shader ;
2020-04-16 13:09:04 +00:00
std : : vector < Path > paths ;
2021-01-07 08:57:37 +00:00
// std::set seems to perform significantly better, at least on Windows.
2021-01-06 14:32:22 +00:00
// std::unordered_set<RenderPath, RenderPathPropertyHash, RenderPathPropertyEqual> render_paths;
std : : set < RenderPath , RenderPathPropertyLower > render_paths ;
2020-04-15 14:29:11 +00:00
bool visible { false } ;
void reset ( ) ;
2021-01-12 08:03:35 +00:00
2020-09-16 13:45:53 +00:00
// b_id index of buffer contained in this->indices
// i_id index of first index contained in this->indices[b_id]
// s_id index of first vertex contained in this->vertices
void add_path ( const GCodeProcessor : : MoveVertex & move , unsigned int b_id , size_t i_id , size_t s_id ) ;
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
unsigned int max_vertices_per_segment ( ) const {
2020-09-01 06:29:06 +00:00
switch ( render_primitive_type )
{
case ERenderPrimitiveType : : Point : { return 1 ; }
case ERenderPrimitiveType : : Line : { return 2 ; }
2021-01-12 08:03:35 +00:00
case ERenderPrimitiveType : : Triangle : { return 8 ; }
2020-09-01 06:29:06 +00:00
default : { return 0 ; }
}
}
2021-01-12 08:03:35 +00:00
size_t max_vertices_per_segment_size_floats ( ) const { return vertices . vertex_size_floats ( ) * static_cast < size_t > ( max_vertices_per_segment ( ) ) ; }
size_t max_vertices_per_segment_size_bytes ( ) const { return max_vertices_per_segment_size_floats ( ) * sizeof ( float ) ; }
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
unsigned int indices_per_segment ( ) const {
2020-09-01 12:35:42 +00:00
switch ( render_primitive_type )
{
2021-01-12 08:03:35 +00:00
case ERenderPrimitiveType : : Point : { return 1 ; }
case ERenderPrimitiveType : : Line : { return 2 ; }
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
case ERenderPrimitiveType : : Triangle : { return 30 ; } // 3 indices x 10 triangles
# else
2021-01-12 08:03:35 +00:00
case ERenderPrimitiveType : : Triangle : { return 42 ; } // 3 indices x 14 triangles
2021-02-05 10:53:39 +00:00
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2021-01-12 08:03:35 +00:00
default : { return 0 ; }
2020-09-01 12:35:42 +00:00
}
}
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
2021-01-20 12:47:48 +00:00
size_t indices_per_segment_size_bytes ( ) const { return static_cast < size_t > ( indices_per_segment ( ) * sizeof ( IBufferType ) ) ; }
2021-01-12 08:03:35 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
unsigned int max_indices_per_segment ( ) const {
2020-09-01 12:35:42 +00:00
switch ( render_primitive_type )
{
2021-02-05 10:53:39 +00:00
case ERenderPrimitiveType : : Point : { return 1 ; }
case ERenderPrimitiveType : : Line : { return 2 ; }
case ERenderPrimitiveType : : Triangle : { return 36 ; } // 3 indices x 12 triangles
2020-09-01 12:35:42 +00:00
default : { return 0 ; }
}
}
2021-02-05 10:53:39 +00:00
size_t max_indices_per_segment_size_bytes ( ) const { return max_indices_per_segment ( ) * sizeof ( IBufferType ) ; }
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2020-09-16 13:45:53 +00:00
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
bool has_data ( ) const {
2021-01-13 09:45:52 +00:00
return ! vertices . vbos . empty ( ) & & vertices . vbos . front ( ) ! = 0 & & ! indices . empty ( ) & & indices . front ( ) . ibo ! = 0 ;
2021-01-12 08:03:35 +00:00
}
# else
2021-02-05 10:53:39 +00:00
unsigned int start_segment_vertex_offset ( ) const { return 0 ; }
unsigned int end_segment_vertex_offset ( ) const {
switch ( render_primitive_type )
{
case ERenderPrimitiveType : : Point : { return 0 ; }
case ERenderPrimitiveType : : Line : { return 1 ; }
case ERenderPrimitiveType : : Triangle : { return 36 ; } // 1st vertex of 13th triangle
default : { return 0 ; }
}
}
2020-09-16 13:45:53 +00:00
bool has_data ( ) const { return vertices . id ! = 0 & & ! indices . empty ( ) & & indices . front ( ) . id ! = 0 ; }
2021-01-12 08:03:35 +00:00
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-04-15 14:29:11 +00:00
} ;
2020-05-06 09:18:37 +00:00
// helper to render shells
2020-04-15 12:31:39 +00:00
struct Shells
{
GLVolumeCollection volumes ;
bool visible { false } ;
} ;
2020-04-20 08:52:16 +00:00
// helper to render extrusion paths
2020-04-17 08:43:29 +00:00
struct Extrusions
{
2020-04-20 08:52:16 +00:00
struct Range
{
float min ;
float max ;
2020-08-13 10:51:50 +00:00
unsigned int count ;
2020-04-20 08:52:16 +00:00
Range ( ) { reset ( ) ; }
2020-08-13 10:51:50 +00:00
void update_from ( const float value ) {
if ( value ! = max & & value ! = min )
+ + count ;
min = std : : min ( min , value ) ;
max = std : : max ( max , value ) ;
}
void reset ( ) { min = FLT_MAX ; max = - FLT_MAX ; count = 0 ; }
2020-04-20 08:52:16 +00:00
2020-04-22 14:29:07 +00:00
float step_size ( ) const { return ( max - min ) / ( static_cast < float > ( Range_Colors . size ( ) ) - 1.0f ) ; }
2020-05-05 10:09:11 +00:00
Color get_color_at ( float value ) const ;
2020-04-20 08:52:16 +00:00
} ;
struct Ranges
{
// Color mapping by layer height.
Range height ;
2020-04-20 11:24:25 +00:00
// Color mapping by extrusion width.
Range width ;
2020-04-20 14:04:59 +00:00
// Color mapping by feedrate.
Range feedrate ;
2020-04-21 07:06:43 +00:00
// Color mapping by fan speed.
Range fan_speed ;
2020-04-21 09:38:42 +00:00
// Color mapping by volumetric extrusion rate.
Range volumetric_rate ;
2020-04-20 08:52:16 +00:00
void reset ( ) {
height . reset ( ) ;
2020-04-20 11:24:25 +00:00
width . reset ( ) ;
2020-04-20 14:04:59 +00:00
feedrate . reset ( ) ;
2020-04-21 07:06:43 +00:00
fan_speed . reset ( ) ;
2020-04-21 09:38:42 +00:00
volumetric_rate . reset ( ) ;
2020-04-20 08:52:16 +00:00
}
} ;
2020-04-17 08:43:29 +00:00
unsigned int role_visibility_flags { 0 } ;
2020-04-20 08:52:16 +00:00
Ranges ranges ;
2020-04-17 08:43:29 +00:00
void reset_role_visibility_flags ( ) {
role_visibility_flags = 0 ;
2020-08-26 13:29:33 +00:00
for ( unsigned int i = 0 ; i < erCount ; + + i ) {
2020-04-17 08:43:29 +00:00
role_visibility_flags | = 1 < < i ;
}
}
2020-04-20 08:52:16 +00:00
void reset_ranges ( ) { ranges . reset ( ) ; }
2020-04-17 08:43:29 +00:00
} ;
2020-11-11 15:22:09 +00:00
class Layers
{
public :
struct Endpoints
{
size_t first { 0 } ;
size_t last { 0 } ;
2021-01-12 13:34:52 +00:00
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
bool operator = = ( const Endpoints & other ) const {
return first = = other . first & & last = = other . last ;
}
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-11-11 15:22:09 +00:00
} ;
private :
std : : vector < double > m_zs ;
std : : vector < Endpoints > m_endpoints ;
public :
2021-01-12 08:03:35 +00:00
void append ( double z , Endpoints endpoints ) {
2020-11-11 15:22:09 +00:00
m_zs . emplace_back ( z ) ;
m_endpoints . emplace_back ( endpoints ) ;
}
2021-01-12 08:03:35 +00:00
void reset ( ) {
2020-11-11 15:22:09 +00:00
m_zs = std : : vector < double > ( ) ;
m_endpoints = std : : vector < Endpoints > ( ) ;
}
size_t size ( ) const { return m_zs . size ( ) ; }
bool empty ( ) const { return m_zs . empty ( ) ; }
const std : : vector < double > & get_zs ( ) const { return m_zs ; }
const std : : vector < Endpoints > & get_endpoints ( ) const { return m_endpoints ; }
std : : vector < Endpoints > & get_endpoints ( ) { return m_endpoints ; }
2020-11-12 15:29:44 +00:00
double get_z_at ( unsigned int id ) const { return ( id < m_zs . size ( ) ) ? m_zs [ id ] : 0.0 ; }
2020-11-11 15:22:09 +00:00
Endpoints get_endpoints_at ( unsigned int id ) const { return ( id < m_endpoints . size ( ) ) ? m_endpoints [ id ] : Endpoints ( ) ; }
2021-01-12 08:03:35 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
bool operator ! = ( const Layers & other ) const {
if ( m_zs ! = other . m_zs )
return true ;
if ( ! ( m_endpoints = = other . m_endpoints ) )
return true ;
return false ;
}
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-11-11 15:22:09 +00:00
} ;
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
// used to render the toolpath caps of the current sequential range
// (i.e. when sliding on the horizontal slider)
struct SequentialRangeCap
{
TBuffer * buffer { nullptr } ;
unsigned int ibo { 0 } ;
unsigned int vbo { 0 } ;
Color color ;
~ SequentialRangeCap ( ) ;
bool is_renderable ( ) const { return buffer ! = nullptr ; }
void reset ( ) ;
size_t indices_count ( ) const { return 6 ; }
} ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2020-04-27 12:10:18 +00:00
# if ENABLE_GCODE_VIEWER_STATISTICS
struct Statistics
{
2020-09-11 13:19:23 +00:00
// time
2020-12-10 07:40:08 +00:00
int64_t results_time { 0 } ;
int64_t load_time { 0 } ;
2021-02-05 10:53:39 +00:00
int64_t load_vertices { 0 } ;
int64_t smooth_vertices { 0 } ;
int64_t load_indices { 0 } ;
2020-12-10 07:40:08 +00:00
int64_t refresh_time { 0 } ;
int64_t refresh_paths_time { 0 } ;
2020-06-24 14:57:09 +00:00
// opengl calls
2020-12-10 07:40:08 +00:00
int64_t gl_multi_points_calls_count { 0 } ;
int64_t gl_multi_lines_calls_count { 0 } ;
int64_t gl_multi_triangles_calls_count { 0 } ;
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
int64_t gl_triangles_calls_count { 0 } ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2020-06-24 14:57:09 +00:00
// memory
2020-12-10 07:40:08 +00:00
int64_t results_size { 0 } ;
2020-12-11 10:58:08 +00:00
int64_t total_vertices_gpu_size { 0 } ;
int64_t total_indices_gpu_size { 0 } ;
int64_t max_vbuffer_gpu_size { 0 } ;
int64_t max_ibuffer_gpu_size { 0 } ;
2020-12-10 07:40:08 +00:00
int64_t paths_size { 0 } ;
int64_t render_paths_size { 0 } ;
2020-09-11 13:19:23 +00:00
// other
2020-12-10 07:40:08 +00:00
int64_t travel_segments_count { 0 } ;
int64_t wipe_segments_count { 0 } ;
int64_t extrude_segments_count { 0 } ;
2020-12-11 10:58:08 +00:00
int64_t vbuffers_count { 0 } ;
int64_t ibuffers_count { 0 } ;
2020-04-27 12:10:18 +00:00
void reset_all ( ) {
reset_times ( ) ;
reset_opengl ( ) ;
reset_sizes ( ) ;
2020-09-11 13:19:23 +00:00
reset_others ( ) ;
2020-04-27 12:10:18 +00:00
}
void reset_times ( ) {
2020-06-29 12:00:08 +00:00
results_time = 0 ;
2020-04-27 12:10:18 +00:00
load_time = 0 ;
2021-02-05 10:53:39 +00:00
load_vertices = 0 ;
smooth_vertices = 0 ;
load_indices = 0 ;
2020-04-27 12:10:18 +00:00
refresh_time = 0 ;
2020-05-05 11:57:51 +00:00
refresh_paths_time = 0 ;
2020-04-27 12:10:18 +00:00
}
void reset_opengl ( ) {
2020-04-28 13:08:36 +00:00
gl_multi_points_calls_count = 0 ;
2020-08-26 13:29:33 +00:00
gl_multi_lines_calls_count = 0 ;
gl_multi_triangles_calls_count = 0 ;
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
gl_triangles_calls_count = 0 ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2020-04-27 12:10:18 +00:00
}
void reset_sizes ( ) {
2020-04-28 08:29:25 +00:00
results_size = 0 ;
2020-12-11 10:58:08 +00:00
total_vertices_gpu_size = 0 ;
total_indices_gpu_size = 0 ;
max_vbuffer_gpu_size = 0 ;
max_ibuffer_gpu_size = 0 ;
2020-06-29 12:00:08 +00:00
paths_size = 0 ;
2020-05-05 10:09:11 +00:00
render_paths_size = 0 ;
2020-04-27 12:10:18 +00:00
}
2020-06-29 12:00:08 +00:00
2020-09-11 13:19:23 +00:00
void reset_others ( ) {
2020-06-29 12:00:08 +00:00
travel_segments_count = 0 ;
2020-11-21 09:36:10 +00:00
wipe_segments_count = 0 ;
2020-06-29 12:00:08 +00:00
extrude_segments_count = 0 ;
2020-12-11 10:58:08 +00:00
vbuffers_count = 0 ;
ibuffers_count = 0 ;
2020-06-29 12:00:08 +00:00
}
2020-04-27 12:10:18 +00:00
} ;
# endif // ENABLE_GCODE_VIEWER_STATISTICS
2020-04-16 13:59:36 +00:00
public :
2020-05-15 07:22:51 +00:00
struct SequentialView
{
class Marker
{
2020-05-27 06:06:02 +00:00
GLModel m_model ;
2020-06-09 06:12:51 +00:00
Vec3f m_world_position ;
2020-05-15 07:22:51 +00:00
Transform3f m_world_transform ;
2020-06-09 06:12:51 +00:00
float m_z_offset { 0.5f } ;
2020-10-09 10:21:00 +00:00
std : : array < float , 4 > m_color { 1.0f , 1.0f , 1.0f , 0.5f } ;
2020-11-03 08:27:18 +00:00
bool m_visible { true } ;
2020-05-15 07:22:51 +00:00
public :
void init ( ) ;
2020-06-24 14:57:09 +00:00
const BoundingBoxf3 & get_bounding_box ( ) const { return m_model . get_bounding_box ( ) ; }
2020-05-15 07:22:51 +00:00
2020-05-22 08:43:59 +00:00
void set_world_position ( const Vec3f & position ) ;
2020-05-15 07:22:51 +00:00
void set_color ( const std : : array < float , 4 > & color ) { m_color = color ; }
bool is_visible ( ) const { return m_visible ; }
void set_visible ( bool visible ) { m_visible = visible ; }
void render ( ) const ;
} ;
2020-05-18 11:24:07 +00:00
struct Endpoints
{
2020-09-16 13:45:53 +00:00
size_t first { 0 } ;
size_t last { 0 } ;
2020-05-18 11:24:07 +00:00
} ;
2020-10-09 11:00:20 +00:00
bool skip_invisible_moves { false } ;
2020-05-18 11:24:07 +00:00
Endpoints endpoints ;
Endpoints current ;
2020-10-07 11:19:44 +00:00
Endpoints last_current ;
2020-05-15 07:22:51 +00:00
Vec3f current_position { Vec3f : : Zero ( ) } ;
Marker marker ;
2021-02-16 09:07:05 +00:00
# if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
std : : vector < unsigned int > gcode_ids ;
# endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
2020-05-15 07:22:51 +00:00
} ;
2020-04-16 13:59:36 +00:00
enum class EViewType : unsigned char
{
FeatureType ,
Height ,
Width ,
Feedrate ,
FanSpeed ,
VolumetricRate ,
Tool ,
ColorPrint ,
Count
} ;
private :
2021-02-05 10:53:39 +00:00
bool m_gl_data_initialized { false } ;
2020-04-21 13:55:26 +00:00
unsigned int m_last_result_id { 0 } ;
2020-09-14 07:18:20 +00:00
size_t m_moves_count { 0 } ;
2021-02-05 10:53:39 +00:00
std : : vector < TBuffer > m_buffers { static_cast < size_t > ( EMoveType : : Extrude ) } ;
2020-06-24 14:57:09 +00:00
// bounding box of toolpaths
BoundingBoxf3 m_paths_bounding_box ;
// bounding box of toolpaths + marker tools
BoundingBoxf3 m_max_bounding_box ;
2020-05-05 10:09:11 +00:00
std : : vector < Color > m_tool_colors ;
2020-11-11 15:22:09 +00:00
Layers m_layers ;
2020-11-12 15:29:44 +00:00
std : : array < unsigned int , 2 > m_layers_z_range ;
2020-04-18 08:41:37 +00:00
std : : vector < ExtrusionRole > m_roles ;
2020-11-09 12:06:20 +00:00
size_t m_extruders_count ;
2020-04-22 14:29:07 +00:00
std : : vector < unsigned char > m_extruder_ids ;
2021-02-05 10:53:39 +00:00
Extrusions m_extrusions ;
SequentialView m_sequential_view ;
2020-04-15 12:31:39 +00:00
Shells m_shells ;
2020-04-24 08:59:03 +00:00
EViewType m_view_type { EViewType : : FeatureType } ;
2020-04-18 08:41:37 +00:00
bool m_legend_enabled { true } ;
2020-08-03 11:57:10 +00:00
PrintEstimatedTimeStatistics m_time_statistics ;
2021-02-05 10:53:39 +00:00
PrintEstimatedTimeStatistics : : ETimeMode m_time_estimate_mode { PrintEstimatedTimeStatistics : : ETimeMode : : Normal } ;
2020-04-27 12:10:18 +00:00
# if ENABLE_GCODE_VIEWER_STATISTICS
2021-02-05 10:53:39 +00:00
Statistics m_statistics ;
2020-04-27 12:10:18 +00:00
# endif // ENABLE_GCODE_VIEWER_STATISTICS
2021-02-05 10:53:39 +00:00
std : : array < float , 2 > m_detected_point_sizes = { 0.0f , 0.0f } ;
2020-11-09 07:41:14 +00:00
GCodeProcessor : : Result : : SettingsIds m_settings_ids ;
2021-02-05 10:53:39 +00:00
# if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
std : : array < SequentialRangeCap , 2 > m_sequential_range_caps ;
# endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
2020-04-16 13:59:36 +00:00
2020-04-14 08:02:08 +00:00
public :
2021-01-07 08:57:37 +00:00
GCodeViewer ( ) ;
2020-04-14 14:40:08 +00:00
~ GCodeViewer ( ) { reset ( ) ; }
2020-04-14 08:02:08 +00:00
2020-04-21 13:55:26 +00:00
// extract rendering data from the given parameters
2020-04-22 14:29:07 +00:00
void load ( const GCodeProcessor : : Result & gcode_result , const Print & print , bool initialized ) ;
// recalculate ranges in dependence of what is visible and sets tool/print colors
void refresh ( const GCodeProcessor : : Result & gcode_result , const std : : vector < std : : string > & str_tool_colors ) ;
2020-12-11 13:59:58 +00:00
void refresh_render_paths ( ) ;
2020-12-18 08:03:18 +00:00
void update_shells_color_by_extruder ( const DynamicPrintConfig * config ) ;
2020-04-20 14:04:59 +00:00
2020-04-14 14:40:08 +00:00
void reset ( ) ;
2020-04-14 08:02:08 +00:00
void render ( ) const ;
2020-05-05 10:09:11 +00:00
bool has_data ( ) const { return ! m_roles . empty ( ) ; }
2021-01-13 09:45:52 +00:00
# if ENABLE_SPLITTED_VERTEX_BUFFER
bool can_export_toolpaths ( ) const ;
# endif // ENABLE_SPLITTED_VERTEX_BUFFER
2020-05-05 10:09:11 +00:00
2020-06-24 14:57:09 +00:00
const BoundingBoxf3 & get_paths_bounding_box ( ) const { return m_paths_bounding_box ; }
const BoundingBoxf3 & get_max_bounding_box ( ) const { return m_max_bounding_box ; }
2021-01-29 06:39:27 +00:00
const std : : vector < double > & get_layers_zs ( ) const { return m_layers . get_zs ( ) ; }
2020-04-14 14:40:08 +00:00
2020-05-15 07:22:51 +00:00
const SequentialView & get_sequential_view ( ) const { return m_sequential_view ; }
2020-10-07 11:19:44 +00:00
void update_sequential_view_current ( unsigned int first , unsigned int last ) ;
2020-05-15 07:22:51 +00:00
2020-04-16 13:59:36 +00:00
EViewType get_view_type ( ) const { return m_view_type ; }
void set_view_type ( EViewType type ) {
if ( type = = EViewType : : Count )
type = EViewType : : FeatureType ;
m_view_type = type ;
}
2020-08-03 11:57:10 +00:00
bool is_toolpath_move_type_visible ( EMoveType type ) const ;
void set_toolpath_move_type_visible ( EMoveType type , bool visible ) ;
2020-04-28 06:50:52 +00:00
unsigned int get_toolpath_role_visibility_flags ( ) const { return m_extrusions . role_visibility_flags ; }
2020-04-17 08:43:29 +00:00
void set_toolpath_role_visibility_flags ( unsigned int flags ) { m_extrusions . role_visibility_flags = flags ; }
2020-04-28 06:50:52 +00:00
unsigned int get_options_visibility_flags ( ) const ;
2020-04-24 14:12:38 +00:00
void set_options_visibility_from_flags ( unsigned int flags ) ;
2020-11-11 15:22:09 +00:00
void set_layers_z_range ( const std : : array < unsigned int , 2 > & layers_z_range ) ;
2020-04-15 12:31:39 +00:00
2020-04-18 08:41:37 +00:00
bool is_legend_enabled ( ) const { return m_legend_enabled ; }
void enable_legend ( bool enable ) { m_legend_enabled = enable ; }
2020-07-03 10:17:12 +00:00
void export_toolpaths_to_obj ( const char * filename ) const ;
2020-04-14 08:02:08 +00:00
private :
2020-04-15 12:31:39 +00:00
void load_toolpaths ( const GCodeProcessor : : Result & gcode_result ) ;
void load_shells ( const Print & print , bool initialized ) ;
2020-10-15 08:25:13 +00:00
void refresh_render_paths ( bool keep_sequential_current_first , bool keep_sequential_current_last ) const ;
2020-04-15 12:31:39 +00:00
void render_toolpaths ( ) const ;
void render_shells ( ) const ;
2020-04-27 12:10:18 +00:00
void render_legend ( ) const ;
# if ENABLE_GCODE_VIEWER_STATISTICS
void render_statistics ( ) const ;
# endif // ENABLE_GCODE_VIEWER_STATISTICS
2020-04-27 10:43:51 +00:00
bool is_visible ( ExtrusionRole role ) const {
return role < erCount & & ( m_extrusions . role_visibility_flags & ( 1 < < role ) ) ! = 0 ;
}
bool is_visible ( const Path & path ) const { return is_visible ( path . role ) ; }
2020-12-10 07:40:08 +00:00
void log_memory_used ( const std : : string & label , int64_t additional = 0 ) const ;
2020-04-14 08:02:08 +00:00
} ;
} // namespace GUI
} // namespace Slic3r
# endif // slic3r_GCodeViewer_hpp_