Fixed conflicts after merge with master

This commit is contained in:
enricoturri1966 2022-02-14 09:20:37 +01:00
commit 6a7e32ad3e
50 changed files with 1954 additions and 221 deletions

View File

@ -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

View 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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View 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);
}

View 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();
}

View File

@ -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);
}

View File

@ -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

View 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

View 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_

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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);
};

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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).

View File

@ -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());

View File

@ -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);

View File

@ -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;

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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));

View File

@ -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.

View File

@ -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

View File

@ -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>());

View File

@ -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();

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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>());

View File

@ -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;

View File

@ -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());
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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));

View File

@ -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

View File

@ -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)