mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-25 04:14:24 +08:00
Fixed conflicts after merge with master
This commit is contained in:
commit
6a7e32ad3e
4
deps/wxWidgets/wxWidgets.cmake
vendored
4
deps/wxWidgets/wxWidgets.cmake
vendored
@ -12,8 +12,8 @@ endif()
|
||||
prusaslicer_add_cmake_project(wxWidgets
|
||||
# GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets"
|
||||
# GIT_TAG tm_cross_compile #${_wx_git_tag}
|
||||
URL https://github.com/prusa3d/wxWidgets/archive/73f029adfcc82fb3aa4b01220a013f716e57d110.zip
|
||||
URL_HASH SHA256=c35fe0187db497b6a3f477e24ed5e307028657ff0c2554385810b6e7961ad2e4
|
||||
URL https://github.com/prusa3d/wxWidgets/archive/489f6118256853cf5b299d595868641938566cdb.zip
|
||||
URL_HASH SHA256=5b22d465377cedd8044bba69bea958b248953fd3628c1de4913a84d4e6f6175b
|
||||
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} dep_TIFF dep_JPEG
|
||||
CMAKE_ARGS
|
||||
-DwxBUILD_PRECOMP=ON
|
||||
|
50
resources/icons/legend_cog.svg
Normal file
50
resources/icons/legend_cog.svg
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 1000 1000"
|
||||
enable-background="new 0 0 1000 1000"
|
||||
xml:space="preserve"
|
||||
id="svg1405"
|
||||
sodipodi:docname="legend_cog.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1409" /><sodipodi:namedview
|
||||
id="namedview1407"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.57417071"
|
||||
inkscape:cx="498.98052"
|
||||
inkscape:cy="500.72217"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g1403" />
|
||||
<metadata
|
||||
id="metadata1400"> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g
|
||||
id="g1403"><g
|
||||
id="g3385"
|
||||
transform="matrix(0.9,0,0,0.9,50,50)"><path
|
||||
id="Delicious"
|
||||
d="M 951.5,309.2 C 914.3,221.2 852.2,146.5 774,93.7 734.9,67.3 691.8,46.3 645.7,32 599.6,17.7 550.7,10 500,10 432.4,10 367.9,23.7 309.3,48.5 221.3,85.7 146.5,147.8 93.7,226 67.3,265.1 46.3,308.2 32,354.3 c -14.3,46 -22,95 -22,145.7 0,67.6 13.7,132.1 38.5,190.8 37.2,88 99.3,162.7 177.5,215.5 39.1,26.4 82.2,47.3 128.3,61.7 46,14.4 95,22 145.7,22 67.5,0 132.1,-13.7 190.7,-38.5 88,-37.2 162.7,-99.3 215.6,-177.5 26.4,-39.1 47.3,-82.3 61.7,-128.3 14.3,-46 22,-95 22,-145.7 0,-67.6 -13.7,-132.1 -38.5,-190.8 z m -61,355.7 c -32.2,76 -85.9,140.8 -153.6,186.4 -33.8,22.9 -71.1,41 -110.9,53.3 -39.8,12.3 -82.1,19 -126,19.1 v 0 -423.2 H 76.3 c 0,-0.2 0,-0.3 0,-0.5 0,-58.6 11.8,-114.2 33.3,-164.9 32.1,-76 85.9,-140.8 153.6,-186.5 33.8,-22.8 71.1,-40.9 110.9,-53.3 39.8,-12.4 82.1,-19 126,-19 V 500 h 423.7 c -0.1,58.6 -11.9,114.2 -33.3,164.9 z" /></g><path
|
||||
style="fill:#ffffff;stroke-width:7.38916;stroke-miterlimit:10;fill-opacity:1"
|
||||
d="m 77.139043,487.37685 c 3.697394,-84.56835 26.698247,-155.86557 72.010107,-223.21429 16.59166,-24.6608 30.37464,-41.20638 53.34679,-64.03941 27.30359,-27.13822 52.65045,-46.7668 84.88257,-65.73293 55.05852,-32.39773 124.18158,-53.51654 183.99427,-56.214822 7.95557,-0.358893 17.65123,-0.906877 21.54594,-1.217743 L 500,76.392444 V 288.19622 500 H 288.29357 76.58715 Z"
|
||||
id="path1516" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:7.38916;stroke-miterlimit:10"
|
||||
d="M 500,711.76464 V 500 h 211.90502 211.90504 l -0.7671,13.23892 c -1.37279,23.69173 -3.21854,41.23939 -6.18546,58.80541 -24.78089,146.71813 -128.58118,271.82029 -269.07425,324.29358 -38.30204,14.30558 -84.14865,23.99629 -120.68965,25.51049 -8.46675,0.35085 -18.02648,0.87257 -21.24385,1.1594 L 500,923.52927 Z"
|
||||
id="path3257" /></g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.0 KiB |
@ -64,6 +64,13 @@ technology = FFF
|
||||
family = PREDATOR
|
||||
default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR
|
||||
|
||||
[printer_model:PHOTON MONO X]
|
||||
name = Photon Mono X
|
||||
variants = default
|
||||
technology = SLA
|
||||
family = PHOTON MONO
|
||||
default_materials = Generic Blue Resin MONO @0.05
|
||||
|
||||
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||
# not make it into the user interface.
|
||||
|
||||
@ -1898,3 +1905,96 @@ default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
|
||||
#########################################
|
||||
########## end printer presets ##########
|
||||
#########################################
|
||||
|
||||
#########################################
|
||||
########## SLA printer presets ##########
|
||||
#########################################
|
||||
|
||||
|
||||
[sla_print:*common print ANYCUBIC SLA*]
|
||||
compatible_printers_condition = family=="PHOTON MONO"
|
||||
layer_height = 0.05
|
||||
output_filename_format = [input_filename_base].pwmx
|
||||
pad_edge_radius = 0.5
|
||||
pad_enable = 0
|
||||
pad_max_merge_distance = 50
|
||||
pad_wall_height = 0
|
||||
pad_wall_thickness = 1
|
||||
pad_wall_slope = 45
|
||||
faded_layers = 8
|
||||
slice_closing_radius = 0.005
|
||||
support_base_diameter = 3
|
||||
support_base_height = 1
|
||||
support_critical_angle = 45
|
||||
support_density_at_45 = 250
|
||||
support_density_at_horizontal = 500
|
||||
support_head_front_diameter = 0.4
|
||||
support_head_penetration = 0.4
|
||||
support_head_width = 3
|
||||
support_max_bridge_length = 10
|
||||
support_minimal_z = 0
|
||||
support_object_elevation = 5
|
||||
support_pillar_diameter = 1
|
||||
support_pillar_connection_mode = zigzag
|
||||
support_pillar_widening_factor = 0
|
||||
supports_enable = 1
|
||||
support_small_pillar_diameter_percent = 60%
|
||||
|
||||
[sla_print:0.05 ANYCUBIC SLA]
|
||||
inherits = *common print ANYCUBIC SLA*
|
||||
layer_height = 0.05
|
||||
|
||||
|
||||
########### Materials
|
||||
|
||||
[sla_material:*common ANYCUBIC SLA*]
|
||||
compatible_printers_condition = family=="PHOTON MONO"
|
||||
compatible_prints_condition = layer_height == 0.05
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 40
|
||||
initial_layer_height = 0.05
|
||||
material_correction = 1,1,1
|
||||
material_notes = LIFT_DISTANCE=8.0\nLIFT_SPEED=2.5\nRETRACT_SPEED=3.0\nBOTTOM_LIFT_SPEED=2.0\nBOTTOM_LIFT_DISTANCE=9.0\nDELAY_BEFORE_EXPOSURE=0.5
|
||||
|
||||
[sla_material:*common 0.05 ANYCUBIC SLA*]
|
||||
inherits = *common ANYCUBIC SLA*
|
||||
|
||||
[sla_material:Generic Blue Resin MONO @0.05]
|
||||
inherits = *common 0.05 ANYCUBIC SLA*
|
||||
exposure_time = 2.5
|
||||
initial_exposure_time = 40
|
||||
material_type = Tough
|
||||
material_vendor = Generic
|
||||
material_colour = #6080EC
|
||||
|
||||
########## Printers
|
||||
|
||||
[printer:Anycubic Photon Mono X]
|
||||
printer_technology = SLA
|
||||
printer_model = PHOTON MONO X
|
||||
printer_variant = default
|
||||
default_sla_material_profile = Generic Blue Resin MONO @0.05
|
||||
default_sla_print_profile = 0.05 ANYCUBIC SLA
|
||||
thumbnails = 224x168
|
||||
sla_archive_format = pwmx
|
||||
bed_shape = 1.48x1.02,193.48x1.02,193.48x121.02,1.48x121.02
|
||||
display_height = 120
|
||||
display_orientation = landscape
|
||||
display_mirror_x = 1
|
||||
display_mirror_y = 0
|
||||
display_pixels_x = 3840
|
||||
display_pixels_y = 2400
|
||||
display_width = 192
|
||||
max_print_height = 245
|
||||
elefant_foot_compensation = 0.2
|
||||
elefant_foot_min_width = 0.2
|
||||
min_exposure_time = 1
|
||||
max_exposure_time = 120
|
||||
min_initial_exposure_time = 1
|
||||
max_initial_exposure_time = 300
|
||||
printer_correction = 1,1,1
|
||||
gamma_correction = 1
|
||||
area_fill = 45
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.'\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PHOTONMONOX\n
|
||||
|
||||
|
||||
|
BIN
resources/profiles/Anycubic/PHOTON MONO X_thumbnail.png
Normal file
BIN
resources/profiles/Anycubic/PHOTON MONO X_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
18
resources/shaders/toolpaths_cog.fs
Normal file
18
resources/shaders/toolpaths_cog.fs
Normal file
@ -0,0 +1,18 @@
|
||||
#version 110
|
||||
|
||||
const vec4 BLACK = vec4(vec3(0.1), 1.0);
|
||||
const vec4 WHITE = vec4(vec3(1.0), 1.0);
|
||||
|
||||
const float emission_factor = 0.25;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
varying vec3 world_position;
|
||||
uniform vec3 world_center;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 delta = world_position - world_center;
|
||||
vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;
|
||||
gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0);
|
||||
}
|
40
resources/shaders/toolpaths_cog.vs
Normal file
40
resources/shaders/toolpaths_cog.vs
Normal file
@ -0,0 +1,40 @@
|
||||
#version 110
|
||||
|
||||
#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
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
varying vec3 world_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 normal = normalize(gl_NormalMatrix * gl_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(normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
world_position = gl_Vertex.xyz;
|
||||
gl_Position = ftransform();
|
||||
}
|
@ -165,8 +165,9 @@ namespace ImGui
|
||||
const wchar_t LegendColorChanges = 0x2612;
|
||||
const wchar_t LegendPausePrints = 0x2613;
|
||||
const wchar_t LegendCustomGCodes = 0x2614;
|
||||
const wchar_t LegendShells = 0x2615;
|
||||
const wchar_t LegendToolMarker = 0x2616;
|
||||
const wchar_t LegendCOG = 0x2615;
|
||||
const wchar_t LegendShells = 0x2616;
|
||||
const wchar_t LegendToolMarker = 0x2617;
|
||||
|
||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ set(SLIC3R_SOURCES
|
||||
Format/SL1.cpp
|
||||
Format/SL1_SVG.hpp
|
||||
Format/SL1_SVG.cpp
|
||||
Format/pwmx.hpp
|
||||
Format/pwmx.cpp
|
||||
GCode/ThumbnailData.cpp
|
||||
GCode/ThumbnailData.hpp
|
||||
GCode/Thumbnails.cpp
|
||||
|
509
src/libslic3r/Format/pwmx.cpp
Normal file
509
src/libslic3r/Format/pwmx.cpp
Normal file
@ -0,0 +1,509 @@
|
||||
#include "pwmx.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#define TAG_INTRO "ANYCUBIC\0\0\0\0"
|
||||
#define TAG_HEADER "HEADER\0\0\0\0\0\0"
|
||||
#define TAG_PREVIEW "PREVIEW\0\0\0\0\0"
|
||||
#define TAG_LAYERS "LAYERDEF\0\0\0\0"
|
||||
|
||||
#define CFG_LIFT_DISTANCE "LIFT_DISTANCE"
|
||||
#define CFG_LIFT_SPEED "LIFT_SPEED"
|
||||
#define CFG_RETRACT_SPEED "RETRACT_SPEED"
|
||||
#define CFG_DELAY_BEFORE_EXPOSURE "DELAY_BEFORE_EXPOSURE"
|
||||
#define CFG_BOTTOM_LIFT_SPEED "BOTTOM_LIFT_SPEED"
|
||||
#define CFG_BOTTOM_LIFT_DISTANCE "BOTTOM_LIFT_DISTANCE"
|
||||
|
||||
#define PREV_W 224
|
||||
#define PREV_H 168
|
||||
#define PREV_DPI 42
|
||||
|
||||
#define LAYER_SIZE_ESTIMATE (32 * 1024)
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using ConfMap = std::map<std::string, std::string>;
|
||||
|
||||
typedef struct pwmx_format_intro
|
||||
{
|
||||
char tag[12];
|
||||
std::uint32_t version; // value 1
|
||||
std::uint32_t area_num; // unknown - usually 4
|
||||
std::uint32_t header_data_offset;
|
||||
std::float_t intro24; // unknown - usually 0
|
||||
std::uint32_t preview_data_offset;
|
||||
std::float_t intro32; // unknown
|
||||
std::uint32_t layer_data_offset;
|
||||
std::float_t intro40; // unknown
|
||||
std::uint32_t image_data_offset;
|
||||
} pwmx_format_intro;
|
||||
|
||||
typedef struct pwmx_format_header
|
||||
{
|
||||
char tag[12];
|
||||
std::uint32_t payload_size;
|
||||
std::float_t pixel_size_um;
|
||||
std::float_t layer_height_mm;
|
||||
std::float_t exposure_time_s;
|
||||
std::float_t delay_before_exposure_s;
|
||||
std::float_t bottom_exposure_time_s;
|
||||
std::float_t bottom_layer_count;
|
||||
std::float_t lift_distance_mm;
|
||||
std::float_t lift_speed_mms;
|
||||
std::float_t retract_speed_mms;
|
||||
std::float_t volume_ml;
|
||||
std::uint32_t antialiasing;
|
||||
std::uint32_t res_x;
|
||||
std::uint32_t res_y;
|
||||
std::float_t weight_g;
|
||||
std::float_t price;
|
||||
std::uint32_t price_currency;
|
||||
std::uint32_t per_layer_override; // ? unknown meaning ?
|
||||
std::uint32_t print_time_s;
|
||||
std::uint32_t transition_layer_count;
|
||||
std::uint32_t unknown; // ? usually 0 ?
|
||||
|
||||
} pwmx_format_header;
|
||||
|
||||
typedef struct pwmx_format_preview
|
||||
{
|
||||
char tag[12];
|
||||
std::uint32_t payload_size;
|
||||
std::uint32_t preview_w;
|
||||
std::uint32_t preview_dpi;
|
||||
std::uint32_t preview_h;
|
||||
// raw image data in BGR565 format
|
||||
std::uint8_t pixels[PREV_W * PREV_H * 2];
|
||||
} pwmx_format_preview;
|
||||
|
||||
typedef struct pwmx_format_layers_header
|
||||
{
|
||||
char tag[12];
|
||||
std::uint32_t payload_size;
|
||||
std::uint32_t layer_count;
|
||||
} pwmx_format_layers_header;
|
||||
|
||||
typedef struct pwmx_format_layer
|
||||
{
|
||||
std::uint32_t image_offset;
|
||||
std::uint32_t image_size;
|
||||
std::float_t lift_distance_mm;
|
||||
std::float_t lift_speed_mms;
|
||||
std::float_t exposure_time_s;
|
||||
std::float_t layer_height_mm;
|
||||
std::float_t layer44; // unkown - usually 0
|
||||
std::float_t layer48; // unkown - usually 0
|
||||
} pwmx_format_layer;
|
||||
|
||||
typedef struct pwmx_format_misc
|
||||
{
|
||||
std::float_t bottom_layer_height_mm;
|
||||
std::float_t bottom_lift_distance_mm;
|
||||
std::float_t bottom_lift_speed_mms;
|
||||
|
||||
} pwmx_format_misc;
|
||||
|
||||
class PwmxFormatConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
PwmxFormatConfigDef()
|
||||
{
|
||||
add(CFG_LIFT_DISTANCE, coFloat);
|
||||
add(CFG_LIFT_SPEED, coFloat);
|
||||
add(CFG_RETRACT_SPEED, coFloat);
|
||||
add(CFG_DELAY_BEFORE_EXPOSURE, coFloat);
|
||||
add(CFG_BOTTOM_LIFT_DISTANCE, coFloat);
|
||||
add(CFG_BOTTOM_LIFT_SPEED, coFloat);
|
||||
}
|
||||
};
|
||||
|
||||
class PwmxFormatDynamicConfig : public DynamicConfig
|
||||
{
|
||||
public:
|
||||
PwmxFormatDynamicConfig(){};
|
||||
const ConfigDef *def() const override { return &config_def; }
|
||||
|
||||
private:
|
||||
PwmxFormatConfigDef config_def;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
const char *get_cfg_value(const DynamicConfig &cfg,
|
||||
const std::string & key,
|
||||
const std::string & def = "0")
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
if (cfg.has(key)) {
|
||||
auto opt = cfg.option(key);
|
||||
if (opt) {
|
||||
ret = opt->serialize();
|
||||
} else {
|
||||
return def.c_str();
|
||||
}
|
||||
} else {
|
||||
return def.c_str();
|
||||
}
|
||||
|
||||
return ret.c_str();
|
||||
}
|
||||
|
||||
template<class T> void crop_value(T &val, T val_min, T val_max)
|
||||
{
|
||||
if (val < val_min) {
|
||||
val = val_min;
|
||||
} else if (val > val_max) {
|
||||
val = val_max;
|
||||
}
|
||||
}
|
||||
|
||||
void fill_preview(pwmx_format_preview &p,
|
||||
pwmx_format_misc &m,
|
||||
ThumbnailsList &thumbnails)
|
||||
{
|
||||
|
||||
p.preview_w = PREV_W;
|
||||
p.preview_h = PREV_H;
|
||||
p.preview_dpi = PREV_DPI;
|
||||
p.payload_size = sizeof(p) - sizeof(p.tag) - sizeof(p.payload_size);
|
||||
|
||||
std::memset(p.pixels, 0 , sizeof(p.pixels));
|
||||
if (!thumbnails.empty()) {
|
||||
std::uint32_t dst_index;
|
||||
std::uint32_t i = 0;
|
||||
size_t len;
|
||||
size_t pixel_x = 0;
|
||||
auto t = thumbnails[0]; //use the first thumbnail
|
||||
len = t.pixels.size();
|
||||
//sanity check
|
||||
if (len != PREV_W * PREV_H * 4) {
|
||||
printf("incorrect thumbnail size. expected %ix%i\n", PREV_W, PREV_H);
|
||||
return;
|
||||
}
|
||||
// rearange pixels: they seem to be stored from bottom to top.
|
||||
dst_index = (PREV_W * (PREV_H - 1) * 2);
|
||||
while (i < len) {
|
||||
std::uint32_t pixel;
|
||||
std::uint32_t r = t.pixels[i++];
|
||||
std::uint32_t g = t.pixels[i++];
|
||||
std::uint32_t b = t.pixels[i++];
|
||||
i++; // Alpha
|
||||
// convert to BGRA565
|
||||
pixel = ((b >> 3) << 11) | ((g >>2) << 5) | (r >> 3);
|
||||
p.pixels[dst_index++] = pixel & 0xFF;
|
||||
p.pixels[dst_index++] = (pixel >> 8) & 0xFF;
|
||||
pixel_x++;
|
||||
if (pixel_x == PREV_W) {
|
||||
pixel_x = 0;
|
||||
dst_index -= (PREV_W * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fill_header(pwmx_format_header &h,
|
||||
pwmx_format_misc &m,
|
||||
const SLAPrint &print,
|
||||
std::uint32_t layer_count)
|
||||
{
|
||||
std::float_t bottle_weight_g;
|
||||
std::float_t bottle_volume_ml;
|
||||
std::float_t bottle_cost;
|
||||
std::float_t material_density;
|
||||
auto & cfg = print.full_print_config();
|
||||
std::string mnotes = cfg.option("material_notes")->serialize();
|
||||
// create a config parser from the material notes
|
||||
Slic3r::PwmxFormatDynamicConfig mat_cfg;
|
||||
SLAPrintStatistics stats = print.print_statistics();
|
||||
|
||||
// sanitize the string config
|
||||
boost::replace_all(mnotes, "\\n", "\n");
|
||||
boost::replace_all(mnotes, "\\r", "\r");
|
||||
mat_cfg.load_from_ini_string(mnotes,
|
||||
ForwardCompatibilitySubstitutionRule::Enable);
|
||||
|
||||
h.layer_height_mm = std::atof(get_cfg_value(cfg, "layer_height"));
|
||||
m.bottom_layer_height_mm = std::atof(
|
||||
get_cfg_value(cfg, "initial_layer_height"));
|
||||
h.exposure_time_s = std::atof(get_cfg_value(cfg, "exposure_time"));
|
||||
h.bottom_exposure_time_s = std::atof(
|
||||
get_cfg_value(cfg, "initial_exposure_time"));
|
||||
h.bottom_layer_count = std::atof(get_cfg_value(cfg, "faded_layers"));
|
||||
if (layer_count < h.bottom_layer_count) {
|
||||
h.bottom_layer_count = layer_count;
|
||||
}
|
||||
h.res_x = std::atol(get_cfg_value(cfg, "display_pixels_x"));
|
||||
h.res_y = std::atol(get_cfg_value(cfg, "display_pixels_y"));
|
||||
bottle_weight_g = std::atof(get_cfg_value(cfg, "bottle_weight")) * 1000.0f;
|
||||
bottle_volume_ml = std::atof(get_cfg_value(cfg, "bottle_volume"));
|
||||
bottle_cost = std::atof(get_cfg_value(cfg, "bottle_cost"));
|
||||
material_density = bottle_weight_g / bottle_volume_ml;
|
||||
|
||||
h.volume_ml = (stats.objects_used_material + stats.support_used_material) / 1000;
|
||||
h.weight_g = h.volume_ml * material_density;
|
||||
h.price = (h.volume_ml * bottle_cost) / bottle_volume_ml;
|
||||
h.price_currency = '$';
|
||||
h.antialiasing = 1;
|
||||
h.per_layer_override = 0;
|
||||
|
||||
// TODO - expose these variables to the UI rather than using material notes
|
||||
h.delay_before_exposure_s = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_DELAY_BEFORE_EXPOSURE, "0.5"));
|
||||
crop_value(h.delay_before_exposure_s, 0.0f, 1000.0f);
|
||||
|
||||
h.lift_distance_mm = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_LIFT_DISTANCE, "8.0"));
|
||||
crop_value(h.lift_distance_mm, 0.0f, 100.0f);
|
||||
|
||||
if (mat_cfg.has(CFG_BOTTOM_LIFT_DISTANCE)) {
|
||||
m.bottom_lift_distance_mm = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_DISTANCE, "8.0"));
|
||||
crop_value(h.lift_distance_mm, 0.0f, 100.0f);
|
||||
} else {
|
||||
m.bottom_lift_distance_mm = h.lift_distance_mm;
|
||||
}
|
||||
|
||||
|
||||
h.lift_speed_mms = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_LIFT_SPEED, "2.0"));
|
||||
crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f);
|
||||
|
||||
if (mat_cfg.has(CFG_BOTTOM_LIFT_SPEED)) {
|
||||
m.bottom_lift_speed_mms = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_BOTTOM_LIFT_SPEED, "2.0"));
|
||||
crop_value(m.bottom_lift_speed_mms, 0.1f, 20.0f);
|
||||
} else {
|
||||
m.bottom_lift_speed_mms = h.lift_speed_mms;
|
||||
}
|
||||
|
||||
h.retract_speed_mms = std::atof(
|
||||
get_cfg_value(mat_cfg, CFG_RETRACT_SPEED, "3.0"));
|
||||
crop_value(h.lift_speed_mms, 0.1f, 20.0f);
|
||||
|
||||
h.print_time_s = (h.bottom_layer_count * h.bottom_exposure_time_s) +
|
||||
((layer_count - h.bottom_layer_count) *
|
||||
h.exposure_time_s) +
|
||||
(layer_count * h.lift_distance_mm / h.retract_speed_mms) +
|
||||
(layer_count * h.lift_distance_mm / h.lift_speed_mms) +
|
||||
(layer_count * h.delay_before_exposure_s);
|
||||
|
||||
|
||||
h.payload_size = sizeof(h) - sizeof(h.tag) - sizeof(h.payload_size);
|
||||
h.pixel_size_um = 50;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<sla::RasterBase> PwmxArchive::create_raster() const
|
||||
{
|
||||
sla::Resolution res;
|
||||
sla::PixelDim pxdim;
|
||||
std::array<bool, 2> mirror;
|
||||
|
||||
double w = m_cfg.display_width.getFloat();
|
||||
double h = m_cfg.display_height.getFloat();
|
||||
auto pw = size_t(m_cfg.display_pixels_x.getInt());
|
||||
auto ph = size_t(m_cfg.display_pixels_y.getInt());
|
||||
|
||||
mirror[X] = m_cfg.display_mirror_x.getBool();
|
||||
mirror[Y] = m_cfg.display_mirror_y.getBool();
|
||||
|
||||
auto ro = m_cfg.display_orientation.getInt();
|
||||
sla::RasterBase::Orientation orientation =
|
||||
ro == sla::RasterBase::roPortrait ? sla::RasterBase::roPortrait :
|
||||
sla::RasterBase::roLandscape;
|
||||
|
||||
if (orientation == sla::RasterBase::roPortrait) {
|
||||
std::swap(w, h);
|
||||
std::swap(pw, ph);
|
||||
}
|
||||
|
||||
res = sla::Resolution{pw, ph};
|
||||
pxdim = sla::PixelDim{w / pw, h / ph};
|
||||
sla::RasterBase::Trafo tr{orientation, mirror};
|
||||
|
||||
double gamma = m_cfg.gamma_correction.getFloat();
|
||||
|
||||
return sla::create_raster_grayscale_aa(res, pxdim, gamma, tr);
|
||||
}
|
||||
|
||||
sla::RasterEncoder PwmxArchive::get_encoder() const
|
||||
{
|
||||
return sla::PWXRasterEncoder{};
|
||||
}
|
||||
|
||||
// Endian safe write of little endian 32bit ints
|
||||
static void pwmx_write_int32(std::ofstream &out, std::uint32_t val)
|
||||
{
|
||||
const char i1 = (val & 0xFF);
|
||||
const char i2 = (val >> 8) & 0xFF;
|
||||
const char i3 = (val >> 16) & 0xFF;
|
||||
const char i4 = (val >> 24) & 0xFF;
|
||||
|
||||
out.write((const char *) &i1, 1);
|
||||
out.write((const char *) &i2, 1);
|
||||
out.write((const char *) &i3, 1);
|
||||
out.write((const char *) &i4, 1);
|
||||
}
|
||||
static void pwmx_write_float(std::ofstream &out, std::float_t val)
|
||||
{
|
||||
std::uint32_t *f = (std::uint32_t *) &val;
|
||||
pwmx_write_int32(out, *f);
|
||||
}
|
||||
|
||||
static void pwmx_write_intro(std::ofstream &out, pwmx_format_intro &i)
|
||||
{
|
||||
out.write(TAG_INTRO, sizeof(i.tag));
|
||||
pwmx_write_int32(out, i.version);
|
||||
pwmx_write_int32(out, i.area_num);
|
||||
pwmx_write_int32(out, i.header_data_offset);
|
||||
pwmx_write_int32(out, i.intro24);
|
||||
pwmx_write_int32(out, i.preview_data_offset);
|
||||
pwmx_write_int32(out, i.intro32);
|
||||
pwmx_write_int32(out, i.layer_data_offset);
|
||||
pwmx_write_int32(out, i.intro40);
|
||||
pwmx_write_int32(out, i.image_data_offset);
|
||||
}
|
||||
|
||||
static void pwmx_write_header(std::ofstream &out, pwmx_format_header &h)
|
||||
{
|
||||
out.write(TAG_HEADER, sizeof(h.tag));
|
||||
pwmx_write_int32(out, h.payload_size);
|
||||
pwmx_write_float(out, h.pixel_size_um);
|
||||
pwmx_write_float(out, h.layer_height_mm);
|
||||
pwmx_write_float(out, h.exposure_time_s);
|
||||
pwmx_write_float(out, h.delay_before_exposure_s);
|
||||
pwmx_write_float(out, h.bottom_exposure_time_s);
|
||||
pwmx_write_float(out, h.bottom_layer_count);
|
||||
pwmx_write_float(out, h.lift_distance_mm);
|
||||
pwmx_write_float(out, h.lift_speed_mms);
|
||||
pwmx_write_float(out, h.retract_speed_mms);
|
||||
pwmx_write_float(out, h.volume_ml);
|
||||
pwmx_write_int32(out, h.antialiasing);
|
||||
pwmx_write_int32(out, h.res_x);
|
||||
pwmx_write_int32(out, h.res_y);
|
||||
pwmx_write_float(out, h.weight_g);
|
||||
pwmx_write_float(out, h.price);
|
||||
pwmx_write_int32(out, h.price_currency);
|
||||
pwmx_write_int32(out, h.per_layer_override);
|
||||
pwmx_write_int32(out, h.print_time_s);
|
||||
pwmx_write_int32(out, h.transition_layer_count);
|
||||
pwmx_write_int32(out, h.unknown);
|
||||
}
|
||||
|
||||
static void pwmx_write_preview(std::ofstream &out, pwmx_format_preview &p)
|
||||
{
|
||||
out.write(TAG_PREVIEW, sizeof(p.tag));
|
||||
pwmx_write_int32(out, p.payload_size);
|
||||
pwmx_write_int32(out, p.preview_w);
|
||||
pwmx_write_int32(out, p.preview_dpi);
|
||||
pwmx_write_int32(out, p.preview_h);
|
||||
out.write((const char*) p.pixels, sizeof(p.pixels));
|
||||
}
|
||||
|
||||
static void pwmx_write_layers_header(std::ofstream &out, pwmx_format_layers_header &h)
|
||||
{
|
||||
out.write(TAG_LAYERS, sizeof(h.tag));
|
||||
pwmx_write_int32(out, h.payload_size);
|
||||
pwmx_write_int32(out, h.layer_count);
|
||||
}
|
||||
|
||||
static void pwmx_write_layer(std::ofstream &out, pwmx_format_layer &l)
|
||||
{
|
||||
pwmx_write_int32(out, l.image_offset);
|
||||
pwmx_write_int32(out, l.image_size);
|
||||
pwmx_write_float(out, l.lift_distance_mm);
|
||||
pwmx_write_float(out, l.lift_speed_mms);
|
||||
pwmx_write_float(out, l.exposure_time_s);
|
||||
pwmx_write_float(out, l.layer_height_mm);
|
||||
pwmx_write_float(out, l.layer44);
|
||||
pwmx_write_float(out, l.layer48);
|
||||
}
|
||||
|
||||
void PwmxArchive::export_print(const std::string fname,
|
||||
const SLAPrint & print,
|
||||
ThumbnailsList & thumbnails,
|
||||
const std::string &prjname)
|
||||
{
|
||||
std::uint32_t layer_count = m_layers.size();
|
||||
|
||||
pwmx_format_intro intro = {0};
|
||||
pwmx_format_header header = {0};
|
||||
pwmx_format_preview preview = {0};
|
||||
pwmx_format_layers_header layers_header = {0};
|
||||
pwmx_format_misc misc = {0};
|
||||
std::vector<uint8_t> layer_images;
|
||||
std::uint32_t image_offset;
|
||||
|
||||
intro.version = 1;
|
||||
intro.area_num = 4;
|
||||
intro.header_data_offset = sizeof(intro);
|
||||
intro.preview_data_offset = sizeof(intro) + sizeof(header);
|
||||
intro.layer_data_offset = intro.preview_data_offset + sizeof(preview);
|
||||
intro.image_data_offset = intro.layer_data_offset +
|
||||
sizeof(layers_header) +
|
||||
(sizeof(pwmx_format_layer) * layer_count);
|
||||
|
||||
fill_header(header, misc, print, layer_count);
|
||||
fill_preview(preview, misc, thumbnails);
|
||||
|
||||
try {
|
||||
// open the file and write the contents
|
||||
std::ofstream out;
|
||||
out.open(fname, std::ios::binary | std::ios::out | std::ios::trunc);
|
||||
pwmx_write_intro(out, intro);
|
||||
pwmx_write_header(out, header);
|
||||
pwmx_write_preview(out, preview);
|
||||
|
||||
layers_header.payload_size = intro.image_data_offset - intro.layer_data_offset -
|
||||
sizeof(layers_header.tag) - sizeof(layers_header.payload_size);
|
||||
layers_header.layer_count = layer_count;
|
||||
pwmx_write_layers_header(out, layers_header);
|
||||
|
||||
//layers
|
||||
layer_images.reserve(layer_count * LAYER_SIZE_ESTIMATE);
|
||||
image_offset = intro.image_data_offset;
|
||||
size_t i = 0;
|
||||
for (const sla::EncodedRaster &rst : m_layers) {
|
||||
pwmx_format_layer l;
|
||||
std::memset(&l, 0, sizeof(l));
|
||||
l.image_offset = image_offset;
|
||||
l.image_size = rst.size();
|
||||
if (i < header.bottom_layer_count) {
|
||||
l.exposure_time_s = header.bottom_exposure_time_s;
|
||||
l.layer_height_mm = misc.bottom_layer_height_mm;
|
||||
l.lift_distance_mm = misc.bottom_lift_distance_mm;
|
||||
l.lift_speed_mms = misc.bottom_lift_speed_mms;
|
||||
} else {
|
||||
l.exposure_time_s = header.exposure_time_s;
|
||||
l.layer_height_mm = header.layer_height_mm;
|
||||
l.lift_distance_mm = header.lift_distance_mm;
|
||||
l.lift_speed_mms = header.lift_speed_mms;
|
||||
}
|
||||
image_offset += l.image_size;
|
||||
pwmx_write_layer(out, l);
|
||||
// add the rle encoded layer image into the buffer
|
||||
const char* img_start = reinterpret_cast<const char*>(rst.data());
|
||||
const char* img_end = img_start + rst.size();
|
||||
std::copy(img_start, img_end, std::back_inserter(layer_images));
|
||||
i++;
|
||||
}
|
||||
const char* img_buffer = reinterpret_cast<const char*>(layer_images.data());
|
||||
out.write(img_buffer, layer_images.size());
|
||||
out.close();
|
||||
} catch(std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
// Rethrow the exception
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
36
src/libslic3r/Format/pwmx.hpp
Normal file
36
src/libslic3r/Format/pwmx.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef _SLIC3R_FORMAT_PWMX_HPP_
|
||||
#define _SLIC3R_FORMAT_PWMX_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class PwmxArchive: public SLAArchive {
|
||||
SLAPrinterConfig m_cfg;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<sla::RasterBase> create_raster() const override;
|
||||
sla::RasterEncoder get_encoder() const override;
|
||||
|
||||
SLAPrinterConfig & cfg() { return m_cfg; }
|
||||
const SLAPrinterConfig & cfg() const { return m_cfg; }
|
||||
|
||||
public:
|
||||
|
||||
PwmxArchive() = default;
|
||||
explicit PwmxArchive(const SLAPrinterConfig &cfg): m_cfg(cfg) {}
|
||||
explicit PwmxArchive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {}
|
||||
|
||||
void export_print(const std::string fname,
|
||||
const SLAPrint &print,
|
||||
ThumbnailsList &thumbnails,
|
||||
const std::string &projectname = "") override;
|
||||
bool uses_zipper_export() override {return false;}
|
||||
};
|
||||
|
||||
|
||||
} // namespace Slic3r::sla
|
||||
|
||||
#endif // _SLIC3R_FORMAT_PWMX_HPP_
|
@ -174,7 +174,7 @@ namespace Slic3r {
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n";
|
||||
auto end = this->path.points.end();
|
||||
bool done = false;
|
||||
for (; it != end; ++ it) {
|
||||
for (; it != end && ! done; ++ it) {
|
||||
p = gcodegen.point_to_gcode_quantized(*it);
|
||||
double segment_length = (p - prev).norm();
|
||||
double dE = GCodeFormatter::quantize_e(xy_to_e * segment_length);
|
||||
|
@ -1196,6 +1196,7 @@ void GCodeProcessor::reset()
|
||||
m_line_id = 0;
|
||||
m_last_line_id = 0;
|
||||
m_feedrate = 0.0f;
|
||||
m_feed_multiply.reset();
|
||||
m_width = 0.0f;
|
||||
m_height = 0.0f;
|
||||
m_forced_width = 0.0f;
|
||||
@ -1698,6 +1699,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
|
||||
break;
|
||||
case '2':
|
||||
switch (cmd[3]) {
|
||||
case '0': { process_M220(line); break; } // Set Feedrate Percentage
|
||||
case '1': { process_M221(line); break; } // Set extrude factor override percentage
|
||||
default: break;
|
||||
}
|
||||
@ -2498,7 +2500,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
|
||||
// updates feedrate from line, if present
|
||||
if (line.has_f())
|
||||
m_feedrate = line.f() * MMMIN_TO_MMSEC;
|
||||
m_feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
|
||||
|
||||
// calculates movement deltas
|
||||
float max_abs_delta = 0.0f;
|
||||
@ -2863,7 +2865,7 @@ void GCodeProcessor::process_G61(const GCodeReader::GCodeLine& line)
|
||||
modified = true;
|
||||
}
|
||||
if (line.has_f())
|
||||
m_feedrate = line.f();
|
||||
m_feedrate = m_feed_multiply.current * line.f();
|
||||
|
||||
if (!modified)
|
||||
m_end_position = m_saved_position;
|
||||
@ -3136,6 +3138,20 @@ void GCodeProcessor::process_M205(const GCodeReader::GCodeLine& line)
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M220(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (m_flavor != gcfMarlinLegacy && m_flavor != gcfMarlinFirmware)
|
||||
return;
|
||||
|
||||
if (line.has('B'))
|
||||
m_feed_multiply.saved = m_feed_multiply.current;
|
||||
float value;
|
||||
if (line.has_value('S', value))
|
||||
m_feed_multiply.current = value * 0.01f;
|
||||
if (line.has('R'))
|
||||
m_feed_multiply.current = m_feed_multiply.saved;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M221(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float value_s;
|
||||
|
@ -525,6 +525,17 @@ namespace Slic3r {
|
||||
unsigned int m_line_id;
|
||||
unsigned int m_last_line_id;
|
||||
float m_feedrate; // mm/s
|
||||
struct FeedMultiply
|
||||
{
|
||||
float current; // percentage
|
||||
float saved; // percentage
|
||||
|
||||
void reset() {
|
||||
current = 1.0f;
|
||||
saved = 1.0f;
|
||||
}
|
||||
};
|
||||
FeedMultiply m_feed_multiply;
|
||||
float m_width; // mm
|
||||
float m_height; // mm
|
||||
float m_forced_width; // mm
|
||||
@ -719,6 +730,9 @@ namespace Slic3r {
|
||||
// Advanced settings
|
||||
void process_M205(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set Feedrate Percentage
|
||||
void process_M220(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set extrude factor override percentage
|
||||
void process_M221(const GCodeReader::GCodeLine& line);
|
||||
|
||||
|
@ -16,6 +16,54 @@ const RasterBase::TMirroring RasterBase::MirrorX = {true, false};
|
||||
const RasterBase::TMirroring RasterBase::MirrorY = {false, true};
|
||||
const RasterBase::TMirroring RasterBase::MirrorXY = {true, true};
|
||||
|
||||
|
||||
|
||||
static void pwx_get_pixel_span(const std::uint8_t* ptr, const std::uint8_t* end,
|
||||
std::uint8_t& pixel, size_t& span_len)
|
||||
{
|
||||
size_t max_len;
|
||||
|
||||
span_len = 0;
|
||||
pixel = (*ptr) & 0xF0;
|
||||
// the maximum length of the span depends on the pixel color
|
||||
max_len = (pixel == 0 || pixel == 0xF0) ? 0xFFF : 0xF;
|
||||
while (((*ptr) & 0xF0) == pixel && ptr < end && span_len < max_len) {
|
||||
span_len++;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
EncodedRaster PWXRasterEncoder::operator()(const void *ptr, size_t w, size_t h,
|
||||
size_t num_components)
|
||||
{
|
||||
std::vector<uint8_t> dst;
|
||||
size_t span_len;
|
||||
std::uint8_t pixel;
|
||||
auto size = w * h * num_components;
|
||||
dst.reserve(size);
|
||||
|
||||
const std::uint8_t* src = reinterpret_cast<const std::uint8_t*>(ptr);
|
||||
const std::uint8_t* src_end = src + size;
|
||||
while (src < src_end) {
|
||||
pwx_get_pixel_span(src, src_end, pixel, span_len);
|
||||
src += span_len;
|
||||
// fully transparent of fully opaque pixel
|
||||
if (pixel == 0 || pixel == 0xF0) {
|
||||
pixel = pixel | (span_len >> 8);
|
||||
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
|
||||
pixel = span_len & 0xFF;
|
||||
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
|
||||
}
|
||||
// antialiased pixel
|
||||
else {
|
||||
pixel = pixel | span_len;
|
||||
std::copy(&pixel, (&pixel) + 1, std::back_inserter(dst));
|
||||
}
|
||||
}
|
||||
|
||||
return EncodedRaster(std::move(dst), "pwx");
|
||||
}
|
||||
|
||||
EncodedRaster PNGRasterEncoder::operator()(const void *ptr, size_t w, size_t h,
|
||||
size_t num_components)
|
||||
{
|
||||
|
@ -97,6 +97,10 @@ public:
|
||||
virtual EncodedRaster encode(RasterEncoder encoder) const = 0;
|
||||
};
|
||||
|
||||
struct PWXRasterEncoder {
|
||||
EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components);
|
||||
};
|
||||
|
||||
struct PNGRasterEncoder {
|
||||
EncodedRaster operator()(const void *ptr, size_t w, size_t h, size_t num_components);
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "Format/SL1.hpp"
|
||||
#include "Format/SL1_SVG.hpp"
|
||||
#include "Format/pwmx.hpp"
|
||||
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
@ -16,6 +17,8 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <miniz.h>
|
||||
|
||||
// #define SLAPRINT_DO_BENCHMARK
|
||||
|
||||
#ifdef SLAPRINT_DO_BENCHMARK
|
||||
@ -249,6 +252,9 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
||||
m_archiver = std::make_unique<SL1Archive>(m_printer_config);
|
||||
else if (m_printer_config.sla_archive_format.value == "SL2")
|
||||
m_archiver = std::make_unique<SL1_SVGArchive>(m_printer_config);
|
||||
else if (m_printer_config.sla_archive_format.value == "pwmx") {
|
||||
m_archiver = std::make_unique<PwmxArchive>(m_printer_config);
|
||||
}
|
||||
}
|
||||
|
||||
struct ModelObjectStatus {
|
||||
@ -1265,4 +1271,16 @@ void SLAPrint::StatusReporter::operator()(SLAPrint & p,
|
||||
p.set_status(int(std::round(st)), msg, flags);
|
||||
}
|
||||
|
||||
|
||||
void SLAPrint::write_thumbnail(Zipper& zipper, const ThumbnailData& data)
|
||||
{
|
||||
size_t png_size = 0;
|
||||
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||
if (png_data != nullptr)
|
||||
{
|
||||
zipper.add_entry("thumbnail/thumbnail" + std::to_string(data.width) + "x" + std::to_string(data.height) + ".png", (const std::uint8_t*)png_data, png_size);
|
||||
mz_free(png_data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Point.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include "Zipper.hpp"
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
|
||||
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||
|
||||
@ -422,12 +423,16 @@ public:
|
||||
}
|
||||
|
||||
// Export the print into an archive using the provided zipper.
|
||||
// TODO: Use an archive writer interface instead of Zipper.
|
||||
// This is quite limiting as the Zipper is a complete class, not an interface.
|
||||
// The output can only be a zip archive.
|
||||
virtual void export_print(Zipper &zipper,
|
||||
const SLAPrint &print,
|
||||
const std::string &projectname = "") = 0;
|
||||
const std::string &projectname = "") {};
|
||||
// Export the print into an archive using the provided filename.
|
||||
virtual void export_print(const std::string fname,
|
||||
const SLAPrint &print,
|
||||
ThumbnailsList &thumbnails,
|
||||
const std::string &projectname = "") {};
|
||||
// By default the exporters use zipper export. Return false to use file export.
|
||||
virtual bool uses_zipper_export() { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -533,16 +538,27 @@ public:
|
||||
// The aggregated and leveled print records from various objects.
|
||||
// TODO: use this structure for the preview in the future.
|
||||
const std::vector<PrintLayer>& print_layers() const { return m_printer_input; }
|
||||
|
||||
void export_print(Zipper &zipper, const std::string &projectname = "")
|
||||
{
|
||||
m_archiver->export_print(zipper, *this, projectname);
|
||||
}
|
||||
|
||||
void write_thumbnail(Zipper& zipper, const ThumbnailData& data);
|
||||
|
||||
void export_print(const std::string &fname, const std::string &projectname = "")
|
||||
{
|
||||
Zipper zipper(fname);
|
||||
export_print(zipper, projectname);
|
||||
Slic3r::ThumbnailsList thumbnails; //empty thumbnail list
|
||||
export_print(fname, thumbnails, projectname);
|
||||
}
|
||||
|
||||
void export_print(const std::string &fname, Slic3r::ThumbnailsList &thumbnails, const std::string &projectname = "")
|
||||
{
|
||||
if (m_archiver->uses_zipper_export()) {
|
||||
Zipper zipper(fname);
|
||||
m_archiver->export_print(zipper, *this, projectname);
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
if (data.is_valid())
|
||||
write_thumbnail(zipper, data);
|
||||
zipper.finalize();
|
||||
} else {
|
||||
m_archiver->export_print(fname, *this, thumbnails, projectname);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -68,10 +68,16 @@
|
||||
#define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable removal of old OpenGL render calls
|
||||
#define ENABLE_GLBEGIN_GLEND_REMOVAL (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable replace GLIndexedVertexArray with GLModel
|
||||
#define ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL (1 && ENABLE_GLBEGIN_GLEND_REMOVAL)
|
||||
// Enable show non-manifold edges
|
||||
#define ENABLE_SHOW_NON_MANIFOLD_EDGES (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable rework of Reload from disk command
|
||||
#define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable showing toolpaths center of gravity
|
||||
#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable recalculating toolpaths when switching to/from volumetric rate visualization
|
||||
#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable editing volumes transformation in world coordinates and instances in local coordinates
|
||||
#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable showing world coordinates of volumes' offset relative to the instance containing them
|
||||
|
@ -311,10 +311,10 @@ void Bed3D::init_triangles()
|
||||
if (triangles.empty() || triangles.size() % 3 != 0)
|
||||
return;
|
||||
|
||||
const GLModel::Geometry::EIndexType index_type = (triangles.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT;
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2, index_type };
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2, GLModel::Geometry::index_type(triangles.size()) };
|
||||
init_data.reserve_vertices(triangles.size());
|
||||
init_data.reserve_indices(triangles.size() / 3);
|
||||
|
||||
Vec2f min = triangles.front();
|
||||
Vec2f max = min;
|
||||
@ -330,13 +330,14 @@ void Bed3D::init_triangles()
|
||||
Vec2f inv_size = size.cwiseInverse();
|
||||
inv_size.y() *= -1.0f;
|
||||
|
||||
// vertices + indices
|
||||
unsigned int vertices_counter = 0;
|
||||
for (const Vec2f& v : triangles) {
|
||||
const Vec3f p = { v.x(), v.y(), GROUND_Z };
|
||||
init_data.add_vertex(p, (Vec2f)v.cwiseProduct(inv_size).eval());
|
||||
init_data.add_vertex(p, (Vec2f)(v - min).cwiseProduct(inv_size).eval());
|
||||
++vertices_counter;
|
||||
if (vertices_counter % 3 == 0) {
|
||||
if (index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_triangle((unsigned short)vertices_counter - 3, (unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
|
||||
else
|
||||
init_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||
@ -378,16 +379,16 @@ void Bed3D::init_gridlines()
|
||||
Lines contour_lines = to_lines(m_contour);
|
||||
std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines));
|
||||
|
||||
const GLModel::Geometry::EIndexType index_type = (gridlines.size() < 65536 / 2) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT;
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, index_type };
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(2 * gridlines.size()) };
|
||||
init_data.reserve_vertices(2 * gridlines.size());
|
||||
init_data.reserve_indices(2 * gridlines.size());
|
||||
|
||||
for (const Line& l : gridlines) {
|
||||
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), GROUND_Z));
|
||||
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), GROUND_Z));
|
||||
const unsigned int vertices_counter = (unsigned int)init_data.vertices_count();
|
||||
if (index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_line((unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
|
||||
else
|
||||
init_data.add_uint_line(vertices_counter - 2, vertices_counter - 1);
|
||||
@ -701,7 +702,9 @@ void Bed3D::render_default(bool bottom, bool picking)
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if (m_model.get_filename().empty() && !bottom) {
|
||||
const bool has_model = !m_model.get_filename().empty();
|
||||
|
||||
if (!has_model && !bottom) {
|
||||
// draw background
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
m_triangles.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
@ -712,7 +715,7 @@ void Bed3D::render_default(bool bottom, bool picking)
|
||||
if (!picking) {
|
||||
// draw grid
|
||||
glsafe(::glLineWidth(1.5f * m_scale_factor));
|
||||
m_gridlines.set_color(picking ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR);
|
||||
m_gridlines.set_color(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR);
|
||||
m_gridlines.render();
|
||||
}
|
||||
|
||||
|
@ -326,8 +326,8 @@ void GLVolume::SinkingContours::update()
|
||||
for (const ExPolygon& expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) {
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(expoly);
|
||||
init_data.vertices.reserve(init_data.vertices.size() + triangulation.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(init_data.indices.size() + triangulation.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(init_data.vertices_count() + triangulation.size());
|
||||
init_data.reserve_indices(init_data.indices_count() + triangulation.size());
|
||||
for (const Vec3d& v : triangulation) {
|
||||
init_data.add_vertex((Vec3f)(v.cast<float>() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
|
||||
++vertices_counter;
|
||||
@ -400,9 +400,9 @@ void GLVolume::NonManifoldEdges::update()
|
||||
if (!edges.empty()) {
|
||||
GUI::GLModel::Geometry init_data;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Lines, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::EIndexType::UINT };
|
||||
init_data.vertices.reserve(2 * edges.size() * GUI::GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * edges.size() * GUI::GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Lines, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::index_type(2 * edges.size()) };
|
||||
init_data.reserve_vertices(2 * edges.size());
|
||||
init_data.reserve_indices(2 * edges.size());
|
||||
|
||||
// vertices + indices
|
||||
unsigned int vertices_count = 0;
|
||||
@ -410,7 +410,10 @@ void GLVolume::NonManifoldEdges::update()
|
||||
init_data.add_vertex((Vec3f)mesh.its.vertices[edge.first].cast<float>());
|
||||
init_data.add_vertex((Vec3f)mesh.its.vertices[edge.second].cast<float>());
|
||||
vertices_count += 2;
|
||||
init_data.add_uint_line(vertices_count - 2, vertices_count - 1);
|
||||
if (init_data.format.index_type == GUI::GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_line((unsigned short)vertices_count - 2, (unsigned short)vertices_count - 1);
|
||||
else
|
||||
init_data.add_uint_line(vertices_count - 2, vertices_count - 1);
|
||||
}
|
||||
m_model.init_from(std::move(init_data));
|
||||
#else
|
||||
@ -681,13 +684,12 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
||||
for (int instance_idx : instance_idxs)
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized));
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, opengl_initialized));
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
@ -696,16 +698,13 @@ int GLVolumeCollection::load_object_volume(
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
const TriangleMesh &mesh = model_volume->mesh();
|
||||
ColorRGBA color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4];
|
||||
color.a(model_volume->is_model_part() ? 1.0f : 0.5f);
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
this->volumes.emplace_back(new GLVolume());
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.set_color(color_from_model_volume(*model_volume));
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
|
@ -593,7 +593,6 @@ public:
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized);
|
||||
|
||||
int load_object_volume(
|
||||
@ -601,7 +600,6 @@ public:
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
|
@ -165,17 +165,6 @@ void BackgroundSlicingProcess::process_fff()
|
||||
}
|
||||
}
|
||||
|
||||
static void write_thumbnail(Zipper& zipper, const ThumbnailData& data)
|
||||
{
|
||||
size_t png_size = 0;
|
||||
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||
if (png_data != nullptr)
|
||||
{
|
||||
zipper.add_entry("thumbnail/thumbnail" + std::to_string(data.width) + "x" + std::to_string(data.height) + ".png", (const std::uint8_t*)png_data, png_size);
|
||||
mz_free(png_data);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundSlicingProcess::process_sla()
|
||||
{
|
||||
assert(m_print == m_sla_print);
|
||||
@ -189,12 +178,7 @@ void BackgroundSlicingProcess::process_sla()
|
||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||
|
||||
Zipper zipper(export_path);
|
||||
m_sla_print->export_print(zipper);
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
if (data.is_valid())
|
||||
write_thumbnail(zipper, data);
|
||||
zipper.finalize();
|
||||
m_sla_print->export_print(export_path, thumbnails);
|
||||
|
||||
m_print->set_status(100, (boost::format(_utf8(L("Masked SLA file exported to %1%"))) % export_path).str());
|
||||
} else if (! m_upload_job.empty()) {
|
||||
@ -739,13 +723,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
||||
|
||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||
// true, false, true, true); // renders also supports and pad
|
||||
Zipper zipper{source_path.string()};
|
||||
m_sla_print->export_print(zipper, m_upload_job.upload_data.upload_path.string());
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
if (data.is_valid())
|
||||
write_thumbnail(zipper, data);
|
||||
zipper.finalize();
|
||||
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.string());
|
||||
}
|
||||
|
||||
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
||||
|
@ -103,7 +103,11 @@ void GCodeViewer::IBuffer::reset()
|
||||
count = 0;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move, bool account_for_volumetric_rate) const
|
||||
#else
|
||||
bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move) const
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
{
|
||||
auto matches_percent = [](float value1, float value2, float max_percent) {
|
||||
return std::abs(value2 - value1) / value1 <= max_percent;
|
||||
@ -120,10 +124,22 @@ bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move) co
|
||||
case EMoveType::Seam:
|
||||
case EMoveType::Extrude: {
|
||||
// use rounding to reduce the number of generated paths
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (account_for_volumetric_rate)
|
||||
return type == move.type && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id && role == move.extrusion_role &&
|
||||
move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed &&
|
||||
height == round_to_bin(move.height) && width == round_to_bin(move.width) &&
|
||||
matches_percent(volumetric_rate, move.volumetric_rate(), 0.001f);
|
||||
else
|
||||
return type == move.type && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id && role == move.extrusion_role &&
|
||||
move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed &&
|
||||
height == round_to_bin(move.height) && width == round_to_bin(move.width);
|
||||
#else
|
||||
return type == move.type && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id && role == move.extrusion_role &&
|
||||
move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed &&
|
||||
height == round_to_bin(move.height) && width == round_to_bin(move.width) &&
|
||||
matches_percent(volumetric_rate, move.volumetric_rate(), 0.05f);
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
}
|
||||
case EMoveType::Travel: {
|
||||
return type == move.type && feedrate == move.feedrate && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id;
|
||||
@ -160,6 +176,66 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move
|
||||
move.volumetric_rate(), move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } });
|
||||
}
|
||||
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
void GCodeViewer::COG::render()
|
||||
{
|
||||
if (!m_visible)
|
||||
return;
|
||||
|
||||
init();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
const Vec3d position = cog();
|
||||
glsafe(::glTranslated(position.x(), position.y(), position.z()));
|
||||
if (m_fixed_size) {
|
||||
const double inv_zoom = wxGetApp().plater()->get_camera().get_inv_zoom();
|
||||
glsafe(::glScaled(inv_zoom, inv_zoom, inv_zoom));
|
||||
}
|
||||
m_model.render();
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
shader->stop_using();
|
||||
|
||||
////Show ImGui window
|
||||
//static float last_window_width = 0.0f;
|
||||
//static size_t last_text_length = 0;
|
||||
|
||||
//ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
//const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
|
||||
//imgui.set_next_window_pos(0.5f * static_cast<float>(cnv_size.get_width()), 0.0f, ImGuiCond_Always, 0.5f, 0.0f);
|
||||
//ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
//ImGui::SetNextWindowBgAlpha(0.25f);
|
||||
//imgui.begin(std::string("COG"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
//imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Center of mass") + ":");
|
||||
//ImGui::SameLine();
|
||||
//char buf[1024];
|
||||
//const Vec3d position = cog();
|
||||
//sprintf(buf, "X: %.3f, Y: %.3f, Z: %.3f", position.x(), position.y(), position.z());
|
||||
//imgui.text(std::string(buf));
|
||||
|
||||
//// force extra frame to automatically update window size
|
||||
//const float width = ImGui::GetWindowWidth();
|
||||
//const size_t length = strlen(buf);
|
||||
//if (width != last_window_width || length != last_text_length) {
|
||||
// last_window_width = width;
|
||||
// last_text_length = length;
|
||||
// imgui.set_requires_extra_frame();
|
||||
//}
|
||||
|
||||
//imgui.end();
|
||||
//ImGui::PopStyleVar();
|
||||
}
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
#if ENABLE_PREVIEW_LAYER_TIME
|
||||
float GCodeViewer::Extrusions::Range::step_size(EType type) const
|
||||
{
|
||||
@ -638,10 +714,19 @@ void GCodeViewer::init()
|
||||
void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& print, bool initialized)
|
||||
{
|
||||
// avoid processing if called with the same gcode_result
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (m_last_result_id == gcode_result.id &&
|
||||
(m_last_view_type == m_view_type || (m_last_view_type != EViewType::VolumetricRate && m_view_type != EViewType::VolumetricRate)))
|
||||
return;
|
||||
#else
|
||||
if (m_last_result_id == gcode_result.id)
|
||||
return;
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
|
||||
m_last_result_id = gcode_result.id;
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
m_last_view_type = m_view_type;
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
|
||||
// release gpu memory, if used
|
||||
reset();
|
||||
@ -955,6 +1040,9 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ColorChanges), is_toolpath_move_type_visible(EMoveType::Color_change));
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::PausePrints), is_toolpath_move_type_visible(EMoveType::Pause_Print));
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::CustomGCodes), is_toolpath_move_type_visible(EMoveType::Custom_GCode));
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::CenterOfGravity), m_cog.is_visible());
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Shells), m_shells.visible);
|
||||
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ToolMarker), m_sequential_view.marker.is_visible());
|
||||
#if !ENABLE_PREVIEW_LAYOUT
|
||||
@ -978,6 +1066,9 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
|
||||
set_toolpath_move_type_visible(EMoveType::Color_change, is_flag_set(static_cast<unsigned int>(Preview::OptionType::ColorChanges)));
|
||||
set_toolpath_move_type_visible(EMoveType::Pause_Print, is_flag_set(static_cast<unsigned int>(Preview::OptionType::PausePrints)));
|
||||
set_toolpath_move_type_visible(EMoveType::Custom_GCode, is_flag_set(static_cast<unsigned int>(Preview::OptionType::CustomGCodes)));
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
m_cog.set_visible(is_flag_set(static_cast<unsigned int>(Preview::OptionType::CenterOfGravity)));
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
m_shells.visible = is_flag_set(static_cast<unsigned int>(Preview::OptionType::Shells));
|
||||
m_sequential_view.marker.set_visible(is_flag_set(static_cast<unsigned int>(Preview::OptionType::ToolMarker)));
|
||||
#if !ENABLE_PREVIEW_LAYOUT
|
||||
@ -1200,9 +1291,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
// add current vertex
|
||||
add_vertex(curr);
|
||||
};
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
auto add_indices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer,
|
||||
unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id, bool account_for_volumetric_rate) {
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr, account_for_volumetric_rate)) {
|
||||
#else
|
||||
auto add_indices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer,
|
||||
unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
// add starting index
|
||||
indices.push_back(static_cast<IBufferType>(indices.size()));
|
||||
buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1);
|
||||
@ -1221,7 +1318,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
};
|
||||
|
||||
// format data into the buffers to be rendered as solid
|
||||
auto add_vertices_as_solid = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer, unsigned int vbuffer_id, VertexBuffer& vertices, size_t move_id) {
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
auto add_vertices_as_solid = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer,
|
||||
unsigned int vbuffer_id, VertexBuffer& vertices, size_t move_id, bool account_for_volumetric_rate) {
|
||||
#else
|
||||
auto add_vertices_as_solid = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, TBuffer& buffer,
|
||||
unsigned int vbuffer_id, VertexBuffer& vertices, size_t move_id) {
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
auto store_vertex = [](VertexBuffer& vertices, const Vec3f& position, const Vec3f& normal) {
|
||||
// append position
|
||||
vertices.push_back(position.x());
|
||||
@ -1233,7 +1336,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
vertices.push_back(normal.z());
|
||||
};
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr, account_for_volumetric_rate)) {
|
||||
#else
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
buffer.add_path(curr, vbuffer_id, vertices.size(), move_id - 1);
|
||||
buffer.paths.back().sub_paths.back().first.position = prev.position;
|
||||
}
|
||||
@ -1278,8 +1385,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
|
||||
last_path.sub_paths.back().last = { vbuffer_id, vertices.size(), move_id, curr.position };
|
||||
};
|
||||
auto add_indices_as_solid = [&](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, const GCodeProcessorResult::MoveVertex* next,
|
||||
TBuffer& buffer, size_t& vbuffer_size, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
auto add_indices_as_solid = [&](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr,
|
||||
const GCodeProcessorResult::MoveVertex* next, TBuffer& buffer, size_t& vbuffer_size, unsigned int ibuffer_id,
|
||||
IndexBuffer& indices, size_t move_id, bool account_for_volumetric_rate) {
|
||||
#else
|
||||
auto add_indices_as_solid = [&](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr,
|
||||
const GCodeProcessorResult::MoveVertex* next, TBuffer& buffer, size_t& vbuffer_size, unsigned int ibuffer_id,
|
||||
IndexBuffer& indices, size_t move_id) {
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
static Vec3f prev_dir;
|
||||
static Vec3f prev_up;
|
||||
static float sq_prev_length;
|
||||
@ -1324,7 +1438,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
store_triangle(indices, v_offsets[4], v_offsets[5], v_offsets[6]);
|
||||
};
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr, account_for_volumetric_rate)) {
|
||||
#else
|
||||
if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) {
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
buffer.add_path(curr, ibuffer_id, indices.size(), move_id - 1);
|
||||
buffer.paths.back().sub_paths.back().first.position = prev.position;
|
||||
}
|
||||
@ -1408,7 +1526,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
vbuffer_size += 6;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (next != nullptr && (curr.type != next->type || !last_path.matches(*next, account_for_volumetric_rate)))
|
||||
#else
|
||||
if (next != nullptr && (curr.type != next->type || !last_path.matches(*next)))
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
// ending cap triangles
|
||||
append_ending_cap_triangles(indices, is_first_segment ? first_seg_v_offsets : non_first_seg_v_offsets);
|
||||
|
||||
@ -1537,6 +1659,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
if (wxGetApp().is_editor())
|
||||
m_contained_in_bed = wxGetApp().plater()->build_volume().all_paths_inside(gcode_result, m_paths_bounding_box);
|
||||
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
m_cog.reset();
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
m_sequential_view.gcode_ids.clear();
|
||||
for (size_t i = 0; i < gcode_result.moves.size(); ++i) {
|
||||
const GCodeProcessorResult::MoveVertex& move = gcode_result.moves[i];
|
||||
@ -1544,6 +1670,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
m_sequential_view.gcode_ids.push_back(move.gcode_id);
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
bool account_for_volumetric_rate = m_view_type == EViewType::VolumetricRate;
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
|
||||
std::vector<MultiVertexBuffer> vertices(m_buffers.size());
|
||||
std::vector<MultiIndexBuffer> indices(m_buffers.size());
|
||||
std::vector<InstanceBuffer> instances(m_buffers.size());
|
||||
@ -1551,18 +1681,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
std::vector<InstancesOffsets> instances_offsets(m_buffers.size());
|
||||
std::vector<float> options_zs;
|
||||
|
||||
size_t seams_count = 0;
|
||||
std::vector<size_t> biased_seams_ids;
|
||||
|
||||
// toolpaths data -> extract vertices from result
|
||||
for (size_t i = 0; i < m_moves_count; ++i) {
|
||||
const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i];
|
||||
if (curr.type == EMoveType::Seam) {
|
||||
++seams_count;
|
||||
if (curr.type == EMoveType::Seam)
|
||||
biased_seams_ids.push_back(i - biased_seams_ids.size() - 1);
|
||||
}
|
||||
|
||||
size_t move_id = i - seams_count;
|
||||
const size_t move_id = i - biased_seams_ids.size();
|
||||
|
||||
// skip first vertex
|
||||
if (i == 0)
|
||||
@ -1570,6 +1697,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
|
||||
const GCodeProcessorResult::MoveVertex& prev = gcode_result.moves[i - 1];
|
||||
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
if (curr.type == EMoveType::Extrude &&
|
||||
curr.extrusion_role != erSkirt &&
|
||||
curr.extrusion_role != erSupportMaterial &&
|
||||
curr.extrusion_role != erSupportMaterialInterface &&
|
||||
curr.extrusion_role != erWipeTower &&
|
||||
curr.extrusion_role != erCustom &&
|
||||
curr.extrusion_role != erMixed) {
|
||||
const Vec3d curr_pos = curr.position.cast<double>();
|
||||
const Vec3d prev_pos = prev.position.cast<double>();
|
||||
m_cog.add_segment(curr_pos, prev_pos, curr.mm3_per_mm * (curr_pos - prev_pos).norm());
|
||||
}
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
// update progress dialog
|
||||
++progress_count;
|
||||
if (progress_dialog != nullptr && progress_count % progress_threshold == 0) {
|
||||
@ -1597,7 +1738,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
v_multibuffer.push_back(VertexBuffer());
|
||||
if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
|
||||
Path& last_path = t_buffer.paths.back();
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
if (prev.type == curr.type && last_path.matches(curr, account_for_volumetric_rate))
|
||||
#else
|
||||
if (prev.type == curr.type && last_path.matches(curr))
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
last_path.add_sub_path(prev, static_cast<unsigned int>(v_multibuffer.size()) - 1, 0, move_id - 1);
|
||||
}
|
||||
}
|
||||
@ -1608,7 +1753,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
{
|
||||
case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; }
|
||||
case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; }
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, move_id, account_for_volumetric_rate); break; }
|
||||
#else
|
||||
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, move_id); break; }
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
case TBuffer::ERenderPrimitiveType::InstancedModel:
|
||||
{
|
||||
add_model_instance(curr, inst_buffer, inst_id_buffer, move_id);
|
||||
@ -1893,14 +2042,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
using VboIndexList = std::vector<unsigned int>;
|
||||
std::vector<VboIndexList> vbo_indices(m_buffers.size());
|
||||
|
||||
seams_count = 0;
|
||||
size_t seams_count = 0;
|
||||
|
||||
for (size_t i = 0; i < m_moves_count; ++i) {
|
||||
const GCodeProcessorResult::MoveVertex& curr = gcode_result.moves[i];
|
||||
if (curr.type == EMoveType::Seam)
|
||||
++seams_count;
|
||||
|
||||
size_t move_id = i - seams_count;
|
||||
const size_t move_id = i - seams_count;
|
||||
|
||||
// skip first vertex
|
||||
if (i == 0)
|
||||
@ -1972,12 +2121,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
||||
break;
|
||||
}
|
||||
case TBuffer::ERenderPrimitiveType::Line: {
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id, account_for_volumetric_rate);
|
||||
#else
|
||||
add_indices_as_line(prev, curr, t_buffer, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
curr_vertex_buffer.second += t_buffer.max_vertices_per_segment();
|
||||
break;
|
||||
}
|
||||
case TBuffer::ERenderPrimitiveType::Triangle: {
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id, account_for_volumetric_rate);
|
||||
#else
|
||||
add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, move_id);
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
break;
|
||||
}
|
||||
case TBuffer::ERenderPrimitiveType::BatchedModel: {
|
||||
@ -2149,7 +2306,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized)
|
||||
}
|
||||
|
||||
size_t current_volumes_count = m_shells.volumes.volumes.size();
|
||||
m_shells.volumes.load_object(model_obj, object_id, instance_ids, "object", initialized);
|
||||
m_shells.volumes.load_object(model_obj, object_id, instance_ids, initialized);
|
||||
|
||||
// adjust shells' z if raft is present
|
||||
const SlicingParameters& slicing_parameters = obj->slicing_parameters();
|
||||
@ -4074,15 +4231,6 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
};
|
||||
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
// auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) {
|
||||
// const float margin = 3.0f;
|
||||
// const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size));
|
||||
// window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
|
||||
// };
|
||||
// auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) {
|
||||
// const float margin = 3.0f;
|
||||
// window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f);
|
||||
// };
|
||||
auto image_icon = [&imgui](ImGuiWindow& window, const ImVec2& pos, float size, const wchar_t& icon_id) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
const ImTextureID tex_id = io.Fonts->TexID;
|
||||
@ -4091,17 +4239,17 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
const ImFontAtlas::CustomRect* const rect = imgui.GetTextureCustomRect(icon_id);
|
||||
const ImVec2 uv0 = { static_cast<float>(rect->X) / tex_w, static_cast<float>(rect->Y) / tex_h };
|
||||
const ImVec2 uv1 = { static_cast<float>(rect->X + rect->Width) / tex_w, static_cast<float>(rect->Y + rect->Height) / tex_h };
|
||||
window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f }));
|
||||
window.DrawList->AddImage(tex_id, pos, { pos.x + size, pos.y + size }, uv0, uv1, ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f }));
|
||||
};
|
||||
#else
|
||||
auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) {
|
||||
const float margin = 3.0f;
|
||||
auto circle_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const ColorRGBA& color) {
|
||||
const float margin = 3.0f;
|
||||
const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size));
|
||||
window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
|
||||
window.DrawList->AddCircleFilled(center, 0.5f * (size - 2.0f * margin), ImGuiWrapper::to_ImU32(color), 16);
|
||||
};
|
||||
auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const Color& color) {
|
||||
auto line_icon = [](ImGuiWindow& window, const ImVec2& pos, float size, const ColorRGBA& color) {
|
||||
const float margin = 3.0f;
|
||||
window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f);
|
||||
window.DrawList->AddLine({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin, pos.y + margin }, ImGuiWrapper::to_ImU32(color), 3.0f);
|
||||
};
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
|
||||
@ -4190,12 +4338,41 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
});
|
||||
ImGui::SameLine();
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
toggle_button(Preview::OptionType::CenterOfGravity, _u8L("Center of gravity"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
image_icon(window, pos, size, ImGui::LegendCOG);
|
||||
});
|
||||
#else
|
||||
toggle_button(Preview::OptionType::CenterOfGravity, _u8L("Center of gravity"), [](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
const ImU32 black = ImGuiWrapper::to_ImU32({ 0.0f, 0.0f, 0.0f, 1.0f });
|
||||
const ImU32 white = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
const float margin = 3.0f;
|
||||
const ImVec2 center(0.5f * (pos.x + pos.x + size), 0.5f * (pos.y + pos.y + size));
|
||||
const float radius = 0.5f * (size - 2.0f * margin);
|
||||
window.DrawList->PathArcToFast(center, radius, 0, 3);
|
||||
window.DrawList->PathLineTo(center);
|
||||
window.DrawList->PathFillConvex(black);
|
||||
window.DrawList->PathArcToFast(center, radius, 3, 6);
|
||||
window.DrawList->PathLineTo(center);
|
||||
window.DrawList->PathFillConvex(white);
|
||||
window.DrawList->PathArcToFast(center, radius, 6, 9);
|
||||
window.DrawList->PathLineTo(center);
|
||||
window.DrawList->PathFillConvex(black);
|
||||
window.DrawList->PathArcToFast(center, radius, 9, 12);
|
||||
window.DrawList->PathLineTo(center);
|
||||
window.DrawList->PathFillConvex(white);
|
||||
window.DrawList->AddCircle(center, radius, black, 16);
|
||||
});
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
ImGui::SameLine();
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [image_icon](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
image_icon(window, pos, size, ImGui::LegendShells);
|
||||
#else
|
||||
toggle_button(Preview::OptionType::Shells, _u8L("Shells"), [](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
const float margin = 3.0f;
|
||||
const float proj = 0.25f * size;
|
||||
window.DrawList->AddRect({ pos.x + margin, pos.y + size - margin }, { pos.x + size - margin - proj, pos.y + margin + proj }, color);
|
||||
@ -4212,11 +4389,11 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
image_icon(window, pos, size, ImGui::LegendToolMarker);
|
||||
#else
|
||||
toggle_button(Preview::OptionType::ToolMarker, _u8L("Tool marker"), [](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||
const ImU32 color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.8f });
|
||||
const ImU32 color = ImGuiWrapper::to_ImU32({ 1.0f, 1.0f, 1.0f, 0.8f });
|
||||
const float margin = 3.0f;
|
||||
const ImVec2 p1(0.5f * (pos.x + pos.x + size), pos.y + size - margin);
|
||||
const ImVec2 p2 = ImVec2(p1.x + 0.25f * size, p1.y - 0.25f * size);
|
||||
const ImVec2 p3 = ImVec2(p1.x - 0.25f * size, p1.y - 0.25f * size);
|
||||
const ImVec2 p2(p1.x + 0.25f * size, p1.y - 0.25f * size);
|
||||
const ImVec2 p3(p1.x - 0.25f * size, p1.y - 0.25f * size);
|
||||
window.DrawList->AddTriangleFilled(p1, p2, p3, color);
|
||||
const float mid_x = 0.5f * (pos.x + pos.x + size);
|
||||
window.DrawList->AddRectFilled({ mid_x - 0.09375f * size, p1.y - 0.25f * size }, { mid_x + 0.09375f * size, pos.y + margin }, color);
|
||||
|
@ -212,7 +212,11 @@ class GCodeViewer
|
||||
unsigned char cp_color_id{ 0 };
|
||||
std::vector<Sub_Path> sub_paths;
|
||||
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
bool matches(const GCodeProcessorResult::MoveVertex& move, bool account_for_volumetric_rate) const;
|
||||
#else
|
||||
bool matches(const GCodeProcessorResult::MoveVertex& move) const;
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
size_t vertices_count() const {
|
||||
return sub_paths.empty() ? 0 : sub_paths.back().last.s_id - sub_paths.front().first.s_id + 1;
|
||||
}
|
||||
@ -380,6 +384,52 @@ class GCodeViewer
|
||||
bool visible{ false };
|
||||
};
|
||||
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
// helper to render center of gravity
|
||||
class COG
|
||||
{
|
||||
GLModel m_model;
|
||||
bool m_visible{ false };
|
||||
// whether or not to render the model with fixed screen size
|
||||
bool m_fixed_size{ true };
|
||||
double m_total_mass{ 0.0 };
|
||||
Vec3d m_position{ Vec3d::Zero() };
|
||||
|
||||
public:
|
||||
void render();
|
||||
|
||||
void reset() {
|
||||
m_position = Vec3d::Zero();
|
||||
m_total_mass = 0.0;
|
||||
}
|
||||
|
||||
bool is_visible() const { return m_visible; }
|
||||
void set_visible(bool visible) { m_visible = visible; }
|
||||
|
||||
void add_segment(const Vec3d& v1, const Vec3d& v2, double mass) {
|
||||
assert(mass > 0.0);
|
||||
m_position += mass * 0.5 * (v1 + v2);
|
||||
m_total_mass += mass;
|
||||
}
|
||||
|
||||
Vec3d cog() const { return (m_total_mass > 0.0) ? (Vec3d)(m_position / m_total_mass) : Vec3d::Zero(); }
|
||||
|
||||
private:
|
||||
void init() {
|
||||
if (m_model.is_initialized())
|
||||
return;
|
||||
|
||||
const float radius = m_fixed_size ? 10.0f : 1.0f;
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_model.init_from(smooth_sphere(32, radius));
|
||||
#else
|
||||
m_model.init_from(its_make_sphere(radius, PI / 32.0));
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
};
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
// helper to render extrusion paths
|
||||
struct Extrusions
|
||||
{
|
||||
@ -716,6 +766,9 @@ public:
|
||||
private:
|
||||
bool m_gl_data_initialized{ false };
|
||||
unsigned int m_last_result_id{ 0 };
|
||||
#if ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
EViewType m_last_view_type{ EViewType::Count };
|
||||
#endif // ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC
|
||||
size_t m_moves_count{ 0 };
|
||||
std::vector<TBuffer> m_buffers{ static_cast<size_t>(EMoveType::Extrude) };
|
||||
// bounding box of toolpaths
|
||||
@ -734,6 +787,9 @@ private:
|
||||
Extrusions m_extrusions;
|
||||
SequentialView m_sequential_view;
|
||||
Shells m_shells;
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
COG m_cog;
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
EViewType m_view_type{ EViewType::FeatureType };
|
||||
bool m_legend_enabled{ true };
|
||||
#if ENABLE_PREVIEW_LAYOUT
|
||||
@ -779,6 +835,9 @@ public:
|
||||
|
||||
void reset();
|
||||
void render();
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
void render_cog() { m_cog.render(); }
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
bool has_data() const { return !m_roles.empty(); }
|
||||
bool can_export_toolpaths() const;
|
||||
|
@ -368,8 +368,8 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
const float l = bar_rect.get_left();
|
||||
@ -428,8 +428,8 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect)
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = ColorRGBA::BLACK();
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x;
|
||||
@ -447,16 +447,19 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect)
|
||||
m_profile.profile.reset();
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::UINT };
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::index_type(m_layer_height_profile.size() / 2) };
|
||||
init_data.color = ColorRGBA::BLUE();
|
||||
init_data.vertices.reserve(m_layer_height_profile.size() * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(m_layer_height_profile.size() * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(m_layer_height_profile.size() / 2);
|
||||
init_data.reserve_indices(m_layer_height_profile.size() / 2);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned int i = 0; i < (unsigned int)m_layer_height_profile.size(); i += 2) {
|
||||
init_data.add_vertex(Vec2f(bar_rect.get_left() + float(m_layer_height_profile[i + 1]) * scale_x,
|
||||
bar_rect.get_bottom() + float(m_layer_height_profile[i]) * scale_y));
|
||||
init_data.add_uint_index(i / 2);
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_index((unsigned short)i / 2);
|
||||
else
|
||||
init_data.add_uint_index(i / 2);
|
||||
}
|
||||
|
||||
m_profile.profile.init_from(std::move(init_data));
|
||||
@ -492,17 +495,17 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
|
||||
{
|
||||
assert(this->is_allowed());
|
||||
assert(this->last_object_id != -1);
|
||||
|
||||
GLShaderProgram* current_shader = wxGetApp().get_current_shader();
|
||||
ScopeGuard guard([current_shader]() { if (current_shader != nullptr) current_shader->start_using(); });
|
||||
if (current_shader != nullptr)
|
||||
current_shader->stop_using();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
GLShaderProgram* current_shader = wxGetApp().get_current_shader();
|
||||
if (shader->get_id() != current_shader->get_id())
|
||||
// The layer editing shader is not yet active. Activate it.
|
||||
shader->start_using();
|
||||
else
|
||||
// The layer editing shader was already active.
|
||||
current_shader = nullptr;
|
||||
shader->start_using();
|
||||
|
||||
generate_layer_height_texture();
|
||||
|
||||
@ -513,10 +516,10 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
|
||||
shader->set_uniform("z_cursor_band_width", float(this->band_width));
|
||||
|
||||
// Initialize the layer height texture mapping.
|
||||
GLsizei w = (GLsizei)m_layers_texture.width;
|
||||
GLsizei h = (GLsizei)m_layers_texture.height;
|
||||
GLsizei half_w = w / 2;
|
||||
GLsizei half_h = h / 2;
|
||||
const GLsizei w = (GLsizei)m_layers_texture.width;
|
||||
const GLsizei h = (GLsizei)m_layers_texture.height;
|
||||
const GLsizei half_w = w / 2;
|
||||
const GLsizei half_h = h / 2;
|
||||
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id));
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
||||
@ -525,17 +528,15 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
|
||||
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4));
|
||||
for (const GLVolume* glvolume : volumes.volumes) {
|
||||
// Render the object using the layer editing shader and texture.
|
||||
if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
|
||||
if (!glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
|
||||
continue;
|
||||
|
||||
shader->set_uniform("volume_world_matrix", glvolume->world_matrix());
|
||||
shader->set_uniform("object_max_z", GLfloat(0));
|
||||
shader->set_uniform("object_max_z", 0.0f);
|
||||
glvolume->render();
|
||||
}
|
||||
// Revert back to the previous shader.
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
if (current_shader != nullptr)
|
||||
current_shader->start_using();
|
||||
}
|
||||
|
||||
void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
|
||||
@ -898,6 +899,8 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
|
||||
unsigned int vertices_counter = 0;
|
||||
for (const ExPolygon& poly : polygons_union) {
|
||||
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(poly);
|
||||
fill_data.reserve_vertices(fill_data.vertices_count() + triangulation.size());
|
||||
fill_data.reserve_indices(fill_data.indices_count() + triangulation.size());
|
||||
for (const Vec3d& v : triangulation) {
|
||||
fill_data.add_vertex((Vec3f)(v.cast<float>() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
|
||||
++vertices_counter;
|
||||
@ -1101,7 +1104,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
, m_moving(false)
|
||||
, m_tab_down(false)
|
||||
, m_cursor_type(Standard)
|
||||
, m_color_by("volume")
|
||||
, m_reload_delayed(false)
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
, m_show_picking_texture(false)
|
||||
@ -1152,6 +1154,7 @@ bool GLCanvas3D::init()
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// Set antialiasing / multisampling
|
||||
glsafe(::glDisable(GL_LINE_SMOOTH));
|
||||
glsafe(::glDisable(GL_POLYGON_SMOOTH));
|
||||
@ -1181,6 +1184,7 @@ bool GLCanvas3D::init()
|
||||
// A handy trick -- have surface material mirror the color.
|
||||
glsafe(::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE));
|
||||
glsafe(::glEnable(GL_COLOR_MATERIAL));
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
if (m_multisample_allowed)
|
||||
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||
@ -1351,11 +1355,6 @@ void GLCanvas3D::bed_shape_changed()
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLCanvas3D::set_color_by(const std::string& value)
|
||||
{
|
||||
m_color_by = value;
|
||||
}
|
||||
|
||||
void GLCanvas3D::refresh_camera_scene_box()
|
||||
{
|
||||
wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box());
|
||||
@ -1600,6 +1599,10 @@ void GLCanvas3D::render()
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
_render_selection_center();
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
if (!m_main_toolbar.is_enabled())
|
||||
_render_gcode_cog();
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
// we need to set the mouse's scene position here because the depth buffer
|
||||
// could be invalidated by the following gizmo render methods
|
||||
@ -1796,7 +1799,7 @@ std::vector<int> GLCanvas3D::load_object(const ModelObject& model_object, int ob
|
||||
instance_idxs.emplace_back(i);
|
||||
}
|
||||
}
|
||||
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_initialized);
|
||||
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_initialized);
|
||||
}
|
||||
|
||||
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
||||
@ -2021,7 +2024,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
// Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
|
||||
// later in this function.
|
||||
it->volume_idx = m_volumes.volumes.size();
|
||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized);
|
||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_initialized);
|
||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||
update_object_list = true;
|
||||
} else {
|
||||
@ -5234,8 +5237,8 @@ void GLCanvas3D::_render_background()
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec2f(-1.0f, -1.0f), Vec2f(0.0f, 0.0f));
|
||||
@ -5415,6 +5418,13 @@ void GLCanvas3D::_render_gcode()
|
||||
m_gcode_viewer.render();
|
||||
}
|
||||
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
void GLCanvas3D::_render_gcode_cog()
|
||||
{
|
||||
m_gcode_viewer.render_cog();
|
||||
}
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
|
||||
void GLCanvas3D::_render_selection()
|
||||
{
|
||||
float scale_factor = 1.0;
|
||||
@ -5784,32 +5794,81 @@ void GLCanvas3D::_render_sla_slices()
|
||||
if (!obj->is_step_done(slaposSliceSupports))
|
||||
continue;
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
SlaCap::ObjectIdToModelsMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
|
||||
SlaCap::ObjectIdToModelsMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
|
||||
#else
|
||||
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
|
||||
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
{
|
||||
if (it_caps_bottom == m_sla_caps[0].triangles.end())
|
||||
it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
|
||||
if (!m_sla_caps[0].matches(clip_min_z)) {
|
||||
m_sla_caps[0].z = clip_min_z;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
it_caps_bottom->second.object.reset();
|
||||
it_caps_bottom->second.supports.reset();
|
||||
#else
|
||||
it_caps_bottom->second.object.clear();
|
||||
it_caps_bottom->second.supports.clear();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
if (it_caps_top == m_sla_caps[1].triangles.end())
|
||||
it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
|
||||
if (!m_sla_caps[1].matches(clip_max_z)) {
|
||||
m_sla_caps[1].z = clip_max_z;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
it_caps_top->second.object.reset();
|
||||
it_caps_top->second.supports.reset();
|
||||
#else
|
||||
it_caps_top->second.object.clear();
|
||||
it_caps_top->second.supports.clear();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
}
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel& bottom_obj_triangles = it_caps_bottom->second.object;
|
||||
GLModel& bottom_sup_triangles = it_caps_bottom->second.supports;
|
||||
GLModel& top_obj_triangles = it_caps_top->second.object;
|
||||
GLModel& top_sup_triangles = it_caps_top->second.supports;
|
||||
#else
|
||||
Pointf3s &bottom_obj_triangles = it_caps_bottom->second.object;
|
||||
Pointf3s &bottom_sup_triangles = it_caps_bottom->second.supports;
|
||||
Pointf3s &top_obj_triangles = it_caps_top->second.object;
|
||||
Pointf3s &top_sup_triangles = it_caps_top->second.supports;
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
auto init_model = [](GLModel& model, const Pointf3s& triangles, const ColorRGBA& color) {
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(triangles.size()) };
|
||||
init_data.reserve_vertices(triangles.size());
|
||||
init_data.reserve_indices(triangles.size() / 3);
|
||||
init_data.color = color;
|
||||
|
||||
unsigned int vertices_count = 0;
|
||||
for (const Vec3d& v : triangles) {
|
||||
init_data.add_vertex((Vec3f)v.cast<float>());
|
||||
++vertices_count;
|
||||
if (vertices_count % 3 == 0) {
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_triangle((unsigned short)vertices_count - 3, (unsigned short)vertices_count - 2, (unsigned short)vertices_count - 1);
|
||||
else
|
||||
init_data.add_uint_triangle(vertices_count - 3, vertices_count - 2, vertices_count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_data.is_empty())
|
||||
model.init_from(std::move(init_data));
|
||||
};
|
||||
|
||||
if ((!bottom_obj_triangles.is_initialized() || !bottom_sup_triangles.is_initialized() ||
|
||||
!top_obj_triangles.is_initialized() || !top_sup_triangles.is_initialized()) && !obj->get_slice_index().empty()) {
|
||||
#else
|
||||
if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) &&
|
||||
!obj->get_slice_index().empty())
|
||||
{
|
||||
!obj->get_slice_index().empty()) {
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
double layer_height = print->default_object_config().layer_height.value;
|
||||
double initial_layer_height = print->material_config().initial_layer_height.value;
|
||||
bool left_handed = obj->is_left_handed();
|
||||
@ -5824,39 +5883,81 @@ void GLCanvas3D::_render_sla_slices()
|
||||
const SliceRecord& slice_high = obj->closest_slice_to_print_level(key_high, coord_t(SCALED_EPSILON));
|
||||
|
||||
// Offset to avoid OpenGL Z fighting between the object's horizontal surfaces and the triangluated surfaces of the cuts.
|
||||
double plane_shift_z = 0.002;
|
||||
const double plane_shift_z = 0.002;
|
||||
|
||||
if (slice_low.is_valid()) {
|
||||
const ExPolygons& obj_bottom = slice_low.get_slice(soModel);
|
||||
const ExPolygons& sup_bottom = slice_low.get_slice(soSupport);
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// calculate model bottom cap
|
||||
if (!bottom_obj_triangles.is_initialized() && !obj_bottom.empty())
|
||||
init_model(bottom_obj_triangles, triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.37f, 0.0f, 1.0f });
|
||||
// calculate support bottom cap
|
||||
if (!bottom_sup_triangles.is_initialized() && !sup_bottom.empty())
|
||||
init_model(bottom_sup_triangles, triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.0f, 0.37f, 1.0f });
|
||||
#else
|
||||
// calculate model bottom cap
|
||||
if (bottom_obj_triangles.empty() && !obj_bottom.empty())
|
||||
bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, ! left_handed);
|
||||
// calculate support bottom cap
|
||||
if (bottom_sup_triangles.empty() && !sup_bottom.empty())
|
||||
bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, ! left_handed);
|
||||
bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, !left_handed);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
if (slice_high.is_valid()) {
|
||||
const ExPolygons& obj_top = slice_high.get_slice(soModel);
|
||||
const ExPolygons& sup_top = slice_high.get_slice(soSupport);
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// calculate model top cap
|
||||
if (!top_obj_triangles.is_initialized() && !obj_top.empty())
|
||||
init_model(top_obj_triangles, triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.37f, 0.0f, 1.0f });
|
||||
// calculate support top cap
|
||||
if (!top_sup_triangles.is_initialized() && !sup_top.empty())
|
||||
init_model(top_sup_triangles, triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.0f, 0.37f, 1.0f });
|
||||
#else
|
||||
// calculate model top cap
|
||||
if (top_obj_triangles.empty() && !obj_top.empty())
|
||||
top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed);
|
||||
// calculate support top cap
|
||||
if (top_sup_triangles.empty() && !sup_top.empty())
|
||||
top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
|
||||
for (const SLAPrintObject::Instance& inst : obj->instances()) {
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0.0));
|
||||
glsafe(::glRotatef(Geometry::rad2deg(inst.rotation), 0.0f, 0.0f, 1.0f));
|
||||
if (obj->is_left_handed())
|
||||
// The polygons are mirrored by X.
|
||||
glsafe(::glScalef(-1.0f, 1.0f, 1.0f));
|
||||
|
||||
bottom_obj_triangles.render();
|
||||
top_obj_triangles.render();
|
||||
bottom_sup_triangles.render();
|
||||
top_sup_triangles.render();
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
#else
|
||||
if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty()) {
|
||||
for (const SLAPrintObject::Instance& inst : obj->instances()) {
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0));
|
||||
glsafe(::glRotatef(Geometry::rad2deg(inst.rotation), 0.0, 0.0, 1.0));
|
||||
glsafe(::glTranslated(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0.0));
|
||||
glsafe(::glRotatef(Geometry::rad2deg(inst.rotation), 0.0f, 0.0f, 1.0f));
|
||||
if (obj->is_left_handed())
|
||||
// The polygons are mirrored by X.
|
||||
glsafe(::glScalef(-1.0, 1.0, 1.0));
|
||||
glsafe(::glScalef(-1.0f, 1.0f, 1.0f));
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glColor3f(1.0f, 0.37f, 0.0f));
|
||||
if (!bottom_obj_triangles.empty()) {
|
||||
@ -5880,6 +5981,7 @@ void GLCanvas3D::_render_sla_slices()
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,6 +335,16 @@ class GLCanvas3D
|
||||
|
||||
struct SlaCap
|
||||
{
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
struct Triangles
|
||||
{
|
||||
GLModel object;
|
||||
GLModel supports;
|
||||
};
|
||||
typedef std::map<unsigned int, Triangles> ObjectIdToModelsMap;
|
||||
double z;
|
||||
ObjectIdToModelsMap triangles;
|
||||
#else
|
||||
struct Triangles
|
||||
{
|
||||
Pointf3s object;
|
||||
@ -343,6 +353,7 @@ class GLCanvas3D
|
||||
typedef std::map<unsigned int, Triangles> ObjectIdToTrianglesMap;
|
||||
double z;
|
||||
ObjectIdToTrianglesMap triangles;
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
SlaCap() { reset(); }
|
||||
void reset() { z = DBL_MAX; triangles.clear(); }
|
||||
@ -473,7 +484,7 @@ private:
|
||||
std::array<ClippingPlane, 2> m_clipping_planes;
|
||||
ClippingPlane m_camera_clipping_plane;
|
||||
bool m_use_clipping_planes;
|
||||
SlaCap m_sla_caps[2];
|
||||
std::array<SlaCap, 2> m_sla_caps;
|
||||
std::string m_sidebar_field;
|
||||
// when true renders an extra frame by not resetting m_dirty to false
|
||||
// see request_extra_frame()
|
||||
@ -511,8 +522,6 @@ private:
|
||||
// I just don't want to do it now before a release (Lukas Matena 24.3.2019)
|
||||
bool m_render_sla_auxiliaries;
|
||||
|
||||
std::string m_color_by;
|
||||
|
||||
bool m_reload_delayed;
|
||||
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
@ -681,8 +690,6 @@ public:
|
||||
bool get_use_clipping_planes() const { return m_use_clipping_planes; }
|
||||
const std::array<ClippingPlane, 2> &get_clipping_planes() const { return m_clipping_planes; };
|
||||
|
||||
void set_color_by(const std::string& value);
|
||||
|
||||
void refresh_camera_scene_box();
|
||||
|
||||
BoundingBoxf3 volumes_bounding_box() const;
|
||||
@ -938,6 +945,9 @@ private:
|
||||
void _render_bed_for_picking(bool bottom);
|
||||
void _render_objects(GLVolumeCollection::ERenderType type);
|
||||
void _render_gcode();
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
void _render_gcode_cog();
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
void _render_selection();
|
||||
void _render_sequential_clearance();
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
|
@ -18,6 +18,16 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void GLModel::Geometry::reserve_vertices(size_t vertices_count)
|
||||
{
|
||||
vertices.reserve(vertices_count * vertex_stride_floats(format));
|
||||
}
|
||||
|
||||
void GLModel::Geometry::reserve_indices(size_t indices_count)
|
||||
{
|
||||
indices.reserve(indices_count * index_stride_bytes(format));
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec2f& position)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P2);
|
||||
@ -318,6 +328,11 @@ size_t GLModel::Geometry::index_stride_bytes(const Format& format)
|
||||
};
|
||||
}
|
||||
|
||||
GLModel::Geometry::EIndexType GLModel::Geometry::index_type(size_t vertices_count)
|
||||
{
|
||||
return (vertices_count < 65536) ? EIndexType::USHORT : EIndexType::UINT;
|
||||
}
|
||||
|
||||
bool GLModel::Geometry::has_position(const Format& format)
|
||||
{
|
||||
switch (format.vertex_layout)
|
||||
@ -470,8 +485,8 @@ void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bb
|
||||
|
||||
Geometry& data = m_render_data.geometry;
|
||||
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, Geometry::EIndexType::UINT };
|
||||
data.vertices.reserve(3 * its.indices.size() * Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve(3 * its.indices.size() * Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(3 * its.indices.size());
|
||||
data.reserve_indices(3 * its.indices.size());
|
||||
|
||||
// vertices + indices
|
||||
unsigned int vertices_counter = 0;
|
||||
@ -552,8 +567,8 @@ void GLModel::init_from(const Polygons& polygons, float z)
|
||||
segments_count += polygon.points.size();
|
||||
}
|
||||
|
||||
data.vertices.reserve(2 * segments_count * Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve(2 * segments_count * Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(2 * segments_count);
|
||||
data.reserve_indices(2 * segments_count);
|
||||
|
||||
// vertices + indices
|
||||
unsigned int vertices_counter = 0;
|
||||
@ -720,8 +735,8 @@ void GLModel::render() const
|
||||
|
||||
const Geometry& data = m_render_data.geometry;
|
||||
|
||||
GLenum mode = get_primitive_mode(data.format);
|
||||
GLenum index_type = get_index_type(data.format);
|
||||
const GLenum mode = get_primitive_mode(data.format);
|
||||
const GLenum index_type = get_index_type(data.format);
|
||||
|
||||
const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format);
|
||||
const bool position = Geometry::has_position(data.format);
|
||||
@ -1034,8 +1049,8 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl
|
||||
GLModel::Geometry data;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT };
|
||||
data.vertices.reserve((6 * resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve((6 * resolution * 3) * GLModel::Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(6 * resolution + 2);
|
||||
data.reserve_indices(6 * resolution * 3);
|
||||
#else
|
||||
GLModel::Geometry::Entity entity;
|
||||
entity.type = GLModel::EPrimitiveType::Triangles;
|
||||
@ -1175,6 +1190,7 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1200,8 +1216,8 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float
|
||||
GLModel::Geometry data;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT };
|
||||
data.vertices.reserve((8 * (resolution + 1) + 30) * GLModel::Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve(((8 * resolution + 16) * 3) * GLModel::Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(8 * (resolution + 1) + 30);
|
||||
data.reserve_indices((8 * resolution + 16) * 3);
|
||||
#else
|
||||
GLModel::Geometry::Entity entity;
|
||||
entity.type = GLModel::EPrimitiveType::Triangles;
|
||||
@ -1506,6 +1522,7 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1526,8 +1543,8 @@ GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_w
|
||||
GLModel::Geometry data;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT };
|
||||
data.vertices.reserve(42 * GLModel::Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve((24 * 3) * GLModel::Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(42);
|
||||
data.reserve_indices(72);
|
||||
#else
|
||||
GLModel::Geometry::Entity entity;
|
||||
entity.type = GLModel::EPrimitiveType::Triangles;
|
||||
@ -1699,6 +1716,7 @@ GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_w
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1712,8 +1730,8 @@ GLModel::Geometry diamond(unsigned short resolution)
|
||||
GLModel::Geometry data;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT };
|
||||
data.vertices.reserve((resolution + 2) * GLModel::Geometry::vertex_stride_floats(data.format));
|
||||
data.indices.reserve(((2 * (resolution + 1)) * 3) * GLModel::Geometry::index_stride_bytes(data.format));
|
||||
data.reserve_vertices(resolution + 2);
|
||||
data.reserve_indices((2 * (resolution + 1)) * 3);
|
||||
#else
|
||||
GLModel::Geometry::Entity entity;
|
||||
entity.type = GLModel::EPrimitiveType::Triangles;
|
||||
@ -1724,7 +1742,7 @@ GLModel::Geometry diamond(unsigned short resolution)
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// vertices
|
||||
for (unsigned short i = 0; i < resolution; ++i) {
|
||||
float ii = float(i) * step;
|
||||
const float ii = float(i) * step;
|
||||
const Vec3f p = { 0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f };
|
||||
append_vertex(data, p, p.normalized());
|
||||
}
|
||||
@ -1782,8 +1800,77 @@ GLModel::Geometry diamond(unsigned short resolution)
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
GLModel::Geometry smooth_sphere(unsigned short resolution, float radius)
|
||||
{
|
||||
resolution = std::max<unsigned short>(4, resolution);
|
||||
resolution = std::min<unsigned short>(256, resolution); // ensure no unsigned short overflow of indices
|
||||
|
||||
const unsigned short sectorCount = /*2 **/ resolution;
|
||||
const unsigned short stackCount = resolution;
|
||||
|
||||
const float sectorStep = float(2.0 * M_PI / sectorCount);
|
||||
const float stackStep = float(M_PI / stackCount);
|
||||
|
||||
GLModel::Geometry data;
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT };
|
||||
data.reserve_vertices((stackCount - 1) * sectorCount + 2);
|
||||
data.reserve_indices((2 * (stackCount - 1) * sectorCount) * 3);
|
||||
|
||||
// vertices
|
||||
for (unsigned short i = 0; i <= stackCount; ++i) {
|
||||
// from pi/2 to -pi/2
|
||||
const double stackAngle = 0.5 * M_PI - stackStep * i;
|
||||
const double xy = double(radius) * ::cos(stackAngle);
|
||||
const double z = double(radius) * ::sin(stackAngle);
|
||||
if (i == 0 || i == stackCount) {
|
||||
const Vec3f v(float(xy), 0.0f, float(z));
|
||||
data.add_vertex(v, (Vec3f)v.normalized());
|
||||
}
|
||||
else {
|
||||
for (unsigned short j = 0; j < sectorCount; ++j) {
|
||||
// from 0 to 2pi
|
||||
const double sectorAngle = sectorStep * j;
|
||||
const Vec3f v(float(xy * std::cos(sectorAngle)), float(xy * std::sin(sectorAngle)), float(z));
|
||||
data.add_vertex(v, (Vec3f)v.normalized());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// triangles
|
||||
for (unsigned short i = 0; i < stackCount; ++i) {
|
||||
// Beginning of current stack.
|
||||
unsigned short k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount);
|
||||
const unsigned short k1_first = k1;
|
||||
// Beginning of next stack.
|
||||
unsigned short k2 = (i == 0) ? 1 : (k1 + sectorCount);
|
||||
const unsigned short k2_first = k2;
|
||||
for (unsigned short j = 0; j < sectorCount; ++j) {
|
||||
// 2 triangles per sector excluding first and last stacks
|
||||
unsigned short k1_next = k1;
|
||||
unsigned short k2_next = k2;
|
||||
if (i != 0) {
|
||||
k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1);
|
||||
data.add_ushort_triangle(k1, k2, k1_next);
|
||||
}
|
||||
if (i + 1 != stackCount) {
|
||||
k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1);
|
||||
data.add_ushort_triangle(k1_next, k2, k2_next);
|
||||
}
|
||||
k1 = k1_next;
|
||||
k2 = k2_next;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
@ -80,11 +80,14 @@ namespace GUI {
|
||||
std::vector<unsigned char> indices;
|
||||
ColorRGBA color{ ColorRGBA::BLACK() };
|
||||
|
||||
void add_vertex(const Vec2f& position);
|
||||
void add_vertex(const Vec2f& position, const Vec2f& tex_coord);
|
||||
void add_vertex(const Vec3f& position);
|
||||
void add_vertex(const Vec3f& position, const Vec2f& tex_coord);
|
||||
void add_vertex(const Vec3f& position, const Vec3f& normal);
|
||||
void reserve_vertices(size_t vertices_count);
|
||||
void reserve_indices(size_t indices_count);
|
||||
|
||||
void add_vertex(const Vec2f& position); // EVertexLayout::P2
|
||||
void add_vertex(const Vec2f& position, const Vec2f& tex_coord); // EVertexLayout::P2T2
|
||||
void add_vertex(const Vec3f& position); // EVertexLayout::P3
|
||||
void add_vertex(const Vec3f& position, const Vec2f& tex_coord); // EVertexLayout::P3T2
|
||||
void add_vertex(const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3
|
||||
|
||||
void add_ushort_index(unsigned short id);
|
||||
void add_uint_index(unsigned int id);
|
||||
@ -103,6 +106,8 @@ namespace GUI {
|
||||
unsigned int extract_uint_index(size_t id) const;
|
||||
unsigned short extract_ushort_index(size_t id) const;
|
||||
|
||||
bool is_empty() const { return vertices.empty() || indices.empty(); }
|
||||
|
||||
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
|
||||
size_t indices_count() const { return indices.size() / index_stride_bytes(format); }
|
||||
|
||||
@ -130,6 +135,8 @@ namespace GUI {
|
||||
|
||||
static size_t index_stride_bytes(const Format& format);
|
||||
|
||||
static EIndexType index_type(size_t vertices_count);
|
||||
|
||||
static bool has_position(const Format& format);
|
||||
static bool has_normal(const Format& format);
|
||||
static bool has_tex_coord(const Format& format);
|
||||
@ -256,6 +263,14 @@ namespace GUI {
|
||||
// the diamond is contained into a box with size [1, 1, 1]
|
||||
GLModel::Geometry diamond(unsigned short resolution);
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
// create a sphere with the given resolution and smooth normals
|
||||
// the origin of the sphere is in its center
|
||||
GLModel::Geometry smooth_sphere(unsigned short resolution, float radius);
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -126,8 +126,8 @@ namespace GUI {
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(4 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(4);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec2f(left, bottom));
|
||||
|
@ -41,6 +41,10 @@ std::pair<bool, std::string> GLShadersManager::init()
|
||||
// used to render 3D scene background
|
||||
valid &= append_shader("background", { "background.vs", "background.fs" });
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
// used to render toolpaths center of gravity
|
||||
valid &= append_shader("toolpaths_cog", { "toolpaths_cog.vs", "toolpaths_cog.fs" });
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
|
||||
valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" });
|
||||
// used to render printbed
|
||||
|
@ -342,8 +342,8 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec2f(left, bottom), Vec2f(uvs.left_bottom.u, uvs.left_bottom.v));
|
||||
|
@ -496,7 +496,7 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
|
||||
|
||||
/* FT_TEX */ { "Texture"sv, { ".png"sv, ".svg"sv } },
|
||||
|
||||
/* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv } },
|
||||
/* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv, ".pwmx"sv } },
|
||||
};
|
||||
|
||||
// This function produces a Win32 file dialog file template mask to be consumed by wxWidgets on all platforms.
|
||||
|
@ -126,6 +126,9 @@ public:
|
||||
ColorChanges,
|
||||
PausePrints,
|
||||
CustomGCodes,
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
CenterOfGravity,
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
Shells,
|
||||
ToolMarker,
|
||||
#if !ENABLE_PREVIEW_LAYOUT
|
||||
|
@ -115,8 +115,8 @@ void GLGizmoCut::on_render()
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(min_x, min_y, plane_center.z()));
|
||||
@ -160,8 +160,8 @@ void GLGizmoCut::on_render()
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = ColorRGBA::YELLOW();
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex((Vec3f)plane_center.cast<float>());
|
||||
|
@ -1,6 +1,9 @@
|
||||
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
|
||||
#include "GLGizmoFlatten.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
||||
|
||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||
@ -63,6 +66,14 @@ void GLGizmoFlatten::on_render()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
@ -76,21 +87,38 @@ void GLGizmoFlatten::on_render()
|
||||
if (this->is_plane_update_necessary())
|
||||
update_planes();
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
m_planes[i].vbo.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR);
|
||||
m_planes[i].vbo.render();
|
||||
#else
|
||||
glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data()));
|
||||
if (m_planes[i].vbo.has_VBOs())
|
||||
m_planes[i].vbo.render();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
shader->stop_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
void GLGizmoFlatten::on_render_for_picking()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
@ -102,13 +130,21 @@ void GLGizmoFlatten::on_render_for_picking()
|
||||
if (this->is_plane_update_necessary())
|
||||
update_planes();
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
m_planes[i].vbo.set_color(picking_color_component(i));
|
||||
#else
|
||||
glsafe(::glColor4fv(picking_color_component(i).data()));
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
m_planes[i].vbo.render();
|
||||
}
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
shader->stop_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
|
||||
@ -324,12 +360,28 @@ void GLGizmoFlatten::update_planes()
|
||||
// And finally create respective VBOs. The polygon is convex with
|
||||
// the vertices in order, so triangulation is trivial.
|
||||
for (auto& plane : m_planes) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(plane.vertices.size()) };
|
||||
init_data.reserve_vertices(plane.vertices.size());
|
||||
init_data.reserve_indices(plane.vertices.size());
|
||||
// vertices + indices
|
||||
for (size_t i = 0; i < plane.vertices.size(); ++i) {
|
||||
init_data.add_vertex((Vec3f)plane.vertices[i].cast<float>(), (Vec3f)plane.normal.cast<float>());
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_index((unsigned short)i);
|
||||
else
|
||||
init_data.add_uint_index((unsigned int)i);
|
||||
}
|
||||
plane.vbo.init_from(std::move(init_data));
|
||||
#else
|
||||
plane.vbo.reserve(plane.vertices.size());
|
||||
for (const auto& vert : plane.vertices)
|
||||
plane.vbo.push_geometry(vert, plane.normal);
|
||||
for (size_t i=1; i<plane.vertices.size()-1; ++i)
|
||||
plane.vbo.push_triangle(0, i, i+1); // triangle fan
|
||||
plane.vbo.finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
// FIXME: vertices should really be local, they need not
|
||||
// persist now when we use VBOs
|
||||
plane.vertices.clear();
|
||||
|
@ -2,7 +2,11 @@
|
||||
#define slic3r_GLGizmoFlatten_hpp_
|
||||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#else
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
@ -22,7 +26,11 @@ private:
|
||||
|
||||
struct PlaneData {
|
||||
std::vector<Vec3d> vertices; // should be in fact local in update_planes()
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel vbo;
|
||||
#else
|
||||
GLIndexedVertexArray vbo;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
Vec3d normal;
|
||||
float area;
|
||||
};
|
||||
|
@ -589,6 +589,9 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
|
||||
m_gizmo_scene.render(color_idx);
|
||||
}
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
render_paint_contour();
|
||||
#else
|
||||
if (m_paint_contour.has_VBO()) {
|
||||
ScopeGuard guard_mm_gouraud([shader]() { shader->start_using(); });
|
||||
shader->stop_using();
|
||||
@ -602,6 +605,7 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
|
||||
|
||||
contour_shader->stop_using();
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
m_update_render_data = false;
|
||||
}
|
||||
@ -636,6 +640,9 @@ void TriangleSelectorMmGui::update_render_data()
|
||||
|
||||
m_gizmo_scene.finalize_triangle_indices();
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
update_paint_contour();
|
||||
#else
|
||||
m_paint_contour.release_geometry();
|
||||
std::vector<Vec2i> contour_edges = this->get_seed_fill_contour();
|
||||
m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6);
|
||||
@ -654,6 +661,7 @@ void TriangleSelectorMmGui::update_render_data()
|
||||
m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size();
|
||||
|
||||
m_paint_contour.finalize_geometry();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const
|
||||
|
@ -184,8 +184,8 @@ void GLGizmoMove3D::on_render()
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = AXES_COLOR[id];
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
@ -18,7 +18,11 @@
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
std::shared_ptr<GLIndexedVertexArray> GLGizmoPainterBase::s_sphere = nullptr;
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
std::shared_ptr<GLModel> GLGizmoPainterBase::s_sphere = nullptr;
|
||||
#else
|
||||
std::shared_ptr<GLIndexedVertexArray> GLGizmoPainterBase::s_sphere = nullptr;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
@ -27,8 +31,13 @@ GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& ic
|
||||
|
||||
GLGizmoPainterBase::~GLGizmoPainterBase()
|
||||
{
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
if (s_sphere != nullptr)
|
||||
s_sphere.reset();
|
||||
#else
|
||||
if (s_sphere != nullptr && s_sphere->has_VBOs())
|
||||
s_sphere->release_geometry();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection)
|
||||
@ -185,8 +194,8 @@ void GLGizmoPainterBase::render_cursor_circle()
|
||||
static const float StepSize = 2.0f * float(PI) / float(StepsCount);
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f };
|
||||
init_data.vertices.reserve(StepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(StepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(StepsCount);
|
||||
init_data.reserve_indices(StepsCount);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i < StepsCount; ++i) {
|
||||
@ -220,18 +229,27 @@ void GLGizmoPainterBase::render_cursor_circle()
|
||||
void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
||||
{
|
||||
if (s_sphere == nullptr) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
s_sphere = std::make_shared<GLModel>();
|
||||
s_sphere->init_from(its_make_sphere(1.0, double(PI) / 12.0));
|
||||
#else
|
||||
s_sphere = std::make_shared<GLIndexedVertexArray>();
|
||||
s_sphere->load_its_flat_shading(its_make_sphere(1.0, double(PI) / 12.0));
|
||||
s_sphere->finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
|
||||
const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed();
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixd(trafo.data()));
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glTranslatef(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2)));
|
||||
glsafe(::glTranslatef(m_rr.hit.x(), m_rr.hit.y(), m_rr.hit.z()));
|
||||
glsafe(::glMultMatrixd(complete_scaling_matrix_inverse.data()));
|
||||
glsafe(::glScaled(m_cursor_radius, m_cursor_radius, m_cursor_radius));
|
||||
|
||||
@ -243,11 +261,22 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
||||
render_color = this->get_cursor_sphere_left_button_color();
|
||||
else if (m_button_down == Button::Right)
|
||||
render_color = this->get_cursor_sphere_right_button_color();
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
shader->start_using();
|
||||
|
||||
assert(s_sphere != nullptr);
|
||||
s_sphere->set_color(render_color);
|
||||
#else
|
||||
glsafe(::glColor4fv(render_color.data()));
|
||||
|
||||
assert(s_sphere != nullptr);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
s_sphere->render();
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
shader->stop_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
if (is_left_handed)
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
@ -763,13 +792,28 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||
shader->set_uniform("offset_depth_buffer", true);
|
||||
for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color),
|
||||
std::make_pair(&m_iva_blockers, blockers_color)}) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
iva.first->set_color(iva.second);
|
||||
iva.first->render();
|
||||
#else
|
||||
if (iva.first->has_VBOs()) {
|
||||
shader->set_uniform("uniform_color", iva.second);
|
||||
iva.first->render();
|
||||
}
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
for (auto &iva : m_iva_seed_fills)
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
for (auto& iva : m_iva_seed_fills) {
|
||||
size_t color_idx = &iva - &m_iva_seed_fills.front();
|
||||
const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color :
|
||||
color_idx == 2 ? blockers_color :
|
||||
GLVolume::NEUTRAL_COLOR);
|
||||
iva.set_color(color);
|
||||
iva.render();
|
||||
}
|
||||
#else
|
||||
for (auto& iva : m_iva_seed_fills)
|
||||
if (iva.has_VBOs()) {
|
||||
size_t color_idx = &iva - &m_iva_seed_fills.front();
|
||||
const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color :
|
||||
@ -778,7 +822,11 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||
shader->set_uniform("uniform_color", color);
|
||||
iva.render();
|
||||
}
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
render_paint_contour();
|
||||
#else
|
||||
if (m_paint_contour.has_VBO()) {
|
||||
ScopeGuard guard_gouraud([shader]() { shader->start_using(); });
|
||||
shader->stop_using();
|
||||
@ -792,13 +840,14 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||
|
||||
contour_shader->stop_using();
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
if (imgui)
|
||||
render_debug(imgui);
|
||||
else
|
||||
assert(false); // If you want debug output, pass ptr to ImGuiWrapper.
|
||||
#endif
|
||||
#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
}
|
||||
|
||||
void TriangleSelectorGUI::update_render_data()
|
||||
@ -807,20 +856,44 @@ void TriangleSelectorGUI::update_render_data()
|
||||
int blc_cnt = 0;
|
||||
std::vector<int> seed_fill_cnt(m_iva_seed_fills.size(), 0);
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
for (auto* iva : { &m_iva_enforcers, &m_iva_blockers }) {
|
||||
iva->reset();
|
||||
}
|
||||
|
||||
for (auto& iva : m_iva_seed_fills) {
|
||||
iva.reset();
|
||||
}
|
||||
|
||||
GLModel::Geometry iva_enforcers_data;
|
||||
iva_enforcers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||
GLModel::Geometry iva_blockers_data;
|
||||
iva_blockers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||
std::array<GLModel::Geometry, 3> iva_seed_fills_data;
|
||||
for (auto& data : iva_seed_fills_data)
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||
#else
|
||||
for (auto *iva : {&m_iva_enforcers, &m_iva_blockers})
|
||||
iva->release_geometry();
|
||||
|
||||
for (auto &iva : m_iva_seed_fills)
|
||||
iva.release_geometry();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
for (const Triangle &tr : m_triangles) {
|
||||
if (!tr.valid() || tr.is_split() || (tr.get_state() == EnforcerBlockerType::NONE && !tr.is_selected_by_seed_fill()))
|
||||
continue;
|
||||
|
||||
int tr_state = int(tr.get_state());
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel::Geometry &iva = tr.is_selected_by_seed_fill() ? iva_seed_fills_data[tr_state] :
|
||||
tr.get_state() == EnforcerBlockerType::ENFORCER ? iva_enforcers_data :
|
||||
iva_blockers_data;
|
||||
#else
|
||||
GLIndexedVertexArray &iva = tr.is_selected_by_seed_fill() ? m_iva_seed_fills[tr_state] :
|
||||
tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers :
|
||||
m_iva_blockers;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] :
|
||||
tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt :
|
||||
blc_cnt;
|
||||
@ -830,19 +903,40 @@ void TriangleSelectorGUI::update_render_data()
|
||||
//FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort
|
||||
// or the current implementation may be more cache friendly.
|
||||
const Vec3f n = (v1 - v0).cross(v2 - v1).normalized();
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
iva.add_vertex(v0, n);
|
||||
iva.add_vertex(v1, n);
|
||||
iva.add_vertex(v2, n);
|
||||
iva.add_uint_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2);
|
||||
#else
|
||||
iva.push_geometry(v0, n);
|
||||
iva.push_geometry(v1, n);
|
||||
iva.push_geometry(v2, n);
|
||||
iva.push_triangle(cnt, cnt + 1, cnt + 2);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
cnt += 3;
|
||||
}
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
if (!iva_enforcers_data.is_empty())
|
||||
m_iva_enforcers.init_from(std::move(iva_enforcers_data));
|
||||
if (!iva_blockers_data.is_empty())
|
||||
m_iva_blockers.init_from(std::move(iva_blockers_data));
|
||||
for (size_t i = 0; i < m_iva_seed_fills.size(); ++i) {
|
||||
if (!iva_seed_fills_data[i].is_empty())
|
||||
m_iva_seed_fills[i].init_from(std::move(iva_seed_fills_data[i]));
|
||||
}
|
||||
#else
|
||||
for (auto *iva : {&m_iva_enforcers, &m_iva_blockers})
|
||||
iva->finalize_geometry(true);
|
||||
|
||||
for (auto &iva : m_iva_seed_fills)
|
||||
iva.finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
update_paint_contour();
|
||||
#else
|
||||
m_paint_contour.release_geometry();
|
||||
std::vector<Vec2i> contour_edges = this->get_seed_fill_contour();
|
||||
m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6);
|
||||
@ -861,8 +955,10 @@ void TriangleSelectorGUI::update_render_data()
|
||||
m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size();
|
||||
|
||||
m_paint_contour.finalize_geometry();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void GLPaintContour::render() const
|
||||
{
|
||||
assert(this->m_contour_VBO_id != 0);
|
||||
@ -920,6 +1016,7 @@ void GLPaintContour::release_geometry()
|
||||
}
|
||||
this->clear();
|
||||
}
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
|
||||
@ -956,45 +1053,111 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
|
||||
INVALID
|
||||
};
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
for (auto& va : m_varrays)
|
||||
va.reset();
|
||||
#else
|
||||
for (auto& va : m_varrays)
|
||||
va.release_geometry();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
std::array<int, 3> cnts;
|
||||
|
||||
::glScalef(1.01f, 1.01f, 1.01f);
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
std::array<GLModel::Geometry, 3> varrays_data;
|
||||
for (auto& data : varrays_data)
|
||||
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
for (int tr_id=0; tr_id<int(m_triangles.size()); ++tr_id) {
|
||||
const Triangle& tr = m_triangles[tr_id];
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel::Geometry* va = nullptr;
|
||||
#else
|
||||
GLIndexedVertexArray* va = nullptr;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
int* cnt = nullptr;
|
||||
if (tr_id < m_orig_size_indices) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
va = &varrays_data[ORIGINAL];
|
||||
#else
|
||||
va = &m_varrays[ORIGINAL];
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
cnt = &cnts[ORIGINAL];
|
||||
}
|
||||
else if (tr.valid()) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
va = &varrays_data[SPLIT];
|
||||
#else
|
||||
va = &m_varrays[SPLIT];
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
cnt = &cnts[SPLIT];
|
||||
}
|
||||
else {
|
||||
if (! m_show_invalid)
|
||||
continue;
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
va = &varrays_data[INVALID];
|
||||
#else
|
||||
va = &m_varrays[INVALID];
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
cnt = &cnts[INVALID];
|
||||
}
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
va->add_vertex(m_vertices[tr.verts_idxs[i]].v, Vec3f(0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
va->add_uint_triangle((unsigned int)*cnt, (unsigned int)*cnt + 1, (unsigned int)*cnt + 2);
|
||||
#else
|
||||
for (int i = 0; i < 3; ++i)
|
||||
va->push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
|
||||
double(m_vertices[tr.verts_idxs[i]].v[1]),
|
||||
double(m_vertices[tr.verts_idxs[i]].v[2]),
|
||||
0., 0., 1.);
|
||||
va->push_triangle(*cnt,
|
||||
*cnt+1,
|
||||
*cnt+2);
|
||||
*cnt + 1,
|
||||
*cnt + 2);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
*cnt += 3;
|
||||
}
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (!varrays_data[i].is_empty())
|
||||
m_varrays[i].init_from(std::move(varrays_data[i]));
|
||||
}
|
||||
#else
|
||||
for (auto* iva : { &m_iva_enforcers, &m_iva_blockers })
|
||||
iva->finalize_geometry(true);
|
||||
|
||||
for (auto& iva : m_iva_seed_fills)
|
||||
iva.finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->stop_using();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||
for (vtype i : {ORIGINAL, SPLIT, INVALID}) {
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel& va = m_varrays[i];
|
||||
switch (i) {
|
||||
case ORIGINAL: va.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); break;
|
||||
case SPLIT: va.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); break;
|
||||
case INVALID: va.set_color({ 1.0f, 1.0f, 0.0f, 1.0f }); break;
|
||||
}
|
||||
va.render();
|
||||
#else
|
||||
GLIndexedVertexArray& va = m_varrays[i];
|
||||
va.finalize_geometry(true);
|
||||
if (va.has_VBOs()) {
|
||||
@ -1005,11 +1168,66 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
|
||||
}
|
||||
va.render();
|
||||
}
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->start_using();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
#endif
|
||||
#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void TriangleSelectorGUI::update_paint_contour()
|
||||
{
|
||||
m_paint_contour.reset();
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
const std::vector<Vec2i> contour_edges = this->get_seed_fill_contour();
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(2 * contour_edges.size()) };
|
||||
init_data.reserve_vertices(2 * contour_edges.size());
|
||||
init_data.reserve_indices(2 * contour_edges.size());
|
||||
// vertices + indices
|
||||
unsigned int vertices_count = 0;
|
||||
for (const Vec2i& edge : contour_edges) {
|
||||
init_data.add_vertex(m_vertices[edge(0)].v);
|
||||
init_data.add_vertex(m_vertices[edge(1)].v);
|
||||
vertices_count += 2;
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_line((unsigned short)vertices_count - 2, (unsigned short)vertices_count - 1);
|
||||
else
|
||||
init_data.add_uint_line(vertices_count - 2, vertices_count - 1);
|
||||
}
|
||||
|
||||
if (!init_data.is_empty())
|
||||
m_paint_contour.init_from(std::move(init_data));
|
||||
}
|
||||
|
||||
void TriangleSelectorGUI::render_paint_contour()
|
||||
{
|
||||
auto* curr_shader = wxGetApp().get_current_shader();
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->stop_using();
|
||||
|
||||
auto* contour_shader = wxGetApp().get_shader("mm_contour");
|
||||
if (contour_shader != nullptr) {
|
||||
contour_shader->start_using();
|
||||
|
||||
glsafe(::glDepthFunc(GL_LEQUAL));
|
||||
m_paint_contour.render();
|
||||
glsafe(::glDepthFunc(GL_LESS));
|
||||
|
||||
contour_shader->stop_using();
|
||||
}
|
||||
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->start_using();
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
@ -3,7 +3,11 @@
|
||||
|
||||
#include "GLGizmoBase.hpp"
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#else
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#include "libslic3r/ObjectID.hpp"
|
||||
#include "libslic3r/TriangleSelector.hpp"
|
||||
@ -28,6 +32,7 @@ enum class PainterGizmoType {
|
||||
MMU_SEGMENTATION
|
||||
};
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
class GLPaintContour
|
||||
{
|
||||
public:
|
||||
@ -63,6 +68,7 @@ public:
|
||||
GLuint m_contour_VBO_id{0};
|
||||
GLuint m_contour_EBO_id{0};
|
||||
};
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
class TriangleSelectorGUI : public TriangleSelector {
|
||||
public:
|
||||
@ -75,13 +81,13 @@ public:
|
||||
virtual void render(ImGuiWrapper *imgui);
|
||||
void render() { this->render(nullptr); }
|
||||
|
||||
void request_update_render_data() { m_update_render_data = true; };
|
||||
void request_update_render_data() { m_update_render_data = true; }
|
||||
|
||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
void render_debug(ImGuiWrapper* imgui);
|
||||
bool m_show_triangles{false};
|
||||
bool m_show_invalid{false};
|
||||
#endif
|
||||
#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
|
||||
protected:
|
||||
bool m_update_render_data = false;
|
||||
@ -91,13 +97,29 @@ protected:
|
||||
private:
|
||||
void update_render_data();
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel m_iva_enforcers;
|
||||
GLModel m_iva_blockers;
|
||||
std::array<GLModel, 3> m_iva_seed_fills;
|
||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
std::array<GLModel, 3> m_varrays;
|
||||
#endif // PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
#else
|
||||
GLIndexedVertexArray m_iva_enforcers;
|
||||
GLIndexedVertexArray m_iva_blockers;
|
||||
std::array<GLIndexedVertexArray, 3> m_iva_seed_fills;
|
||||
std::array<GLIndexedVertexArray, 3> m_varrays;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
protected:
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel m_paint_contour;
|
||||
|
||||
void update_paint_contour();
|
||||
void render_paint_contour();
|
||||
#else
|
||||
GLPaintContour m_paint_contour;
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
};
|
||||
|
||||
|
||||
@ -209,7 +231,11 @@ private:
|
||||
const Camera& camera,
|
||||
const std::vector<Transform3d>& trafo_matrices) const;
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
static std::shared_ptr<GLModel> s_sphere;
|
||||
#else
|
||||
static std::shared_ptr<GLIndexedVertexArray> s_sphere;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
bool m_internal_stack_active = false;
|
||||
bool m_schedule_update = false;
|
||||
|
@ -314,8 +314,8 @@ void GLGizmoRotate::render_circle() const
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(ScaleStepsCount);
|
||||
init_data.reserve_indices(ScaleStepsCount);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
|
||||
@ -357,8 +357,8 @@ void GLGizmoRotate::render_scale() const
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2 * ScaleStepsCount);
|
||||
init_data.reserve_indices(2 * ScaleStepsCount);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
|
||||
@ -416,8 +416,8 @@ void GLGizmoRotate::render_snap_radii() const
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2 * ScaleStepsCount);
|
||||
init_data.reserve_indices(2 * ScaleStepsCount);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
|
||||
@ -467,8 +467,8 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f));
|
||||
@ -508,8 +508,8 @@ void GLGizmoRotate::render_angle() const
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve((1 + AngleResolution) * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve((1 + AngleResolution) * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(1 + AngleResolution);
|
||||
init_data.reserve_indices(1 + AngleResolution);
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i <= AngleResolution; ++i) {
|
||||
@ -545,8 +545,8 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f));
|
||||
|
@ -531,8 +531,8 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast<float>());
|
||||
|
@ -127,6 +127,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
if (! has_points && ! has_holes)
|
||||
return;
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
ScopeGuard guard([shader]() { shader->stop_using(); });
|
||||
#else
|
||||
GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light");
|
||||
if (shader != nullptr)
|
||||
shader->start_using();
|
||||
@ -134,6 +142,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
if (shader != nullptr)
|
||||
shader->stop_using();
|
||||
});
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
|
||||
@ -177,11 +186,12 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_cone.set_color(render_color);
|
||||
m_sphere.set_color(render_color);
|
||||
if (!picking)
|
||||
#else
|
||||
m_cone.set_color(-1, render_color);
|
||||
m_sphere.set_color(-1, render_color);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
if (shader && !picking)
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
shader->set_uniform("emission_factor", 0.5f);
|
||||
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
@ -236,9 +246,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
m_cylinder.set_color(render_color);
|
||||
#else
|
||||
m_cylinder.set_color(-1, render_color);
|
||||
if (shader != nu)
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
if (shader)
|
||||
shader->set_uniform("emission_factor", 0.5f);
|
||||
shader->set_uniform("emission_factor", 0.5f);
|
||||
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
|
||||
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
|
||||
continue;
|
||||
|
@ -213,15 +213,21 @@ void InstancesHider::render_cut() const
|
||||
clipper->set_limiting_plane(ClippingPlane::ClipsNothing());
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
#if !ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
if (mv->is_model_part())
|
||||
glsafe(::glColor3f(0.8f, 0.3f, 0.0f));
|
||||
else {
|
||||
const ColorRGBA color = color_from_model_volume(*mv);
|
||||
glsafe(::glColor4fv(color.data()));
|
||||
}
|
||||
#endif // !ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
glsafe(::glPushAttrib(GL_DEPTH_TEST));
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
clipper->render_cut(mv->is_model_part() ? ColorRGBA(0.8f, 0.3f, 0.0f, 1.0f) : color_from_model_volume(*mv));
|
||||
#else
|
||||
clipper->render_cut();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
glsafe(::glPopAttrib());
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
@ -417,8 +423,12 @@ void ObjectClipper::render_cut() const
|
||||
clipper->set_transformation(trafo);
|
||||
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
|
||||
glsafe(::glPushMatrix());
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
clipper->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f });
|
||||
#else
|
||||
glsafe(::glColor3f(1.0f, 0.37f, 0.0f));
|
||||
clipper->render_cut();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
++clipper_id;
|
||||
@ -530,8 +540,12 @@ void SupportsClipper::render_cut() const
|
||||
m_clipper->set_transformation(supports_trafo);
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
m_clipper->render_cut({ 1.0f, 0.f, 0.37f, 1.0f });
|
||||
#else
|
||||
glsafe(::glColor3f(1.0f, 0.f, 0.37f));
|
||||
m_clipper->render_cut();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,9 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
||||
{ImGui::LegendColorChanges , "legend_colorchanges" },
|
||||
{ImGui::LegendPausePrints , "legend_pauseprints" },
|
||||
{ImGui::LegendCustomGCodes , "legend_customgcodes" },
|
||||
#if ENABLE_SHOW_TOOLPATHS_COG
|
||||
{ImGui::LegendCOG , "legend_cog" },
|
||||
#endif // ENABLE_SHOW_TOOLPATHS_COG
|
||||
{ImGui::LegendShells , "legend_shells" },
|
||||
{ImGui::LegendToolMarker , "legend_toolmarker" },
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
|
@ -6,6 +6,9 @@
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
@ -66,13 +69,34 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo)
|
||||
|
||||
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
void MeshClipper::render_cut(const ColorRGBA& color)
|
||||
#else
|
||||
void MeshClipper::render_cut()
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
{
|
||||
if (! m_triangles_valid)
|
||||
recalculate_triangles();
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->stop_using();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
m_model.set_color(color);
|
||||
m_model.render();
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
if (curr_shader != nullptr)
|
||||
curr_shader->start_using();
|
||||
#else
|
||||
if (m_vertex_array.has_VBOs())
|
||||
m_vertex_array.render();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
}
|
||||
|
||||
|
||||
@ -161,6 +185,29 @@ void MeshClipper::recalculate_triangles()
|
||||
|
||||
tr.pretranslate(0.001 * m_plane.get_normal().normalized()); // to avoid z-fighting
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
m_model.reset();
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(m_triangles2d.size()) };
|
||||
init_data.reserve_vertices(m_triangles2d.size());
|
||||
init_data.reserve_indices(m_triangles2d.size());
|
||||
|
||||
// vertices + indices
|
||||
for (auto it = m_triangles2d.cbegin(); it != m_triangles2d.cend(); it = it + 3) {
|
||||
init_data.add_vertex((Vec3f)(tr * Vec3d((*(it + 0)).x(), (*(it + 0)).y(), height_mesh)).cast<float>(), (Vec3f)up.cast<float>());
|
||||
init_data.add_vertex((Vec3f)(tr * Vec3d((*(it + 1)).x(), (*(it + 1)).y(), height_mesh)).cast<float>(), (Vec3f)up.cast<float>());
|
||||
init_data.add_vertex((Vec3f)(tr * Vec3d((*(it + 2)).x(), (*(it + 2)).y(), height_mesh)).cast<float>(), (Vec3f)up.cast<float>());
|
||||
const size_t idx = it - m_triangles2d.cbegin();
|
||||
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_triangle((unsigned short)idx, (unsigned short)idx + 1, (unsigned short)idx + 2);
|
||||
else
|
||||
init_data.add_uint_triangle((unsigned int)idx, (unsigned int)idx + 1, (unsigned int)idx + 2);
|
||||
}
|
||||
|
||||
if (!init_data.is_empty())
|
||||
m_model.init_from(std::move(init_data));
|
||||
#else
|
||||
m_vertex_array.release_geometry();
|
||||
for (auto it=m_triangles2d.cbegin(); it != m_triangles2d.cend(); it=it+3) {
|
||||
m_vertex_array.push_geometry(tr * Vec3d((*(it+0))(0), (*(it+0))(1), height_mesh), up);
|
||||
@ -170,6 +217,7 @@ void MeshClipper::recalculate_triangles()
|
||||
m_vertex_array.push_triangle(idx, idx+1, idx+2);
|
||||
}
|
||||
m_vertex_array.finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
m_triangles_valid = true;
|
||||
}
|
||||
|
@ -3,10 +3,15 @@
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/SLA/IndexedMesh.hpp"
|
||||
#include "admesh/stl.h"
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#else
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
@ -69,7 +74,8 @@ public:
|
||||
|
||||
|
||||
// MeshClipper class cuts a mesh and is able to return a triangulated cut.
|
||||
class MeshClipper {
|
||||
class MeshClipper
|
||||
{
|
||||
public:
|
||||
// Inform MeshClipper about which plane we want to use to cut the mesh
|
||||
// This is supposed to be in world coordinates.
|
||||
@ -92,7 +98,11 @@ public:
|
||||
|
||||
// Render the triangulated cut. Transformation matrices should
|
||||
// be set in world coords.
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
void render_cut(const ColorRGBA& color);
|
||||
#else
|
||||
void render_cut();
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
private:
|
||||
void recalculate_triangles();
|
||||
@ -103,7 +113,11 @@ private:
|
||||
ClippingPlane m_plane;
|
||||
ClippingPlane m_limiting_plane = ClippingPlane::ClipsNothing();
|
||||
std::vector<Vec2f> m_triangles2d;
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
GLModel m_model;
|
||||
#else
|
||||
GLIndexedVertexArray m_vertex_array;
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
bool m_triangles_valid = false;
|
||||
};
|
||||
|
||||
|
@ -1429,10 +1429,10 @@ void Selection::render(float scale_factor)
|
||||
return;
|
||||
|
||||
m_scale_factor = scale_factor;
|
||||
// render cumulative bounding box of selected volumes
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
render_bounding_box(get_bounding_box(), ColorRGB::WHITE());
|
||||
#else
|
||||
// render cumulative bounding box of selected volumes
|
||||
render_selected_volumes();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
render_synchronized_volumes();
|
||||
@ -1444,6 +1444,14 @@ void Selection::render_center(bool gizmo_is_dragging)
|
||||
if (!m_valid || is_empty())
|
||||
return;
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
const Vec3d center = gizmo_is_dragging ? m_cache.dragging_center : get_bounding_box().center();
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
@ -1452,19 +1460,17 @@ void Selection::render_center(bool gizmo_is_dragging)
|
||||
glsafe(::glTranslated(center.x(), center.y(), center.z()));
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_vbo_sphere.set_color(ColorRGBA::WHITE());
|
||||
#else
|
||||
m_vbo_sphere.set_color(-1, ColorRGBA::WHITE());
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_vbo_sphere.render();
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
shader->stop_using();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
|
||||
@ -2086,8 +2092,8 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(48 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(48 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(48);
|
||||
init_data.reserve_indices(48);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z()));
|
||||
@ -2395,8 +2401,8 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(p1.x(), p1.y(), z1));
|
||||
@ -2417,8 +2423,8 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.vertices.reserve(4 * GLModel::Geometry::vertex_stride_floats(init_data.format));
|
||||
init_data.indices.reserve(6 * GLModel::Geometry::index_stride_bytes(init_data.format));
|
||||
init_data.reserve_vertices(4);
|
||||
init_data.reserve_indices(6);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex(Vec3f(p1.x(), p1.y(), z2));
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include <libslic3r/ObjectID.hpp>
|
||||
#include <libslic3r/Utils.hpp>
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -210,15 +210,24 @@ else ()
|
||||
endif ()
|
||||
|
||||
set(PERL_ENV_VARS "")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_CROSSCOMPILING AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
if (SLIC3R_ASAN OR SLIC3R_UBSAN)
|
||||
set(PERL_ENV_VARS env)
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_ASAN)
|
||||
# Find the location of libasan.so for passing it into LD_PRELOAD. It works with GCC and Clang on Linux.
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libasan.so OUTPUT_VARIABLE LIBASAN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(PERL_ENV_VARS ${PERL_ENV_VARS} "LD_PRELOAD=${LIBASAN_PATH}")
|
||||
# On Centos 7 calling "gcc -print-file-name=libasan.so" returns path to "ld script" instead of path to shared library.
|
||||
set(_asan_compiled_bin ${CMAKE_CURRENT_BINARY_DIR}/detect_libasan)
|
||||
set(_asan_source_file ${_asan_compiled_bin}.c)
|
||||
# Compile and link simple C application with enabled address sanitizer.
|
||||
file(WRITE ${_asan_source_file} "int main(){}")
|
||||
include(GetPrerequisites)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} ${_asan_source_file} -fsanitize=address -lasan -o ${_asan_compiled_bin})
|
||||
# Extract from the compiled application absolute path of libasan.
|
||||
get_prerequisites(${_asan_compiled_bin} _asan_shared_libraries_list 0 0 "" "")
|
||||
list(FILTER _asan_shared_libraries_list INCLUDE REGEX libasan)
|
||||
set(PERL_ENV_VARS ${PERL_ENV_VARS} "LD_PRELOAD=${_asan_shared_libraries_list}")
|
||||
|
||||
# Suppressed memory leak reports that come from Perl.
|
||||
set(PERL_LEAK_SUPPRESSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/leak_suppression.txt)
|
||||
|
Loading…
x
Reference in New Issue
Block a user