mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-18 04:08:02 -06:00
Merge branch 'SoftFever:main' into main
This commit is contained in:
commit
a3d08e010d
16 changed files with 1604 additions and 1172 deletions
|
@ -80,7 +80,7 @@ fi
|
||||||
|
|
||||||
DISTRIBUTION=$(awk -F= '/^ID=/ {print $2}' /etc/os-release)
|
DISTRIBUTION=$(awk -F= '/^ID=/ {print $2}' /etc/os-release)
|
||||||
# treat ubuntu as debian
|
# treat ubuntu as debian
|
||||||
if [ "${DISTRIBUTION}" == "ubuntu" ]
|
if [ "${DISTRIBUTION}" == "ubuntu" ] || [ "${DISTRIBUTION}" == "linuxmint" ]
|
||||||
then
|
then
|
||||||
DISTRIBUTION="debian"
|
DISTRIBUTION="debian"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -119,11 +119,6 @@ Thank you! :)
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://peopoly.net/">
|
|
||||||
<img src="SoftFever_doc\sponsor_logos\peopoly-standard-logo.png" alt="Peopoly" width="96" height="">
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://qidi3d.com/">
|
<a href="https://qidi3d.com/">
|
||||||
<img src="SoftFever_doc\sponsor_logos\QIDI.png" alt="QIDI" width="96" height="">
|
<img src="SoftFever_doc\sponsor_logos\QIDI.png" alt="QIDI" width="96" height="">
|
||||||
</a>
|
</a>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.9 KiB |
File diff suppressed because it is too large
Load diff
|
@ -36,6 +36,9 @@ uniform SlopeDetection slope;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
uniform bool is_outline;
|
uniform bool is_outline;
|
||||||
|
uniform sampler2D depth_tex;
|
||||||
|
uniform vec2 screen_size;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
uniform sampler2D environment_tex;
|
uniform sampler2D environment_tex;
|
||||||
|
@ -44,6 +47,9 @@ uniform bool is_outline;
|
||||||
|
|
||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
|
uniform float z_far;
|
||||||
|
uniform float z_near;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
varying float color_clip_plane_dot;
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
|
@ -54,6 +60,71 @@ varying vec4 world_pos;
|
||||||
varying float world_normal_z;
|
varying float world_normal_z;
|
||||||
varying vec3 eye_normal;
|
varying vec3 eye_normal;
|
||||||
|
|
||||||
|
vec3 getBackfaceColor(vec3 fill) {
|
||||||
|
float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b;
|
||||||
|
return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Silhouette edge detection & rendering algorithem by leoneruggiero
|
||||||
|
// https://www.shadertoy.com/view/DslXz2
|
||||||
|
#define INFLATE 1
|
||||||
|
|
||||||
|
float GetTolerance(float d, float k)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// Find a tolerance for depth that is constant
|
||||||
|
// in view space (k in view space).
|
||||||
|
//
|
||||||
|
// tol = k*ddx(ZtoDepth(z))
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float A=- (z_far+z_near)/(z_far-z_near);
|
||||||
|
float B=-2.0*z_far*z_near /(z_far-z_near);
|
||||||
|
|
||||||
|
d = d*2.0-1.0;
|
||||||
|
|
||||||
|
return -k*(d+A)*(d+A)/B;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(vec2 fragCoord, vec2 dir)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// x0 ___ x1----o
|
||||||
|
// :\ :
|
||||||
|
// r0 : \ : r1
|
||||||
|
// : \ :
|
||||||
|
// o---x2 ___ x3
|
||||||
|
//
|
||||||
|
// r0 and r1 are the differences between actual
|
||||||
|
// and expected (as if x0..3 where on the same
|
||||||
|
// plane) depth values.
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float x0 = abs(texture2D(depth_tex, (fragCoord + dir*-2.0) / screen_size).r);
|
||||||
|
float x1 = abs(texture2D(depth_tex, (fragCoord + dir*-1.0) / screen_size).r);
|
||||||
|
float x2 = abs(texture2D(depth_tex, (fragCoord + dir* 0.0) / screen_size).r);
|
||||||
|
float x3 = abs(texture2D(depth_tex, (fragCoord + dir* 1.0) / screen_size).r);
|
||||||
|
|
||||||
|
float d0 = (x1-x0);
|
||||||
|
float d1 = (x2-x3);
|
||||||
|
|
||||||
|
float r0 = x1 + d0 - x2;
|
||||||
|
float r1 = x2 + d1 - x1;
|
||||||
|
|
||||||
|
float tol = GetTolerance(x2, 0.04);
|
||||||
|
|
||||||
|
return smoothstep(0.0, tol*tol, max( - r0*r1, 0.0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(vec2 fragCoord)
|
||||||
|
{
|
||||||
|
return max(
|
||||||
|
DetectSilho(fragCoord, vec2(1,0)), // Horizontal
|
||||||
|
DetectSilho(fragCoord, vec2(0,1)) // Vertical
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
|
@ -96,8 +167,18 @@ void main()
|
||||||
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
if (is_outline)
|
if (is_outline) {
|
||||||
gl_FragColor = uniform_color;
|
color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
|
float s = DetectSilho(fragCoord);
|
||||||
|
// Makes silhouettes thicker.
|
||||||
|
for(int i=1;i<=INFLATE; i++)
|
||||||
|
{
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
|
||||||
|
}
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
else if (use_environment_tex)
|
else if (use_environment_tex)
|
||||||
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
|
|
|
@ -36,6 +36,8 @@ uniform SlopeDetection slope;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
uniform bool is_outline;
|
uniform bool is_outline;
|
||||||
|
uniform sampler2D depth_tex;
|
||||||
|
uniform vec2 screen_size;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
uniform sampler2D environment_tex;
|
uniform sampler2D environment_tex;
|
||||||
|
@ -44,6 +46,9 @@ uniform bool is_outline;
|
||||||
|
|
||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
|
uniform float z_far;
|
||||||
|
uniform float z_near;
|
||||||
|
|
||||||
in vec3 clipping_planes_dots;
|
in vec3 clipping_planes_dots;
|
||||||
in float color_clip_plane_dot;
|
in float color_clip_plane_dot;
|
||||||
|
|
||||||
|
@ -54,6 +59,71 @@ in vec4 world_pos;
|
||||||
in float world_normal_z;
|
in float world_normal_z;
|
||||||
in vec3 eye_normal;
|
in vec3 eye_normal;
|
||||||
|
|
||||||
|
vec3 getBackfaceColor(vec3 fill) {
|
||||||
|
float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b;
|
||||||
|
return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Silhouette edge detection & rendering algorithem by leoneruggiero
|
||||||
|
// https://www.shadertoy.com/view/DslXz2
|
||||||
|
#define INFLATE 1
|
||||||
|
|
||||||
|
float GetTolerance(float d, float k)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// Find a tolerance for depth that is constant
|
||||||
|
// in view space (k in view space).
|
||||||
|
//
|
||||||
|
// tol = k*ddx(ZtoDepth(z))
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float A=- (z_far+z_near)/(z_far-z_near);
|
||||||
|
float B=-2.0*z_far*z_near /(z_far-z_near);
|
||||||
|
|
||||||
|
d = d*2.0-1.0;
|
||||||
|
|
||||||
|
return -k*(d+A)*(d+A)/B;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(vec2 fragCoord, vec2 dir)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// x0 ___ x1----o
|
||||||
|
// :\ :
|
||||||
|
// r0 : \ : r1
|
||||||
|
// : \ :
|
||||||
|
// o---x2 ___ x3
|
||||||
|
//
|
||||||
|
// r0 and r1 are the differences between actual
|
||||||
|
// and expected (as if x0..3 where on the same
|
||||||
|
// plane) depth values.
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float x0 = abs(texture(depth_tex, (fragCoord + dir*-2.0) / screen_size).r);
|
||||||
|
float x1 = abs(texture(depth_tex, (fragCoord + dir*-1.0) / screen_size).r);
|
||||||
|
float x2 = abs(texture(depth_tex, (fragCoord + dir* 0.0) / screen_size).r);
|
||||||
|
float x3 = abs(texture(depth_tex, (fragCoord + dir* 1.0) / screen_size).r);
|
||||||
|
|
||||||
|
float d0 = (x1-x0);
|
||||||
|
float d1 = (x2-x3);
|
||||||
|
|
||||||
|
float r0 = x1 + d0 - x2;
|
||||||
|
float r1 = x2 + d1 - x1;
|
||||||
|
|
||||||
|
float tol = GetTolerance(x2, 0.04);
|
||||||
|
|
||||||
|
return smoothstep(0.0, tol*tol, max( - r0*r1, 0.0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(vec2 fragCoord)
|
||||||
|
{
|
||||||
|
return max(
|
||||||
|
DetectSilho(fragCoord, vec2(1,0)), // Horizontal
|
||||||
|
DetectSilho(fragCoord, vec2(0,1)) // Vertical
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
out vec4 out_color;
|
out vec4 out_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
@ -98,8 +168,18 @@ void main()
|
||||||
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
if (is_outline)
|
if (is_outline) {
|
||||||
out_color = uniform_color;
|
color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
|
float s = DetectSilho(fragCoord);
|
||||||
|
// Makes silhouettes thicker.
|
||||||
|
for(int i=1;i<=INFLATE; i++)
|
||||||
|
{
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
|
||||||
|
}
|
||||||
|
out_color = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
|
||||||
|
}
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
else if (use_environment_tex)
|
else if (use_environment_tex)
|
||||||
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
|
|
|
@ -200,6 +200,8 @@ void AppConfig::set_defaults()
|
||||||
if (get("show_3d_navigator").empty())
|
if (get("show_3d_navigator").empty())
|
||||||
set_bool("show_3d_navigator", true);
|
set_bool("show_3d_navigator", true);
|
||||||
|
|
||||||
|
if (get("show_outline").empty())
|
||||||
|
set_bool("show_outline", false);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
|
|
@ -423,7 +423,7 @@ void GLVolume::render()
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: add outline related logic
|
//BBS: add outline related logic
|
||||||
void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
|
void GLVolume::render_with_outline(const GUI::Size& cnv_size)
|
||||||
{
|
{
|
||||||
if (!is_active)
|
if (!is_active)
|
||||||
return;
|
return;
|
||||||
|
@ -435,37 +435,79 @@ void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
|
||||||
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
||||||
std::vector<ColorRGBA> colors = get_extruders_colors();
|
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||||
|
|
||||||
glEnable(GL_STENCIL_TEST);
|
const GUI::OpenGLManager::EFramebufferType framebuffers_type = GUI::OpenGLManager::get_framebuffers_type();
|
||||||
glStencilMask(0xFF);
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Unknown) {
|
||||||
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
|
// No supported, degrade to normal rendering
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
|
||||||
glStencilFunc(GL_ALWAYS, 0xff, 0xFF);
|
|
||||||
|
|
||||||
simple_render(shader, model_objects, colors);
|
simple_render(shader, model_objects, colors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
// 1st. render pass, render the model into a separate render target that has only depth buffer
|
||||||
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
|
GLuint depth_fbo = 0;
|
||||||
// the objects' size differences, making it look like borders.
|
GLuint depth_tex = 0;
|
||||||
glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF);
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
glStencilMask(0x00);
|
glsafe(::glGenFramebuffers(1, &depth_fbo));
|
||||||
float scale = 1.02f;
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, depth_fbo));
|
||||||
ColorRGBA body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
|
|
||||||
|
|
||||||
model.set_color(body_color);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
shader->set_uniform("is_outline", true);
|
glsafe(::glGenTextures(1, &depth_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr));
|
||||||
|
|
||||||
Transform3d matrix = view_model_matrix;
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0));
|
||||||
matrix.scale(scale);
|
} else {
|
||||||
shader->set_uniform("view_model_matrix", matrix);
|
glsafe(::glGenFramebuffersEXT(1, &depth_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fbo));
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glsafe(::glGenTextures(1, &depth_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0));
|
||||||
|
}
|
||||||
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
||||||
model.render();
|
model.render();
|
||||||
else
|
else
|
||||||
model.render(this->tverts_range);
|
model.render(this->tverts_range);
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
|
||||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
// 2nd. render pass, just a normal render with the depth buffer passed as a texture
|
||||||
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
|
} else if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Ext) {
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
}
|
||||||
|
shader->set_uniform("is_outline", true);
|
||||||
|
shader->set_uniform("screen_size", Vec2f{cnv_size.get_width(), cnv_size.get_height()});
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
|
shader->set_uniform("depth_tex", 0);
|
||||||
|
simple_render(shader, model_objects, colors);
|
||||||
|
|
||||||
|
// Some clean up to do
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
shader->set_uniform("is_outline", false);
|
shader->set_uniform("is_outline", false);
|
||||||
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
glDisable(GL_STENCIL_TEST);
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
|
if (depth_fbo != 0)
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &depth_fbo));
|
||||||
|
} else if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Ext) {
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
if (depth_fbo != 0)
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &depth_fbo));
|
||||||
|
}
|
||||||
|
if (depth_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &depth_tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS add render for simple case
|
//BBS add render for simple case
|
||||||
|
@ -847,8 +889,8 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
|
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||||
std::function<bool(const GLVolume&)> filter_func, bool with_outline) const
|
std::function<bool(const GLVolume&)> filter_func) const
|
||||||
{
|
{
|
||||||
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
||||||
if (to_render.empty())
|
if (to_render.empty())
|
||||||
|
@ -953,9 +995,9 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
||||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||||
//BBS: add outline related logic
|
//BBS: add outline related logic
|
||||||
//if (with_outline && volume.first->selected)
|
if (volume.first->selected && GUI::wxGetApp().show_outline())
|
||||||
// volume.first->render_with_outline(view_matrix * model_matrix);
|
volume.first->render_with_outline(cnv_size);
|
||||||
//else
|
else
|
||||||
volume.first->render();
|
volume.first->render();
|
||||||
|
|
||||||
#if ENABLE_ENVIRONMENT_MAP
|
#if ENABLE_ENVIRONMENT_MAP
|
||||||
|
|
|
@ -39,6 +39,10 @@ extern Slic3r::ColorRGBA adjust_color_for_rendering(const Slic3r::C
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
class Size;
|
||||||
|
}
|
||||||
|
|
||||||
class SLAPrintObject;
|
class SLAPrintObject;
|
||||||
enum SLAPrintObjectStep : unsigned int;
|
enum SLAPrintObjectStep : unsigned int;
|
||||||
class BuildVolume;
|
class BuildVolume;
|
||||||
|
@ -322,7 +326,7 @@ public:
|
||||||
virtual void render();
|
virtual void render();
|
||||||
|
|
||||||
//BBS: add outline related logic and add virtual specifier
|
//BBS: add outline related logic and add virtual specifier
|
||||||
virtual void render_with_outline(const Transform3d &view_model_matrix);
|
virtual void render_with_outline(const GUI::Size& cnv_size);
|
||||||
|
|
||||||
//BBS: add simple render function for thumbnail
|
//BBS: add simple render function for thumbnail
|
||||||
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors, bool ban_light =false);
|
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors, bool ban_light =false);
|
||||||
|
@ -355,7 +359,7 @@ class GLWipeTowerVolume : public GLVolume {
|
||||||
public:
|
public:
|
||||||
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
||||||
void render() override;
|
void render() override;
|
||||||
void render_with_outline(const Transform3d &view_model_matrix) override { render(); }
|
void render_with_outline(const GUI::Size& cnv_size) override { render(); }
|
||||||
|
|
||||||
std::vector<GUI::GLModel> model_per_colors;
|
std::vector<GUI::GLModel> model_per_colors;
|
||||||
bool IsTransparent();
|
bool IsTransparent();
|
||||||
|
@ -465,8 +469,8 @@ public:
|
||||||
int get_selection_support_threshold_angle(bool&) const;
|
int get_selection_support_threshold_angle(bool&) const;
|
||||||
// Render the volumes by OpenGL.
|
// Render the volumes by OpenGL.
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
|
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(), bool with_outline = true) const;
|
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>()) const;
|
||||||
|
|
||||||
// Clear the geometry
|
// Clear the geometry
|
||||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||||
|
|
|
@ -143,6 +143,15 @@ static bool str_is_all_digit(const std::string &str) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom comparator for case-insensitive sorting
|
||||||
|
static bool caseInsensitiveCompare(const std::string& a, const std::string& b) {
|
||||||
|
std::string lowerA = a;
|
||||||
|
std::string lowerB = b;
|
||||||
|
std::transform(lowerA.begin(), lowerA.end(), lowerA.begin(), ::tolower);
|
||||||
|
std::transform(lowerB.begin(), lowerB.end(), lowerB.begin(), ::tolower);
|
||||||
|
return lowerA < lowerB;
|
||||||
|
}
|
||||||
|
|
||||||
static bool delete_filament_preset_by_name(std::string delete_preset_name, std::string &selected_preset_name)
|
static bool delete_filament_preset_by_name(std::string delete_preset_name, std::string &selected_preset_name)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select preset, name %1%") % delete_preset_name;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("select preset, name %1%") % delete_preset_name;
|
||||||
|
@ -692,11 +701,19 @@ wxBoxSizer *CreateFilamentPresetDialog::create_vendor_item()
|
||||||
optionSizer->SetMinSize(OPTION_SIZE);
|
optionSizer->SetMinSize(OPTION_SIZE);
|
||||||
horizontal_sizer->Add(optionSizer, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
horizontal_sizer->Add(optionSizer, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||||
|
|
||||||
wxArrayString choices;
|
// Convert all std::any to std::string
|
||||||
for (const wxString vendor : filament_vendors) {
|
std::vector<std::string> string_vendors;
|
||||||
choices.push_back(vendor);
|
for (const auto& vendor_any : filament_vendors) {
|
||||||
|
string_vendors.push_back(std::any_cast<std::string>(vendor_any));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the vendors alphabetically
|
||||||
|
std::sort(string_vendors.begin(), string_vendors.end(), caseInsensitiveCompare);
|
||||||
|
|
||||||
|
wxArrayString choices;
|
||||||
|
for (const std::string &vendor : string_vendors) {
|
||||||
|
choices.push_back(wxString(vendor)); // Convert std::string to wxString before adding
|
||||||
}
|
}
|
||||||
choices.Sort();
|
|
||||||
|
|
||||||
wxBoxSizer *vendor_sizer = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer *vendor_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
m_filament_vendor_combobox = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, NAME_OPTION_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY);
|
m_filament_vendor_combobox = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, NAME_OPTION_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY);
|
||||||
|
|
|
@ -1244,7 +1244,7 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
|
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
render_shells();
|
render_shells(canvas_width, canvas_height);
|
||||||
|
|
||||||
if (m_roles.empty())
|
if (m_roles.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -4023,7 +4023,7 @@ void GCodeViewer::render_toolpaths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::render_shells()
|
void GCodeViewer::render_shells(int canvas_width, int canvas_height)
|
||||||
{
|
{
|
||||||
//BBS: add shell previewing logic
|
//BBS: add shell previewing logic
|
||||||
if ((!m_shells.previewing && !m_shells.visible) || m_shells.volumes.empty())
|
if ((!m_shells.previewing && !m_shells.visible) || m_shells.volumes.empty())
|
||||||
|
@ -4039,7 +4039,9 @@ void GCodeViewer::render_shells()
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.1f);
|
shader->set_uniform("emission_factor", 0.1f);
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
shader->set_uniform("z_far", camera.get_far_z());
|
||||||
|
shader->set_uniform("z_near", camera.get_near_z());
|
||||||
|
m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, camera.get_view_matrix(), camera.get_projection_matrix(), {canvas_width, canvas_height});
|
||||||
shader->set_uniform("emission_factor", 0.0f);
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
|
||||||
|
|
|
@ -893,7 +893,7 @@ private:
|
||||||
//void load_shells(const Print& print);
|
//void load_shells(const Print& print);
|
||||||
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
||||||
void render_toolpaths();
|
void render_toolpaths();
|
||||||
void render_shells();
|
void render_shells(int canvas_width, int canvas_height);
|
||||||
|
|
||||||
//BBS: GUI refactor: add canvas size
|
//BBS: GUI refactor: add canvas size
|
||||||
void render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin);
|
void render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin);
|
||||||
|
|
|
@ -7234,6 +7234,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
if (shader != nullptr) {
|
if (shader != nullptr) {
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
|
|
||||||
|
const Size& cvn_size = get_canvas_size();
|
||||||
|
{
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
shader->set_uniform("z_far", camera.get_far_z());
|
||||||
|
shader->set_uniform("z_near", camera.get_near_z());
|
||||||
|
}
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -7245,7 +7251,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
|
if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
|
||||||
int object_id = m_layers_editing.last_object_id;
|
int object_id = m_layers_editing.last_object_id;
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [object_id](const GLVolume& volume) {
|
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [object_id](const GLVolume& volume) {
|
||||||
// Which volume to paint without the layer height profile shader?
|
// Which volume to paint without the layer height profile shader?
|
||||||
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
|
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
|
||||||
});
|
});
|
||||||
|
@ -7261,14 +7267,14 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
//BBS:add assemble view related logic
|
//BBS:add assemble view related logic
|
||||||
// do not cull backfaces to show broken geometry, if any
|
// do not cull backfaces to show broken geometry, if any
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_volumes.render(type, m_picking_enabled, camera.get_view_matrix(), camera.get_projection_matrix(), [this, canvas_type](const GLVolume& volume) {
|
m_volumes.render(type, m_picking_enabled, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [this, canvas_type](const GLVolume& volume) {
|
||||||
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
||||||
return !volume.is_modifier && !volume.is_wipe_tower;
|
return !volume.is_modifier && !volume.is_wipe_tower;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
||||||
}
|
}
|
||||||
}, with_outline);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -7295,14 +7301,14 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
}*/
|
}*/
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
//BBS:add assemble view related logic
|
//BBS:add assemble view related logic
|
||||||
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [this, canvas_type](const GLVolume& volume) {
|
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [this, canvas_type](const GLVolume& volume) {
|
||||||
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
||||||
return !volume.is_modifier;
|
return !volume.is_modifier;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, with_outline);
|
});
|
||||||
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
||||||
const GLGizmosManager& gm = get_gizmos_manager();
|
const GLGizmosManager& gm = get_gizmos_manager();
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
|
|
@ -344,6 +344,9 @@ private:
|
||||||
bool show_3d_navigator() const { return app_config->get_bool("show_3d_navigator"); }
|
bool show_3d_navigator() const { return app_config->get_bool("show_3d_navigator"); }
|
||||||
void toggle_show_3d_navigator() const { app_config->set_bool("show_3d_navigator", !show_3d_navigator()); }
|
void toggle_show_3d_navigator() const { app_config->set_bool("show_3d_navigator", !show_3d_navigator()); }
|
||||||
|
|
||||||
|
bool show_outline() const { return app_config->get_bool("show_outline"); }
|
||||||
|
void toggle_show_outline() const { app_config->set_bool("show_outline", !show_outline()); }
|
||||||
|
|
||||||
wxString get_inf_dialog_contect () {return m_info_dialog_content;};
|
wxString get_inf_dialog_contect () {return m_info_dialog_content;};
|
||||||
|
|
||||||
std::vector<std::string> split_str(std::string src, std::string separator);
|
std::vector<std::string> split_str(std::string src, std::string separator);
|
||||||
|
|
|
@ -2642,6 +2642,16 @@ void MainFrame::init_menubar_as_editor()
|
||||||
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||||
},
|
},
|
||||||
this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->is_view3D_overhang_shown(); }, this);
|
this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->is_view3D_overhang_shown(); }, this);
|
||||||
|
|
||||||
|
append_menu_check_item(
|
||||||
|
viewMenu, wxID_ANY, _L("Show Selected Outline (Experimental)"), _L("Show outline around selected object in 3D scene"),
|
||||||
|
[this](wxCommandEvent&) {
|
||||||
|
wxGetApp().toggle_show_outline();
|
||||||
|
m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT));
|
||||||
|
},
|
||||||
|
this, [this]() { return m_tabpanel->GetSelection() == TabPosition::tp3DEditor; },
|
||||||
|
[this]() { return wxGetApp().show_outline(); }, this);
|
||||||
|
|
||||||
/*viewMenu->AppendSeparator();
|
/*viewMenu->AppendSeparator();
|
||||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene"),
|
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Wireframe") + "\tCtrl+Shift+Enter", _L("Show wireframes in 3D scene"),
|
||||||
[this](wxCommandEvent&) { m_plater->toggle_show_wireframe(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this,
|
[this](wxCommandEvent&) { m_plater->toggle_show_wireframe(); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this,
|
||||||
|
|
|
@ -4457,7 +4457,7 @@ void TabPrinter::toggle_options()
|
||||||
toggle_line(el, is_BBL_printer);
|
toggle_line(el, is_BBL_printer);
|
||||||
|
|
||||||
// SoftFever: hide non-BBL settings
|
// SoftFever: hide non-BBL settings
|
||||||
for (auto el : {"use_firmware_retraction", "use_relative_e_distances", "support_multi_bed_types", "pellet_modded_printer"})
|
for (auto el : {"use_firmware_retraction", "use_relative_e_distances", "support_multi_bed_types", "pellet_modded_printer", "bed_mesh_max", "bed_mesh_min", "bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "thumbnails"})
|
||||||
toggle_line(el, !is_BBL_printer);
|
toggle_line(el, !is_BBL_printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue