Tech ENABLE_LEGACY_OPENGL_REMOVAL - porting remaining changes

(cherry picked from commit prusa3d/PrusaSlicer@2f572d3cf0 )
This commit is contained in:
enricoturri1966 2023-10-25 23:14:53 +08:00 committed by Noisyfox
parent 9f4713eee8
commit 71fd4084c2
68 changed files with 2145 additions and 1837 deletions

View file

@ -0,0 +1,12 @@
#version 110
attribute vec3 v_position;
attribute vec2 v_tex_coord;
varying vec2 tex_coord;
void main()
{
tex_coord = v_tex_coord;
gl_Position = vec4(v_position, 1.0);
}

View file

@ -1,8 +0,0 @@
#version 110
uniform vec4 uniform_color;
void main()
{
gl_FragColor = uniform_color;
}

View file

@ -1,6 +0,0 @@
#version 110
void main()
{
gl_Position = ftransform();
}

View file

@ -2,9 +2,10 @@
attribute vec3 v_position; attribute vec3 v_position;
uniform mat4 projection_view_model_matrix; uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
void main() void main()
{ {
gl_Position = projection_view_model_matrix * vec4(v_position, 1.0); gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
} }

View file

@ -0,0 +1,15 @@
#version 110
attribute vec3 v_position;
attribute vec2 v_tex_coord;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
varying vec2 tex_coord;
void main()
{
tex_coord = v_tex_coord;
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
}

View file

@ -48,7 +48,6 @@ varying vec2 intensity;
uniform PrintVolumeDetection print_volume; uniform PrintVolumeDetection print_volume;
varying vec4 model_pos;
varying vec4 world_pos; varying vec4 world_pos;
varying float world_normal_z; varying float world_normal_z;
varying vec3 eye_normal; varying vec3 eye_normal;

View file

@ -38,7 +38,6 @@ varying vec2 intensity;
varying vec3 clipping_planes_dots; varying vec3 clipping_planes_dots;
varying vec4 model_pos;
varying vec4 world_pos; varying vec4 world_pos;
varying float world_normal_z; varying float world_normal_z;
varying vec3 eye_normal; varying vec3 eye_normal;
@ -60,7 +59,6 @@ void main()
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
model_pos = gl_Vertex;
// Point in homogenous coordinates. // Point in homogenous coordinates.
world_pos = volume_world_matrix * gl_Vertex; world_pos = volume_world_matrix * gl_Vertex;

View file

@ -0,0 +1,77 @@
#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 LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SHININESS 5.0
#define INTENSITY_AMBIENT 0.3
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
struct SlopeDetection
{
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
};
attribute vec3 v_position;
attribute vec3 v_normal;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
uniform mat4 volume_world_matrix;
uniform SlopeDetection slope;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;
// x = diffuse, y = specular;
varying vec2 intensity;
varying vec3 clipping_planes_dots;
varying vec4 world_pos;
varying float world_normal_z;
varying vec3 eye_normal;
void main()
{
// First transform the normal into camera space and normalize the result.
eye_normal = normalize(normal_matrix * v_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(eye_normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec4 position = view_model_matrix * vec4(v_position, 1.0);
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
// Point in homogenous coordinates.
world_pos = volume_world_matrix * vec4(v_position, 1.0);
// z component of normal vector in world coordinate used for slope shading
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
gl_Position = projection_matrix * position;
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
}

View file

@ -0,0 +1,45 @@
#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
attribute vec3 v_position;
attribute vec3 v_normal;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
// x = tainted, y = specular;
varying vec2 intensity;
void main()
{
// First transform the normal into camera space and normalize the result.
vec3 normal = normalize(normal_matrix * v_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;
vec4 position = view_model_matrix * vec4(v_position, 1.0);
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), 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;
gl_Position = projection_matrix * position;
}

View file

@ -0,0 +1,50 @@
#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
// vertex attributes
attribute vec3 v_position;
attribute vec3 v_normal;
// instance attributes
attribute vec3 i_offset;
attribute vec2 i_scales;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
// x = tainted, y = specular;
varying vec2 intensity;
void main()
{
// First transform the normal into camera space and normalize the result.
vec3 eye_normal = normalize(normal_matrix * v_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(eye_normal, LIGHT_TOP_DIR), 0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
vec4 eye_position = view_model_matrix * world_position;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
gl_Position = projection_matrix * eye_position;
}

View file

@ -0,0 +1,13 @@
#version 110
const float EPSILON = 0.0001;
uniform vec4 uniform_color;
void main()
{
gl_FragColor = uniform_color;
// Values inside depth buffer for fragments of the contour of a selected area are offset
// by small epsilon to solve z-fighting between painted triangles and contour lines.
gl_FragDepth = gl_FragCoord.z - EPSILON;
}

View file

@ -0,0 +1,11 @@
#version 110
attribute vec3 v_position;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
void main()
{
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
}

View file

@ -0,0 +1,90 @@
#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
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
const float EPSILON = 0.0001;
//BBS: add grey and orange
//const vec3 GREY = vec3(0.9, 0.9, 0.9);
const vec3 ORANGE = vec3(0.8, 0.4, 0.0);
const vec3 LightRed = vec3(0.78, 0.0, 0.0);
const vec3 LightBlue = vec3(0.73, 1.0, 1.0);
uniform vec4 uniform_color;
uniform bool volume_mirrored;
uniform mat4 view_model_matrix;
uniform mat3 normal_matrix;
varying vec3 clipping_planes_dots;
varying vec4 model_pos;
varying vec4 world_pos;
struct SlopeDetection
{
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
};
uniform SlopeDetection slope;
void main()
{
if (any(lessThan(clipping_planes_dots, ZERO)))
discard;
vec3 color = uniform_color.rgb;
float alpha = uniform_color.a;
vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz)));
#ifdef FLIP_TRIANGLE_NORMALS
triangle_normal = -triangle_normal;
#endif
if (volume_mirrored)
triangle_normal = -triangle_normal;
vec3 transformed_normal = normalize(slope.volume_world_normal_matrix * triangle_normal);
if (slope.actived) {
if(world_pos.z<0.1&&world_pos.z>-0.1)
{
color = LightBlue;
alpha = 1.0;
}
else if( transformed_normal.z < slope.normal_z - EPSILON)
{
color = color * 0.5 + LightRed * 0.5;
alpha = 1.0;
}
}
// First transform the normal into camera space and normalize the result.
vec3 eye_normal = normalize(normal_matrix * triangle_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(eye_normal, LIGHT_TOP_DIR), 0.0);
// x = diffuse, y = specular;
vec2 intensity = vec2(0.0);
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
vec3 position = (view_model_matrix * model_pos).xyz;
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular applied).
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
}

View file

@ -0,0 +1,35 @@
#version 110
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
attribute vec3 v_position;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat4 volume_world_matrix;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;
varying vec3 clipping_planes_dots;
varying vec4 model_pos;
varying vec4 world_pos;
struct SlopeDetection
{
bool actived;
float normal_z;
mat3 volume_world_normal_matrix;
};
uniform SlopeDetection slope;
void main()
{
model_pos = vec4(v_position, 1.0);
// Point in homogenous coordinates.
world_pos = volume_world_matrix * model_pos;
gl_Position = projection_matrix * view_model_matrix * model_pos;
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
}

View file

@ -1,8 +0,0 @@
#version 110
uniform vec4 uniform_color;
void main()
{
gl_FragColor = uniform_color;
}

View file

@ -1,22 +0,0 @@
#version 110
uniform bool use_fixed_screen_size;
uniform float zoom;
uniform float point_size;
uniform float near_plane_height;
float fixed_screen_size()
{
return point_size;
}
float fixed_world_size()
{
return (gl_Position.w == 1.0) ? zoom * near_plane_height * point_size : near_plane_height * point_size / gl_Position.w;
}
void main()
{
gl_Position = ftransform();
gl_PointSize = use_fixed_screen_size ? fixed_screen_size() : fixed_world_size();
}

View file

@ -1,22 +0,0 @@
// version 120 is needed for gl_PointCoord
#version 120
uniform vec4 uniform_color;
uniform float percent_outline_radius;
uniform float percent_center_radius;
vec4 calc_color(float radius, vec4 color)
{
return ((radius < percent_center_radius) || (radius > 1.0 - percent_outline_radius)) ?
vec4(0.5 * color.rgb, color.a) : color;
}
void main()
{
vec2 pos = (gl_PointCoord - 0.5) * 2.0;
float radius = length(pos);
if (radius > 1.0)
discard;
gl_FragColor = calc_color(radius, uniform_color);
}

View file

@ -1,22 +0,0 @@
#version 120
uniform bool use_fixed_screen_size;
uniform float zoom;
uniform float point_size;
uniform float near_plane_height;
float fixed_screen_size()
{
return point_size;
}
float fixed_world_size()
{
return (gl_Position.w == 1.0) ? zoom * near_plane_height * point_size : near_plane_height * point_size / gl_Position.w;
}
void main()
{
gl_Position = ftransform();
gl_PointSize = use_fixed_screen_size ? fixed_screen_size() : fixed_world_size();
}

View file

@ -7,15 +7,15 @@ uniform sampler2D texture;
uniform bool transparent_background; uniform bool transparent_background;
uniform bool svg_source; uniform bool svg_source;
varying vec2 tex_coords; varying vec2 tex_coord;
vec4 svg_color() vec4 svg_color()
{ {
// takes foreground from texture // takes foreground from texture
vec4 fore_color = texture2D(texture, tex_coords); vec4 fore_color = texture2D(texture, tex_coord);
// calculates radial gradient // calculates radial gradient
vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coords.xy) - vec2(0.5))))); vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
// blends foreground with background // blends foreground with background
return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0);
@ -24,7 +24,7 @@ vec4 svg_color()
vec4 non_svg_color() vec4 non_svg_color()
{ {
// takes foreground from texture // takes foreground from texture
vec4 color = texture2D(texture, tex_coords); vec4 color = texture2D(texture, tex_coord);
return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
} }

View file

@ -1,9 +1,9 @@
#version 110 #version 110
varying vec2 tex_coords; varying vec2 tex_coord;
void main() void main()
{ {
gl_Position = ftransform(); gl_Position = ftransform();
tex_coords = gl_MultiTexCoord0.xy; tex_coord = gl_MultiTexCoord0.xy;
} }

View file

@ -0,0 +1,15 @@
#version 110
attribute vec3 v_position;
attribute vec2 v_tex_coord;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
varying vec2 tex_coord;
void main()
{
tex_coord = v_tex_coord;
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
}

View file

@ -0,0 +1,51 @@
#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
attribute vec3 v_position;
attribute vec3 v_normal;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
uniform mat4 volume_world_matrix;
// x = tainted, y = specular;
varying vec2 intensity;
varying vec4 world_pos;
void main()
{
// First transform the normal into camera space and normalize the result.
vec3 normal = normalize(normal_matrix * v_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;
vec4 position = view_model_matrix * vec4(v_position, 1.0);
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), 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;
// Point in homogenous coordinates.
world_pos = volume_world_matrix * gl_Vertex;
gl_Position = projection_matrix * position;
}

View file

@ -0,0 +1,60 @@
#version 110
#define INTENSITY_CORRECTION 0.6
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
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
//#define LIGHT_FRONT_SHININESS 5.0
#define INTENSITY_AMBIENT 0.3
attribute vec3 v_position;
attribute vec3 v_normal;
attribute vec2 v_tex_coord;
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
uniform mat4 volume_world_matrix;
uniform float object_max_z;
// x = tainted, y = specular;
varying vec2 intensity;
varying float object_z;
void main()
{
// =====================================================
// NOTE:
// when object_max_z > 0.0 we are rendering the overlay
// when object_max_z == 0.0 we are rendering the volumes
// =====================================================
// First transform the normal into camera space and normalize the result.
vec3 normal = (object_max_z > 0.0) ? vec3(0.0, 0.0, 1.0) : normalize(normal_matrix * v_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;
vec4 position = view_model_matrix * vec4(v_position, 1.0);
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
// Perform the same lighting calculation for the 2nd light source (no specular)
NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
// Scaled to widths of the Z texture.
object_z = (object_max_z > 0.0) ? object_max_z * v_tex_coord.y : (volume_world_matrix * vec4(v_position, 1.0)).z;
gl_Position = projection_matrix * position;
}

View file

@ -2370,7 +2370,7 @@ int CLI::run(int argc, char **argv)
} }
ThumbnailsParams thumbnail_params; ThumbnailsParams thumbnail_params;
GLShaderProgram* shader = opengl_mgr.get_shader("thumbnail"); GLShaderProgram* shader = opengl_mgr.get_shader("thumbnail_attr");
if (!shader) { if (!shader) {
BOOST_LOG_TRIVIAL(error) << boost::format("can not get shader for rendering thumbnail"); BOOST_LOG_TRIVIAL(error) << boost::format("can not get shader for rendering thumbnail");
} }

View file

@ -47,7 +47,7 @@ bool init_model_from_poly(GLModel &model, const ExPolygon &poly, float z)
return false; return false;
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2, GLModel::Geometry::index_type(triangles.size()) }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2 };
init_data.reserve_vertices(triangles.size()); init_data.reserve_vertices(triangles.size());
init_data.reserve_indices(triangles.size() / 3); init_data.reserve_indices(triangles.size() / 3);
@ -71,12 +71,8 @@ bool init_model_from_poly(GLModel &model, const ExPolygon &poly, float z)
const Vec3f p = {v.x(), v.y(), z}; const Vec3f p = {v.x(), v.y(), z};
init_data.add_vertex(p, (Vec2f)(v - min).cwiseProduct(inv_size).eval()); init_data.add_vertex(p, (Vec2f)(v - min).cwiseProduct(inv_size).eval());
++vertices_counter; ++vertices_counter;
if (vertices_counter % 3 == 0) { if (vertices_counter % 3 == 0)
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
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);
}
} }
model.init_from(std::move(init_data)); model.init_from(std::move(init_data));
@ -210,17 +206,19 @@ void Bed3D::load_render_colors()
void Bed3D::Axes::render() void Bed3D::Axes::render()
{ {
auto render_axis = [this](const Transform3f& transform) { auto render_axis = [this](GLShaderProgram* shader, const Transform3d& transform) {
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixf(transform.data())); const Transform3d matrix = camera.get_view_matrix() * transform;
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.render(); m_arrow.render();
glsafe(::glPopMatrix());
}; };
if (!m_arrow.is_initialized()) if (!m_arrow.is_initialized())
m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -231,15 +229,15 @@ void Bed3D::Axes::render()
// x axis // x axis
m_arrow.set_color(AXIS_X_COLOR); m_arrow.set_color(AXIS_X_COLOR);
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>()); render_axis(shader, Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }));
// y axis // y axis
m_arrow.set_color(AXIS_Y_COLOR); m_arrow.set_color(AXIS_Y_COLOR);
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>()); render_axis(shader, Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }));
// z axis // z axis
m_arrow.set_color(AXIS_Z_COLOR); m_arrow.set_color(AXIS_Z_COLOR);
render_axis(Geometry::assemble_transform(m_origin).cast<float>()); render_axis(shader, Geometry::assemble_transform(m_origin));
shader->stop_using(); shader->stop_using();
@ -362,17 +360,17 @@ void Bed3D::on_change_color_mode(bool is_dark)
m_is_dark = is_dark; m_is_dark = is_dark;
} }
void Bed3D::render(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes) void Bed3D::render(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor, bool show_axes)
{ {
render_internal(canvas, bottom, scale_factor, show_axes); render_internal(canvas, view_matrix, projection_matrix, bottom, scale_factor, show_axes);
} }
/*void Bed3D::render_for_picking(GLCanvas3D& canvas, bool bottom, float scale_factor) /*void Bed3D::render_for_picking(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor)
{ {
render_internal(canvas, bottom, scale_factor, false, false, true); render_internal(canvas, view_matrix, projection_matrix, bottom, scale_factor, false, false, true);
}*/ }*/
void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, void Bed3D::render_internal(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor,
bool show_axes) bool show_axes)
{ {
m_scale_factor = scale_factor; m_scale_factor = scale_factor;
@ -386,9 +384,9 @@ void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
switch (m_type) switch (m_type)
{ {
case Type::System: { render_system(canvas, bottom); break; } case Type::System: { render_system(canvas, view_matrix, projection_matrix, bottom); break; }
default: default:
case Type::Custom: { render_custom(canvas, bottom); break; } case Type::Custom: { render_custom(canvas, view_matrix, projection_matrix, bottom); break; }
} }
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
@ -464,10 +462,10 @@ void Bed3D::render_axes()
m_axes.render(); m_axes.render();
} }
void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) void Bed3D::render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom)
{ {
if (!bottom) if (!bottom)
render_model(); render_model(view_matrix, projection_matrix);
/*if (show_texture) /*if (show_texture)
render_texture(bottom, canvas);*/ render_texture(bottom, canvas);*/
@ -538,9 +536,12 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom)
} }
if (m_triangles.get_vertices_count() > 0) { if (m_triangles.get_vertices_count() > 0) {
GLShaderProgram* shader = wxGetApp().get_shader("printbed"); GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("transparent_background", bottom); shader->set_uniform("transparent_background", bottom);
shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg")); shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg"));
@ -658,7 +659,7 @@ void Bed3D::update_bed_triangles()
const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box(); const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box();
} }
void Bed3D::render_model() void Bed3D::render_model(const Transform3d& view_matrix, const Transform3d& projection_matrix)
{ {
if (m_model_filename.empty()) if (m_model_filename.empty())
return; return;
@ -670,20 +671,21 @@ void Bed3D::render_model()
} }
if (!m_model.get_filename().empty()) { if (!m_model.get_filename().empty()) {
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.0f); shader->set_uniform("emission_factor", 0.0f);
glsafe(::glPushMatrix()); const Transform3d matrix = view_matrix * Geometry::assemble_transform(m_model_offset);
glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_model.render(); m_model.render();
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
} }
} }
} }
void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom) void Bed3D::render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom)
{ {
if (m_model_filename.empty()) { if (m_model_filename.empty()) {
render_default(bottom); render_default(bottom);
@ -691,7 +693,7 @@ void Bed3D::render_custom(GLCanvas3D& canvas, bool bottom)
} }
if (!bottom) if (!bottom)
render_model(); render_model(view_matrix, projection_matrix);
/*if (show_texture) /*if (show_texture)
render_texture(bottom, canvas);*/ render_texture(bottom, canvas);*/
@ -708,8 +710,9 @@ void Bed3D::render_default(bool bottom)
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Transform3d matrix = wxGetApp().plater()->get_camera().get_projection_view_matrix(); const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("projection_view_model_matrix", matrix); shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));

View file

@ -146,8 +146,8 @@ public:
bool contains(const Point& point) const; bool contains(const Point& point) const;
Point point_projection(const Point& point) const; Point point_projection(const Point& point) const;
void render(GLCanvas3D& canvas, bool bottom, float scale_factor, bool show_axes); void render(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor, bool show_axes);
//void render_for_picking(GLCanvas3D& canvas, bool bottom, float scale_factor); //void render_for_picking(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor);
void on_change_color_mode(bool is_dark); void on_change_color_mode(bool is_dark);
@ -159,13 +159,13 @@ private:
//BBS: with offset //BBS: with offset
void update_bed_triangles(); void update_bed_triangles();
static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape); static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape);
void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, void render_internal(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor,
bool show_axes); bool show_axes);
void render_axes(); void render_axes();
void render_system(GLCanvas3D& canvas, bool bottom); void render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom);
//void render_texture(bool bottom, GLCanvas3D& canvas); //void render_texture(bool bottom, GLCanvas3D& canvas);
void render_model(); void render_model(const Transform3d& view_matrix, const Transform3d& projection_matrix);
void render_custom(GLCanvas3D& canvas, bool bottom); void render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom);
void render_default(bool bottom); void render_default(bool bottom);
}; };

View file

@ -6,6 +6,7 @@
#include "GUI_Colors.hpp" #include "GUI_Colors.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "BitmapCache.hpp" #include "BitmapCache.hpp"
#include "Camera.hpp"
#include "libslic3r/BuildVolume.hpp" #include "libslic3r/BuildVolume.hpp"
#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntity.hpp"
@ -96,10 +97,14 @@ void GLVolume::SinkingContours::render()
{ {
update(); update();
glsafe(::glPushMatrix()); GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
glsafe(::glTranslated(m_shift.x(), m_shift.y(), m_shift.z())); if (shader == nullptr)
return;
const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_shift));
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_model.render(); m_model.render();
glsafe(::glPopMatrix());
} }
void GLVolume::SinkingContours::update() void GLVolume::SinkingContours::update()
@ -117,7 +122,7 @@ void GLVolume::SinkingContours::update()
m_model.reset(); m_model.reset();
GUI::GLModel::Geometry init_data; GUI::GLModel::Geometry init_data;
init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3, GUI::GLModel::Geometry::EIndexType::UINT }; init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3 };
init_data.color = ColorRGBA::WHITE(); init_data.color = ColorRGBA::WHITE();
unsigned int vertices_counter = 0; unsigned int vertices_counter = 0;
MeshSlicingParams slicing_params; MeshSlicingParams slicing_params;
@ -131,7 +136,7 @@ void GLVolume::SinkingContours::update()
init_data.add_vertex((Vec3f)(v.cast<float>() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting init_data.add_vertex((Vec3f)(v.cast<float>() + 0.015f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
++vertices_counter; ++vertices_counter;
if (vertices_counter % 3 == 0) if (vertices_counter % 3 == 0)
init_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
} }
} }
m_model.init_from(std::move(init_data)); m_model.init_from(std::move(init_data));
@ -398,10 +403,17 @@ void GLVolume::render(bool with_outline)
if (!is_active) if (!is_active)
return; return;
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr)
return;
if (this->is_left_handed()) if (this->is_left_handed())
glFrontFace(GL_CW); glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK)); glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix()); if (with_outline) {
// Error: not supported!
throw Slic3r::InvalidArgument("Render GLVolume with outline is not supported");
}
// BBS: add logic for mmu segmentation rendering // BBS: add logic for mmu segmentation rendering
auto render_body = [&]() { auto render_body = [&]() {
@ -446,7 +458,6 @@ void GLVolume::render(bool with_outline)
for (int index = 0; index < colors.size(); index++) for (int index = 0; index < colors.size(); index++)
colors[index].a(render_color.a()); colors[index].a(render_color.a());
} }
glsafe(::glMultMatrixd(world_matrix().data()));
for (int idx = 0; idx < mmuseg_models.size(); idx++) { for (int idx = 0; idx < mmuseg_models.size(); idx++) {
GUI::GLModel &m = mmuseg_models[idx]; GUI::GLModel &m = mmuseg_models[idx];
if (m.is_empty()) if (m.is_empty())
@ -489,7 +500,6 @@ void GLVolume::render(bool with_outline)
} }
} }
else { else {
glsafe(::glMultMatrixd(world_matrix().data()));
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
@ -498,7 +508,6 @@ void GLVolume::render(bool with_outline)
}; };
//BBS: add logic of outline rendering //BBS: add logic of outline rendering
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader; //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader;
if (with_outline && shader != nullptr) if (with_outline && shader != nullptr)
{ {
@ -629,7 +638,6 @@ void GLVolume::render(bool with_outline)
render_body(); render_body();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__; //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__;
} }
glsafe(::glPopMatrix());
if (this->is_left_handed()) if (this->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
} }
@ -640,7 +648,6 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj
if (this->is_left_handed()) if (this->is_left_handed())
glFrontFace(GL_CW); glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK)); glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix());
bool color_volume = false; bool color_volume = false;
ModelObject* model_object = nullptr; ModelObject* model_object = nullptr;
@ -704,16 +711,12 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj
else else
m.render(this->tverts_range); m.render(this->tverts_range);
} }
} } else {
else {
glsafe(::glMultMatrixd(world_matrix().data()));
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(::glPopMatrix());
if (this->is_left_handed()) if (this->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
} }
@ -997,8 +1000,8 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
} }
//BBS: add outline drawing logic //BBS: add outline drawing logic
void GLVolumeCollection::render( void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d &view_matrix, std::function<bool(const GLVolume &)> filter_func, bool with_outline) const std::function<bool(const GLVolume&)> filter_func, bool with_outline) 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())
@ -1008,8 +1011,9 @@ void GLVolumeCollection::render(
if (shader == nullptr) if (shader == nullptr)
return; return;
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat_attr");
GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat"); GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat_attr");
assert(boost::algorithm::iends_with(shader->get_name(), "_attr"));
if (type == ERenderType::Transparent) { if (type == ERenderType::Transparent) {
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
@ -1049,9 +1053,6 @@ void GLVolumeCollection::render(
} }
shader->start_using(); shader->start_using();
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
if (!volume.first->model.is_initialized()) if (!volume.first->model.is_initialized())
shader->set_uniform("uniform_color", volume.first->render_color); shader->set_uniform("uniform_color", volume.first->render_color);
shader->set_uniform("z_range", m_z_range, 2); shader->set_uniform("z_range", m_z_range, 2);
@ -1096,6 +1097,10 @@ void GLVolumeCollection::render(
glcheck(); glcheck();
volume.first->model.set_color(volume.first->render_color); volume.first->model.set_color(volume.first->render_color);
const Transform3d matrix = view_matrix * volume.first->world_matrix();
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
//BBS: add outline related logic //BBS: add outline related logic
volume.first->render(with_outline && volume.first->selected); volume.first->render(with_outline && volume.first->selected);
@ -1106,9 +1111,6 @@ void GLVolumeCollection::render(
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
} }
if (m_show_sinking_contours) { if (m_show_sinking_contours) {
@ -1462,8 +1464,8 @@ static void thick_lines_to_geometry(
if (!is_first && bottom_z_different) { if (!is_first && bottom_z_different) {
// Found a change of the layer thickness -> Add a cap at the end of the previous segment. // Found a change of the layer thickness -> Add a cap at the end of the previous segment.
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]); geometry.add_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]);
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]); geometry.add_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]);
} }
// Share top / bottom vertices if possible. // Share top / bottom vertices if possible.
@ -1513,13 +1515,13 @@ static void thick_lines_to_geometry(
geometry.add_vertex(Vec3f(a2.x(), a2.y(), middle_z), Vec3f(-xy_right_normal.x(), -xy_right_normal.y(), 0.0f)); geometry.add_vertex(Vec3f(a2.x(), a2.y(), middle_z), Vec3f(-xy_right_normal.x(), -xy_right_normal.y(), 0.0f));
if (cross2(v_prev, v) > 0.0) { if (cross2(v_prev, v) > 0.0) {
// Right turn. Fill in the right turn wedge. // Right turn. Fill in the right turn wedge.
geometry.add_uint_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]); geometry.add_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]);
geometry.add_uint_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]); geometry.add_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]);
} }
else { else {
// Left turn. Fill in the left turn wedge. // Left turn. Fill in the left turn wedge.
geometry.add_uint_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]); geometry.add_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]);
geometry.add_uint_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]); geometry.add_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]);
} }
} }
} }
@ -1541,11 +1543,11 @@ static void thick_lines_to_geometry(
// Replace the left / right vertex indices to point to the start of the loop. // Replace the left / right vertex indices to point to the start of the loop.
const size_t indices_count = geometry.indices_count(); const size_t indices_count = geometry.indices_count();
for (size_t u = indices_count - 24; u < indices_count; ++u) { for (size_t u = indices_count - 24; u < indices_count; ++u) {
const unsigned int id = geometry.extract_uint_index(u); const unsigned int id = geometry.extract_index(u);
if (id == (unsigned int)idx_prev[Left]) if (id == (unsigned int)idx_prev[Left])
geometry.set_uint_index(u, (unsigned int)idx_initial[Left]); geometry.set_index(u, (unsigned int)idx_initial[Left]);
else if (id == (unsigned int)idx_prev[Right]) else if (id == (unsigned int)idx_prev[Right])
geometry.set_uint_index(u, (unsigned int)idx_initial[Right]); geometry.set_index(u, (unsigned int)idx_initial[Right]);
} }
} }
} }
@ -1582,36 +1584,36 @@ static void thick_lines_to_geometry(
if (bottom_z_different && (closed || (!is_first && !is_last))) { if (bottom_z_different && (closed || (!is_first && !is_last))) {
// Found a change of the layer thickness -> Add a cap at the beginning of this segment. // Found a change of the layer thickness -> Add a cap at the beginning of this segment.
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]); geometry.add_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]);
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]); geometry.add_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]);
} }
if (!closed) { if (!closed) {
// Terminate open paths with caps. // Terminate open paths with caps.
if (is_first) { if (is_first) {
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]); geometry.add_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]);
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]); geometry.add_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]);
} }
// We don't use 'else' because both cases are true if we have only one line. // We don't use 'else' because both cases are true if we have only one line.
if (is_last) { if (is_last) {
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]); geometry.add_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]);
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]); geometry.add_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]);
} }
} }
// Add quads for a straight hollow tube-like segment. // Add quads for a straight hollow tube-like segment.
// bottom-right face // bottom-right face
geometry.add_uint_triangle(idx_a[Bottom], idx_b[Bottom], idx_b[Right]); geometry.add_triangle(idx_a[Bottom], idx_b[Bottom], idx_b[Right]);
geometry.add_uint_triangle(idx_a[Bottom], idx_b[Right], idx_a[Right]); geometry.add_triangle(idx_a[Bottom], idx_b[Right], idx_a[Right]);
// top-right face // top-right face
geometry.add_uint_triangle(idx_a[Right], idx_b[Right], idx_b[Top]); geometry.add_triangle(idx_a[Right], idx_b[Right], idx_b[Top]);
geometry.add_uint_triangle(idx_a[Right], idx_b[Top], idx_a[Top]); geometry.add_triangle(idx_a[Right], idx_b[Top], idx_a[Top]);
// top-left face // top-left face
geometry.add_uint_triangle(idx_a[Top], idx_b[Top], idx_b[Left]); geometry.add_triangle(idx_a[Top], idx_b[Top], idx_b[Left]);
geometry.add_uint_triangle(idx_a[Top], idx_b[Left], idx_a[Left]); geometry.add_triangle(idx_a[Top], idx_b[Left], idx_a[Left]);
// bottom-left face // bottom-left face
geometry.add_uint_triangle(idx_a[Left], idx_b[Left], idx_b[Bottom]); geometry.add_triangle(idx_a[Left], idx_b[Left], idx_b[Bottom]);
geometry.add_uint_triangle(idx_a[Left], idx_b[Bottom], idx_a[Bottom]); geometry.add_triangle(idx_a[Left], idx_b[Bottom], idx_a[Bottom]);
} }
} }
@ -1751,13 +1753,13 @@ static void thick_lines_to_geometry(
if (is_right_turn) { if (is_right_turn) {
// Right turn. Fill in the right turn wedge. // Right turn. Fill in the right turn wedge.
geometry.add_uint_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]); geometry.add_triangle(idx_prev[Right], idx_a[Right], idx_prev[Top]);
geometry.add_uint_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]); geometry.add_triangle(idx_prev[Right], idx_prev[Bottom], idx_a[Right]);
} }
else { else {
// Left turn. Fill in the left turn wedge. // Left turn. Fill in the left turn wedge.
geometry.add_uint_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]); geometry.add_triangle(idx_prev[Left], idx_prev[Top], idx_a[Left]);
geometry.add_uint_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]); geometry.add_triangle(idx_prev[Left], idx_a[Left], idx_prev[Bottom]);
} }
} }
else { else {
@ -1776,11 +1778,11 @@ static void thick_lines_to_geometry(
// Replace the left / right vertex indices to point to the start of the loop. // Replace the left / right vertex indices to point to the start of the loop.
const size_t indices_count = geometry.indices_count(); const size_t indices_count = geometry.indices_count();
for (size_t u = indices_count - 24; u < indices_count; ++u) { for (size_t u = indices_count - 24; u < indices_count; ++u) {
const unsigned int id = geometry.extract_uint_index(u); const unsigned int id = geometry.extract_index(u);
if (id == (unsigned int)idx_prev[Left]) if (id == (unsigned int)idx_prev[Left])
geometry.set_uint_index(u, (unsigned int)idx_initial[Left]); geometry.set_index(u, (unsigned int)idx_initial[Left]);
else if (id == (unsigned int)idx_prev[Right]) else if (id == (unsigned int)idx_prev[Right])
geometry.set_uint_index(u, (unsigned int)idx_initial[Right]); geometry.set_index(u, (unsigned int)idx_initial[Right]);
} }
} }
@ -1819,30 +1821,30 @@ static void thick_lines_to_geometry(
if (!closed) { if (!closed) {
// Terminate open paths with caps. // Terminate open paths with caps.
if (i == 0) { if (i == 0) {
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]); geometry.add_triangle(idx_a[Bottom], idx_a[Right], idx_a[Top]);
geometry.add_uint_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]); geometry.add_triangle(idx_a[Bottom], idx_a[Top], idx_a[Left]);
} }
// We don't use 'else' because both cases are true if we have only one line. // We don't use 'else' because both cases are true if we have only one line.
if (i + 1 == lines.size()) { if (i + 1 == lines.size()) {
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]); geometry.add_triangle(idx_b[Bottom], idx_b[Left], idx_b[Top]);
geometry.add_uint_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]); geometry.add_triangle(idx_b[Bottom], idx_b[Top], idx_b[Right]);
} }
} }
// Add quads for a straight hollow tube-like segment. // Add quads for a straight hollow tube-like segment.
// bottom-right face // bottom-right face
geometry.add_uint_triangle(idx_a[Bottom], idx_b[Bottom], idx_b[Right]); geometry.add_triangle(idx_a[Bottom], idx_b[Bottom], idx_b[Right]);
geometry.add_uint_triangle(idx_a[Bottom], idx_b[Right], idx_a[Right]); geometry.add_triangle(idx_a[Bottom], idx_b[Right], idx_a[Right]);
// top-right face // top-right face
geometry.add_uint_triangle(idx_a[Right], idx_b[Right], idx_b[Top]); geometry.add_triangle(idx_a[Right], idx_b[Right], idx_b[Top]);
geometry.add_uint_triangle(idx_a[Right], idx_b[Top], idx_a[Top]); geometry.add_triangle(idx_a[Right], idx_b[Top], idx_a[Top]);
// top-left face // top-left face
geometry.add_uint_triangle(idx_a[Top], idx_b[Top], idx_b[Left]); geometry.add_triangle(idx_a[Top], idx_b[Top], idx_b[Left]);
geometry.add_uint_triangle(idx_a[Top], idx_b[Left], idx_a[Left]); geometry.add_triangle(idx_a[Top], idx_b[Left], idx_a[Left]);
// bottom-left face // bottom-left face
geometry.add_uint_triangle(idx_a[Left], idx_b[Left], idx_b[Bottom]); geometry.add_triangle(idx_a[Left], idx_b[Left], idx_b[Bottom]);
geometry.add_uint_triangle(idx_a[Left], idx_b[Bottom], idx_a[Bottom]); geometry.add_triangle(idx_a[Left], idx_b[Bottom], idx_a[Bottom]);
} }
} }

View file

@ -446,11 +446,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, void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
bool disable_cullface, std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(), bool with_outline = true) const;
const Transform3d & view_matrix,
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
bool with_outline = true) 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(); }

View file

@ -92,7 +92,6 @@ public:
const std::array<int, 4>& get_viewport() const { return m_viewport; } const std::array<int, 4>& get_viewport() const { return m_viewport; }
const Transform3d& get_view_matrix() const { return m_view_matrix; } const Transform3d& get_view_matrix() const { return m_view_matrix; }
const Transform3d& get_projection_matrix() const { return m_projection_matrix; } const Transform3d& get_projection_matrix() const { return m_projection_matrix; }
Transform3d get_projection_view_matrix() const { return m_projection_matrix * m_view_matrix; }
//BBS //BBS
const Eigen::Quaterniond& get_view_rotation() const {return m_view_rotation; } const Eigen::Quaterniond& get_view_rotation() const {return m_view_rotation; }

View file

@ -307,7 +307,7 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
if (!m_visible) if (!m_visible)
return; return;
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -317,13 +317,14 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.0f); shader->set_uniform("emission_factor", 0.0f);
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixf(m_world_transform.data())); const Transform3d matrix = camera.get_view_matrix() * m_world_transform.cast<double>();
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_model.render(); m_model.render();
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
@ -787,7 +788,7 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle)
case EMoveType::Seam: { case EMoveType::Seam: {
// if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { // if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
// buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; // buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel;
// buffer.shader = "gouraud_light_instanced"; // buffer.shader = "gouraud_light_instanced_attr";
// buffer.model.model.init_from(diamond(16)); // buffer.model.model.init_from(diamond(16));
// buffer.model.color = option_color(type); // buffer.model.color = option_color(type);
// buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; // buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel;
@ -798,7 +799,7 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle)
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
buffer.shader = "gouraud_light"; buffer.shader = "gouraud_light_attr";
buffer.model.data = diamond(16); buffer.model.data = diamond(16);
buffer.model.color = option_color(type); buffer.model.color = option_color(type);
@ -810,13 +811,13 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle)
case EMoveType::Extrude: { case EMoveType::Extrude: {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
buffer.shader = "gouraud_light"; buffer.shader = "gouraud_light_attr";
break; break;
} }
case EMoveType::Travel: { case EMoveType::Travel: {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.vertices.format = VBuffer::EFormat::Position;
buffer.shader = "toolpaths_lines"; buffer.shader = "flat_attr";
break; break;
} }
} }
@ -1324,7 +1325,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
assert(!path.sizes.empty()); assert(!path.sizes.empty());
assert(!path.offsets.empty()); assert(!path.offsets.empty());
glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); shader.set_uniform(uniform_color, path.color);
glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_triangles_calls_count; ++m_statistics.gl_multi_triangles_calls_count;
@ -1359,7 +1360,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) {
#else #else
auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader, int position_id, int normal_id) {
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
struct Range struct Range
@ -1375,12 +1376,16 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
const IBuffer& i_buffer = buffer.indices[j]; const IBuffer& i_buffer = buffer.indices[j];
buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); if (position_id != -1) {
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes()));
glsafe(::glEnableVertexAttribArray(position_id));
}
bool has_normals = buffer.vertices.normal_size_floats() > 0; bool has_normals = buffer.vertices.normal_size_floats() > 0;
if (has_normals) { if (has_normals) {
glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); if (normal_id != -1) {
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes()));
glsafe(::glEnableVertexAttribArray(normal_id));
}
} }
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
@ -1403,11 +1408,11 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
} }
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (has_normals) if (normal_id != -1)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1)
glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
buffer_range.first = buffer_range.last; buffer_range.first = buffer_range.last;
@ -1423,10 +1428,15 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
if (!buffer.visible || !buffer.has_data()) if (!buffer.visible || !buffer.has_data())
continue; continue;
GLShaderProgram* shader = opengl_manager.get_shader("cali"); GLShaderProgram* shader = opengl_manager.get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
int position_id = shader->get_attrib_location("v_position");
int normal_id = shader->get_attrib_location("v_normal");
if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) {
//shader->set_uniform("emission_factor", 0.25f); //shader->set_uniform("emission_factor", 0.25f);
render_as_instanced_model(buffer, *shader); render_as_instanced_model(buffer, *shader);
@ -1434,7 +1444,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
} }
else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) {
//shader->set_uniform("emission_factor", 0.25f); //shader->set_uniform("emission_factor", 0.25f);
render_as_batched_model(buffer, *shader); render_as_batched_model(buffer, *shader, position_id, normal_id);
//shader->set_uniform("emission_factor", 0.0f); //shader->set_uniform("emission_factor", 0.0f);
} }
else { else {
@ -1452,12 +1462,16 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
continue; continue;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); if (position_id != -1) {
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes()));
glsafe(::glEnableVertexAttribArray(position_id));
}
bool has_normals = false;// buffer.vertices.normal_size_floats() > 0; bool has_normals = false;// buffer.vertices.normal_size_floats() > 0;
if (has_normals) { if (has_normals) {
glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); if (normal_id != -1) {
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes()));
glsafe(::glEnableVertexAttribArray(normal_id));
}
} }
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
@ -1473,11 +1487,12 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai
} }
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (normal_id != -1)
glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1)
glsafe(::glDisableVertexAttribArray(position_id));
if (has_normals)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
} }
@ -2032,15 +2047,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
// format data into the buffers to be rendered as lines // format data into the buffers to be rendered as lines
auto add_vertices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, VertexBuffer& vertices) { auto add_vertices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, VertexBuffer& vertices) {
auto add_vertex = [&vertices](const Vec3f& position, const Vec3f& normal) { auto add_vertex = [&vertices](const Vec3f& position) {
// add position // add position
vertices.push_back(position.x()); vertices.push_back(position.x());
vertices.push_back(position.y()); vertices.push_back(position.y());
vertices.push_back(position.z()); vertices.push_back(position.z());
// add normal
vertices.push_back(normal.x());
vertices.push_back(normal.y());
vertices.push_back(normal.z());
}; };
// x component of the normal to the current segment (the normal is parallel to the XY plane) // x component of the normal to the current segment (the normal is parallel to the XY plane)
//BBS: Has modified a lot for this function to support arc move //BBS: Has modified a lot for this function to support arc move
@ -2048,13 +2059,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
for (size_t i = 0; i < loop_num + 1; i++) { for (size_t i = 0; i < loop_num + 1; i++) {
const Vec3f &previous = (i == 0? prev.position : curr.interpolation_points[i-1]); const Vec3f &previous = (i == 0? prev.position : curr.interpolation_points[i-1]);
const Vec3f &current = (i == loop_num? curr.position : curr.interpolation_points[i]); const Vec3f &current = (i == loop_num? curr.position : curr.interpolation_points[i]);
const Vec3f dir = (current - previous).normalized();
Vec3f normal(dir.y(), -dir.x(), 0.0);
normal.normalize();
// add previous vertex // add previous vertex
add_vertex(previous, normal); add_vertex(previous);
// add current vertex // add current vertex
add_vertex(current, normal); add_vertex(current);
} }
}; };
//BBS: modify a lot to support arc travel //BBS: modify a lot to support arc travel
@ -2325,7 +2333,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
auto add_indices_as_model_batch = [](const GLModel::Geometry& data, IndexBuffer& indices, IBufferType base_index) { auto add_indices_as_model_batch = [](const GLModel::Geometry& data, IndexBuffer& indices, IBufferType base_index) {
const size_t indices_count = data.indices_count(); const size_t indices_count = data.indices_count();
for (size_t i = 0; i < indices_count; ++i) { for (size_t i = 0; i < indices_count; ++i) {
indices.push_back(static_cast<IBufferType>(data.extract_ushort_index(i) + base_index)); indices.push_back(static_cast<IBufferType>(data.extract_index(i) + base_index));
} }
}; };
@ -3765,15 +3773,14 @@ m_no_render_path = false;
void GCodeViewer::render_toolpaths() void GCodeViewer::render_toolpaths()
{ {
#if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS #if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
float point_size = 20.0f; const float point_size = 20.0f;
#else #else
float point_size = 0.8f; const float point_size = 0.8f;
#endif // ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS #endif // ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS
std::array<float, 4> light_intensity = { 0.25f, 0.70f, 0.75f, 0.75f };
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
double zoom = camera.get_zoom(); const double zoom = camera.get_zoom();
const std::array<int, 4>& viewport = camera.get_viewport(); const std::array<int, 4>& viewport = camera.get_viewport();
float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) : const float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast<float>(viewport[3]) / (2.0f * static_cast<float>(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) :
static_cast<float>(viewport[3]) * 0.0005; static_cast<float>(viewport[3]) * 0.0005;
auto shader_init_as_points = [zoom, point_size, near_plane_height](GLShaderProgram& shader) { auto shader_init_as_points = [zoom, point_size, near_plane_height](GLShaderProgram& shader) {
@ -3793,7 +3800,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
this this
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { ](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE));
glsafe(::glEnable(GL_POINT_SPRITE)); glsafe(::glEnable(GL_POINT_SPRITE));
@ -3802,7 +3809,7 @@ void GCodeViewer::render_toolpaths()
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
assert(! path.sizes.empty()); assert(! path.sizes.empty());
assert(! path.offsets.empty()); assert(! path.offsets.empty());
glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); shader.set_uniform(uniform_color, path.color);
glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_points_calls_count; ++m_statistics.gl_multi_points_calls_count;
@ -3813,20 +3820,17 @@ void GCodeViewer::render_toolpaths()
glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE));
}; };
auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) {
shader.set_uniform("light_intensity", light_intensity);
};
auto render_as_lines = [ auto render_as_lines = [
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
this this
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { ](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it; const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
assert(! path.sizes.empty()); assert(! path.sizes.empty());
assert(! path.offsets.empty()); assert(! path.offsets.empty());
glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); shader.set_uniform(uniform_color, path.color);
glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_lines_calls_count; ++m_statistics.gl_multi_lines_calls_count;
@ -3838,13 +3842,13 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
this this
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { ](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it; const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
assert(! path.sizes.empty()); assert(! path.sizes.empty());
assert(! path.offsets.empty()); assert(! path.offsets.empty());
glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); shader.set_uniform(uniform_color, path.color);
glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_multi_triangles_calls_count; ++m_statistics.gl_multi_triangles_calls_count;
@ -3877,9 +3881,9 @@ void GCodeViewer::render_toolpaths()
}; };
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader, int position_id, int normal_id) {
#else #else
auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader, int position_id, int normal_id) {
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
struct Range struct Range
@ -3889,30 +3893,34 @@ void GCodeViewer::render_toolpaths()
bool intersects(const Range& other) const { return (other.last < first || other.first > last) ? false : true; } bool intersects(const Range& other) const { return (other.last < first || other.first > last) ? false : true; }
}; };
Range buffer_range = { 0, 0 }; Range buffer_range = { 0, 0 };
size_t indices_per_instance = buffer.model.data.indices_count(); const size_t indices_per_instance = buffer.model.data.indices_count();
for (size_t j = 0; j < buffer.indices.size(); ++j) { for (size_t j = 0; j < buffer.indices.size(); ++j) {
const IBuffer& i_buffer = buffer.indices[j]; const IBuffer& i_buffer = buffer.indices[j];
buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); if (position_id != -1) {
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes()));
bool has_normals = buffer.vertices.normal_size_floats() > 0; glsafe(::glEnableVertexAttribArray(position_id));
}
const bool has_normals = buffer.vertices.normal_size_floats() > 0;
if (has_normals) { if (has_normals) {
glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); if (normal_id != -1) {
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes()));
glsafe(::glEnableVertexAttribArray(normal_id));
}
} }
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
for (auto& range : buffer.model.instances.render_ranges.ranges) { for (auto& range : buffer.model.instances.render_ranges.ranges) {
Range range_range = { range.offset, range.offset + range.count }; const Range range_range = { range.offset, range.offset + range.count };
if (range_range.intersects(buffer_range)) { if (range_range.intersects(buffer_range)) {
shader.set_uniform("uniform_color", range.color); shader.set_uniform("uniform_color", range.color);
unsigned int offset = (range_range.first > buffer_range.first) ? range_range.first - buffer_range.first : 0; const unsigned int offset = (range_range.first > buffer_range.first) ? range_range.first - buffer_range.first : 0;
size_t offset_bytes = static_cast<size_t>(offset) * indices_per_instance * sizeof(IBufferType); const size_t offset_bytes = static_cast<size_t>(offset) * indices_per_instance * sizeof(IBufferType);
Range render_range = { std::max(range_range.first, buffer_range.first), std::min(range_range.last, buffer_range.last) }; const Range render_range = { std::max(range_range.first, buffer_range.first), std::min(range_range.last, buffer_range.last) };
size_t count = static_cast<size_t>(render_range.last - render_range.first) * indices_per_instance; const size_t count = static_cast<size_t>(render_range.last - render_range.first) * indices_per_instance;
if (count > 0) { if (count > 0) {
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)count, GL_UNSIGNED_SHORT, (const void*)offset_bytes)); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)count, GL_UNSIGNED_SHORT, (const void*)offset_bytes));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
@ -3924,10 +3932,10 @@ void GCodeViewer::render_toolpaths()
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (has_normals) if (normal_id != -1)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1)
glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
buffer_range.first = buffer_range.last; buffer_range.first = buffer_range.last;
@ -3938,9 +3946,8 @@ void GCodeViewer::render_toolpaths()
return (zoom < 5.0) ? 1.0 : (1.0 + 5.0 * (zoom - 5.0) / (100.0 - 5.0)); return (zoom < 5.0) ? 1.0 : (1.0 + 5.0 * (zoom - 5.0) / (100.0 - 5.0));
}; };
unsigned char begin_id = buffer_id(EMoveType::Retract); const unsigned char begin_id = buffer_id(EMoveType::Retract);
unsigned char end_id = buffer_id(EMoveType::Count); const unsigned char end_id = buffer_id(EMoveType::Count);
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":begin_id %1%, end_id %2% ")%(int)begin_id %(int)end_id;
for (unsigned char i = begin_id; i < end_id; ++i) { for (unsigned char i = begin_id; i < end_id; ++i) {
TBuffer& buffer = m_buffers[i]; TBuffer& buffer = m_buffers[i];
@ -3948,80 +3955,90 @@ void GCodeViewer::render_toolpaths()
continue; continue;
GLShaderProgram* shader = wxGetApp().get_shader(buffer.shader.c_str()); GLShaderProgram* shader = wxGetApp().get_shader(buffer.shader.c_str());
if (shader != nullptr) { if (shader == nullptr)
shader->start_using(); continue;
if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { shader->start_using();
shader->set_uniform("emission_factor", 0.25f);
render_as_instanced_model(buffer, *shader);
shader->set_uniform("emission_factor", 0.0f);
}
else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) {
shader->set_uniform("emission_factor", 0.25f);
render_as_batched_model(buffer, *shader);
shader->set_uniform("emission_factor", 0.0f);
}
else {
switch (buffer.render_primitive_type) {
case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break;
case TBuffer::ERenderPrimitiveType::Line: shader_init_as_lines(*shader); break;
default: break;
}
int uniform_color = shader->get_uniform_location("uniform_color");
auto it_path = buffer.render_paths.rbegin();
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":buffer indices size %1%, render_path size %2% ")%buffer.indices.size() %buffer.render_paths.size();
unsigned int indices_count = static_cast<unsigned int>(buffer.indices.size());
for (unsigned int index = 0; index < indices_count; ++index) {
unsigned int ibuffer_id = indices_count - index - 1;
const IBuffer& i_buffer = buffer.indices[ibuffer_id];
// Skip all paths with ibuffer_id < ibuffer_id.
for (; it_path != buffer.render_paths.rend() && it_path->ibuffer_id > ibuffer_id; ++ it_path) ;
if (it_path == buffer.render_paths.rend() || it_path->ibuffer_id < ibuffer_id)
// Not found. This shall not happen.
continue;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); int position_id = -1;
glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); int normal_id = -1;
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); const Transform3d& view_matrix = camera.get_view_matrix();
bool has_normals = buffer.vertices.normal_size_floats() > 0; shader->set_uniform("view_model_matrix", view_matrix);
if (has_normals) { shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
}
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); position_id = shader->get_attrib_location("v_position");
normal_id = shader->get_attrib_location("v_normal");
// Render all elements with it_path->ibuffer_id == ibuffer_id, possible with varying colors. if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) {
switch (buffer.render_primitive_type) shader->set_uniform("emission_factor", 0.25f);
{ render_as_instanced_model(buffer, *shader);
case TBuffer::ERenderPrimitiveType::Point: { shader->set_uniform("emission_factor", 0.0f);
render_as_points(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
render_as_triangles(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
default: { break; }
}
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (has_normals)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
}
shader->stop_using();
} }
else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) {
shader->set_uniform("emission_factor", 0.25f);
render_as_batched_model(buffer, *shader, position_id, normal_id);
shader->set_uniform("emission_factor", 0.0f);
}
else {
if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Point)
shader_init_as_points(*shader);
const int uniform_color = shader->get_uniform_location("uniform_color");
auto it_path = buffer.render_paths.begin();
for (unsigned int ibuffer_id = 0; ibuffer_id < static_cast<unsigned int>(buffer.indices.size()); ++ibuffer_id) {
const IBuffer& i_buffer = buffer.indices[ibuffer_id];
// Skip all paths with ibuffer_id < ibuffer_id.
for (; it_path != buffer.render_paths.end() && it_path->ibuffer_id < ibuffer_id; ++it_path);
if (it_path == buffer.render_paths.end() || it_path->ibuffer_id > ibuffer_id)
// Not found. This shall not happen.
continue;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes()));
glsafe(::glEnableVertexAttribArray(position_id));
}
const bool has_normals = buffer.vertices.normal_size_floats() > 0;
if (has_normals) {
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes()));
glsafe(::glEnableVertexAttribArray(normal_id));
}
}
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
// Render all elements with it_path->ibuffer_id == ibuffer_id, possible with varying colors.
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
render_as_points(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
render_as_lines(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
render_as_triangles(it_path, buffer.render_paths.end(), *shader, uniform_color);
break;
}
default: { break; }
}
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (normal_id != -1)
glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1)
glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
}
shader->stop_using();
} }
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
@ -4030,37 +4047,55 @@ void GCodeViewer::render_toolpaths()
auto render_sequential_range_cap = [] auto render_sequential_range_cap = []
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
(const SequentialRangeCap& cap) { (const SequentialRangeCap& cap) {
GLShaderProgram* shader = wxGetApp().get_shader(cap.buffer->shader.c_str()); const TBuffer* buffer = cap.buffer;
if (shader != nullptr) { GLShaderProgram* shader = wxGetApp().get_shader(buffer->shader.c_str());
shader->start_using(); if (shader == nullptr)
return;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, cap.vbo)); shader->start_using();
glsafe(::glVertexPointer(cap.buffer->vertices.position_size_floats(), GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.position_offset_bytes()));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); int position_id = -1;
bool has_normals = cap.buffer->vertices.normal_size_floats() > 0; int normal_id = -1;
if (has_normals) { const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glNormalPointer(GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.normal_offset_bytes())); const Transform3d& view_matrix = camera.get_view_matrix();
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
position_id = shader->get_attrib_location("v_position");
normal_id = shader->get_attrib_location("v_normal");
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, cap.vbo));
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, buffer->vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer->vertices.vertex_size_bytes(), (const void*)buffer->vertices.position_offset_bytes()));
glsafe(::glEnableVertexAttribArray(position_id));
}
const bool has_normals = buffer->vertices.normal_size_floats() > 0;
if (has_normals) {
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, buffer->vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer->vertices.vertex_size_bytes(), (const void*)buffer->vertices.normal_offset_bytes()));
glsafe(::glEnableVertexAttribArray(normal_id));
} }
}
shader->set_uniform("uniform_color", cap.color); shader->set_uniform("uniform_color", cap.color);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)cap.indices_count(), GL_UNSIGNED_SHORT, nullptr)); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)cap.indices_count(), GL_UNSIGNED_SHORT, nullptr));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
++m_statistics.gl_triangles_calls_count; ++m_statistics.gl_triangles_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
if (has_normals) if (normal_id != -1)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1)
glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
shader->stop_using(); shader->stop_using();
}
}; };
for (unsigned int i = 0; i < 2; ++i) { for (unsigned int i = 0; i < 2; ++i) {
@ -4076,7 +4111,7 @@ void GCodeViewer::render_shells()
//if (!m_shells.visible || m_shells.volumes.empty()) //if (!m_shells.visible || m_shells.volumes.empty())
return; return;
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -4084,8 +4119,9 @@ void GCodeViewer::render_shells()
// glsafe(::glDepthMask(GL_FALSE)); // glsafe(::glDepthMask(GL_FALSE));
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
//BBS: reopen cul faces //BBS: reopen cul faces
m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix()); m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, camera.get_view_matrix(), camera.get_projection_matrix());
shader->stop_using(); shader->stop_using();
// glsafe(::glDepthMask(GL_TRUE)); // glsafe(::glDepthMask(GL_TRUE));

View file

@ -14,22 +14,16 @@
#include "libslic3r/Technologies.hpp" #include "libslic3r/Technologies.hpp"
#include "libslic3r/Tesselate.hpp" #include "libslic3r/Tesselate.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/3DBed.hpp" #include "3DBed.hpp"
#include "slic3r/GUI/3DScene.hpp" #include "3DScene.hpp"
#include "slic3r/GUI/BackgroundSlicingProcess.hpp" #include "BackgroundSlicingProcess.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "GLShader.hpp"
#include "slic3r/GUI/GLShader.hpp" #include "GUI.hpp"
#include "slic3r/GUI/GUI.hpp" #include "Tab.hpp"
#include "slic3r/GUI/Tab.hpp" #include "GUI_Preview.hpp"
#include "slic3r/GUI/GUI_Preview.hpp" #include "OpenGLManager.hpp"
#include "slic3r/GUI/OpenGLManager.hpp" #include "Plater.hpp"
#include "slic3r/GUI/Plater.hpp" #include "MainFrame.hpp"
#include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp"
#include "slic3r/GUI/BitmapCache.hpp"
#include "slic3r/Utils/MacDarkMode.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "GUI_ObjectList.hpp" #include "GUI_ObjectList.hpp"
#include "GUI_Colors.hpp" #include "GUI_Colors.hpp"
@ -38,6 +32,9 @@
#include "NotificationManager.hpp" #include "NotificationManager.hpp"
#include "format.hpp" #include "format.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <slic3r/GUI/GUI_Utils.hpp> #include <slic3r/GUI/GUI_Utils.hpp>
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
@ -166,7 +163,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model& model, int object_id)
bool GLCanvas3D::LayersEditing::is_allowed() const bool GLCanvas3D::LayersEditing::is_allowed() const
{ {
return wxGetApp().get_shader("variable_layer_height") != nullptr && m_z_texture_id > 0; return wxGetApp().get_shader("variable_layer_height_attr") != nullptr && m_z_texture_id > 0;
} }
bool GLCanvas3D::LayersEditing::is_enabled() const bool GLCanvas3D::LayersEditing::is_enabled() const
@ -220,9 +217,8 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
ImGuiWrapper& imgui = *wxGetApp().imgui(); ImGuiWrapper& imgui = *wxGetApp().imgui();
const Size& cnv_size = canvas.get_canvas_size(); const Size& cnv_size = canvas.get_canvas_size();
float zoom = (float)wxGetApp().plater()->get_camera().get_zoom();
float left_pos = canvas.m_main_toolbar.get_item("layersediting")->render_left_pos; float left_pos = canvas.m_main_toolbar.get_item("layersediting")->render_left_pos;
const float x = 0.5 * cnv_size.get_width() + left_pos * zoom; const float x = (1 + left_pos) * cnv_size.get_width() / 2;
imgui.set_next_window_pos(x, canvas.m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f); imgui.set_next_window_pos(x, canvas.m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f);
imgui.push_toolbar_style(canvas.get_scale()); imgui.push_toolbar_style(canvas.get_scale());
@ -322,12 +318,8 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas)
{ {
render_variable_layer_height_dialog(canvas); render_variable_layer_height_dialog(canvas);
const Rect& bar_rect = get_bar_rect_viewport(canvas); render_active_object_annotations(canvas);
m_profile.dirty = m_profile.old_bar_rect != bar_rect; render_profile(canvas);
render_active_object_annotations(canvas, bar_rect);
render_profile(bar_rect);
m_profile.old_bar_rect = bar_rect;
m_profile.dirty = false;
} }
float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas) float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas)
@ -361,18 +353,9 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_screen(const GLCanvas3D& canvas)
return { w - thickness_bar_width(canvas), 0.0f, w, h }; return { w - thickness_bar_width(canvas), 0.0f, w, h };
} }
Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas)
{
const Size& cnv_size = canvas.get_canvas_size();
float half_w = 0.5f * (float)cnv_size.get_width();
float half_h = 0.5f * (float)cnv_size.get_height();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
return { (half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom };
}
bool GLCanvas3D::LayersEditing::is_initialized() const bool GLCanvas3D::LayersEditing::is_initialized() const
{ {
return wxGetApp().get_shader("variable_layer_height") != nullptr; return wxGetApp().get_shader("variable_layer_height_attr") != nullptr;
} }
std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) const std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) const
@ -401,12 +384,20 @@ std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) con
return ret; return ret;
} }
void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3D& canvas)
{ {
if (!m_enabled) if (!m_enabled)
return; return;
GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); const Size cnv_size = canvas.get_canvas_size();
const float cnv_width = (float)cnv_size.get_width();
const float cnv_height = (float)cnv_size.get_height();
if (cnv_width == 0.0f || cnv_height == 0.0f)
return;
const float cnv_inv_width = 1.0f / cnv_width;
GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -417,32 +408,36 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3
shader->set_uniform("z_cursor", m_object_max_z * this->get_cursor_z_relative(canvas)); shader->set_uniform("z_cursor", m_object_max_z * this->get_cursor_z_relative(canvas));
shader->set_uniform("z_cursor_band_width", band_width); shader->set_uniform("z_cursor_band_width", band_width);
shader->set_uniform("object_max_z", m_object_max_z); shader->set_uniform("object_max_z", m_object_max_z);
shader->set_uniform("view_model_matrix", Transform3d::Identity());
shader->set_uniform("projection_matrix", Transform3d::Identity());
shader->set_uniform("normal_matrix", (Matrix3d)Eigen::Matrix3d::Identity());
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id)); glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id));
// Render the color bar // Render the color bar
if (!m_profile.background.is_initialized() || m_profile.dirty) { if (!m_profile.background.is_initialized() || m_profile.old_canvas_width != cnv_width) {
m_profile.old_canvas_width = cnv_width;
m_profile.background.reset(); m_profile.background.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(6); init_data.reserve_indices(6);
// vertices // vertices
const float l = bar_rect.get_left(); const float l = 1.0f - 2.0f * THICKNESS_BAR_WIDTH * cnv_inv_width;
const float r = bar_rect.get_right(); const float r = 1.0f;
const float t = bar_rect.get_top(); const float t = 1.0f;
const float b = bar_rect.get_bottom(); const float b = -1.0f;
init_data.add_vertex(Vec2f(l, b), Vec2f(0.0f, 0.0f)); init_data.add_vertex(Vec2f(l, b), Vec2f(0.0f, 0.0f));
init_data.add_vertex(Vec2f(r, b), Vec2f(1.0f, 0.0f)); init_data.add_vertex(Vec2f(r, b), Vec2f(1.0f, 0.0f));
init_data.add_vertex(Vec2f(r, t), Vec2f(1.0f, 1.0f)); init_data.add_vertex(Vec2f(r, t), Vec2f(1.0f, 1.0f));
init_data.add_vertex(Vec2f(l, t), Vec2f(0.0f, 1.0f)); init_data.add_vertex(Vec2f(l, t), Vec2f(0.0f, 1.0f));
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
m_profile.background.init_from(std::move(init_data)); m_profile.background.init_from(std::move(init_data));
} }
@ -454,73 +449,82 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3
shader->stop_using(); shader->stop_using();
} }
void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) void GLCanvas3D::LayersEditing::render_profile(const GLCanvas3D& canvas)
{ {
if (!m_enabled) if (!m_enabled)
return; return;
//FIXME show some kind of legend. //FIXME show some kind of legend.
if (!m_slicing_parameters) if (!m_slicing_parameters)
return; return;
const Size cnv_size = canvas.get_canvas_size();
const float cnv_width = (float)cnv_size.get_width();
const float cnv_height = (float)cnv_size.get_height();
if (cnv_width == 0.0f || cnv_height == 0.0f)
return;
// Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region. // Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region.
const float scale_x = bar_rect.get_width() / float(1.12 * m_slicing_parameters->max_layer_height); const float scale_x = THICKNESS_BAR_WIDTH / float(1.12 * m_slicing_parameters->max_layer_height);
const float scale_y = bar_rect.get_height() / m_object_max_z; const float scale_y = cnv_height / m_object_max_z;
const float cnv_inv_width = 1.0f / cnv_width;
const float cnv_inv_height = 1.0f / cnv_height;
// Baseline // Baseline
if (!m_profile.baseline.is_initialized() || m_profile.dirty) { if (!m_profile.baseline.is_initialized() || m_profile.old_layer_height_profile != m_layer_height_profile) {
m_profile.baseline.reset(); m_profile.baseline.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P2};
init_data.color = ColorRGBA::BLACK(); init_data.color = ColorRGBA::BLACK();
init_data.reserve_vertices(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2); init_data.reserve_indices(2);
// vertices // vertices
const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; const float axis_x = 2.0f * ((cnv_width - THICKNESS_BAR_WIDTH + float(m_slicing_parameters->layer_height) * scale_x) * cnv_inv_width - 0.5f);
init_data.add_vertex(Vec2f(x, bar_rect.get_bottom())); init_data.add_vertex(Vec2f(axis_x, -1.0f));
init_data.add_vertex(Vec2f(x, bar_rect.get_top())); init_data.add_vertex(Vec2f(axis_x, 1.0f));
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_profile.baseline.init_from(std::move(init_data)); m_profile.baseline.init_from(std::move(init_data));
} }
if (!m_profile.profile.is_initialized() || m_profile.dirty || m_profile.old_layer_height_profile != m_layer_height_profile) { if (!m_profile.profile.is_initialized() || m_profile.old_layer_height_profile != m_layer_height_profile) {
m_profile.old_layer_height_profile = m_layer_height_profile; m_profile.old_layer_height_profile = m_layer_height_profile;
m_profile.profile.reset(); m_profile.profile.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::index_type(m_layer_height_profile.size() / 2) }; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P2 };
init_data.color = ColorRGBA::BLUE(); init_data.color = ColorRGBA::BLUE();
init_data.reserve_vertices(m_layer_height_profile.size() / 2); init_data.reserve_vertices(m_layer_height_profile.size() / 2);
init_data.reserve_indices(m_layer_height_profile.size() / 2); init_data.reserve_indices(m_layer_height_profile.size() / 2);
// vertices + indices // vertices + indices
for (unsigned int i = 0; i < (unsigned int)m_layer_height_profile.size(); i += 2) { 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, init_data.add_vertex(Vec2f(2.0f * ((cnv_width - THICKNESS_BAR_WIDTH + float(m_layer_height_profile[i + 1]) * scale_x) * cnv_inv_width - 0.5f),
bar_rect.get_bottom() + float(m_layer_height_profile[i]) * scale_y)); 2.0f * (float(m_layer_height_profile[i]) * scale_y * cnv_inv_height - 0.5)));
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_index(i / 2);
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)); m_profile.profile.init_from(std::move(init_data));
} }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("view_model_matrix", Transform3d::Identity());
shader->set_uniform("projection_matrix", Transform3d::Identity());
m_profile.baseline.render(); m_profile.baseline.render();
m_profile.profile.render(); m_profile.profile.render();
shader->stop_using(); shader->stop_using();
} }
} }
void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const GLVolumeCollection & volumes)//render volume and layer height texture (has mapping relation with each other) void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection& volumes)
{ {
assert(this->is_allowed()); assert(this->is_allowed());
assert(this->last_object_id != -1); assert(this->last_object_id != -1);
@ -530,7 +534,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const
if (current_shader != nullptr) if (current_shader != nullptr)
current_shader->stop_using(); current_shader->stop_using();
GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -544,6 +548,9 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const
shader->set_uniform("z_cursor", float(m_object_max_z) * float(this->get_cursor_z_relative(canvas))); shader->set_uniform("z_cursor", float(m_object_max_z) * float(this->get_cursor_z_relative(canvas)));
shader->set_uniform("z_cursor_band_width", float(this->band_width)); shader->set_uniform("z_cursor_band_width", float(this->band_width));
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
// Initialize the layer height texture mapping. // Initialize the layer height texture mapping.
const GLsizei w = (GLsizei)m_layers_texture.width; const GLsizei w = (GLsizei)m_layers_texture.width;
const GLsizei h = (GLsizei)m_layers_texture.height; const GLsizei h = (GLsizei)m_layers_texture.height;
@ -562,6 +569,9 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const
shader->set_uniform("volume_world_matrix", glvolume->world_matrix()); shader->set_uniform("volume_world_matrix", glvolume->world_matrix());
shader->set_uniform("object_max_z", 0.0f); shader->set_uniform("object_max_z", 0.0f);
const Transform3d view_model_matrix = camera.get_view_matrix() * glvolume->world_matrix();
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
glvolume->render(); glvolume->render();
} }
@ -883,7 +893,7 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
if (!polygons.empty()) { if (!polygons.empty()) {
if (m_render_fill) { if (m_render_fill) {
GLModel::Geometry fill_data; GLModel::Geometry fill_data;
fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
fill_data.color = { 0.8f, 0.8f, 1.0f, 0.5f }; fill_data.color = { 0.8f, 0.8f, 1.0f, 0.5f };
// vertices + indices // vertices + indices
@ -897,7 +907,7 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
fill_data.add_vertex((Vec3f)(v.cast<float>() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting fill_data.add_vertex((Vec3f)(v.cast<float>() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting
++vertices_counter; ++vertices_counter;
if (vertices_counter % 3 == 0) if (vertices_counter % 3 == 0)
fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
} }
} }
@ -910,7 +920,7 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
//BBS: add the height limit compute logic //BBS: add the height limit compute logic
if (!height_polygons.empty()) { if (!height_polygons.empty()) {
GLModel::Geometry height_fill_data; GLModel::Geometry height_fill_data;
height_fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::UINT }; height_fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
height_fill_data.color = {0.8f, 0.8f, 1.0f, 0.5f}; height_fill_data.color = {0.8f, 0.8f, 1.0f, 0.5f};
// vertices + indices // vertices + indices
@ -923,7 +933,7 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
height_fill_data.add_vertex(point); height_fill_data.add_vertex(point);
++vertices_counter; ++vertices_counter;
if (vertices_counter % 3 == 0) if (vertices_counter % 3 == 0)
height_fill_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); height_fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
} }
} }
@ -936,12 +946,16 @@ void GLCanvas3D::SequentialPrintClearance::render()
const ColorRGBA FILL_COLOR = { 0.7f, 0.7f, 1.0f, 0.5f }; const ColorRGBA FILL_COLOR = { 0.7f, 0.7f, 1.0f, 0.5f };
const ColorRGBA NO_FILL_COLOR = { 0.75f, 0.75f, 0.75f, 0.75f }; const ColorRGBA NO_FILL_COLOR = { 0.75f, 0.75f, 0.75f, 0.75f };
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
@ -1839,9 +1853,9 @@ void GLCanvas3D::render(bool only_init)
_render_sla_slices(); _render_sla_slices();
_render_selection(); _render_selection();
if (!no_partplate) if (!no_partplate)
_render_bed(!camera.is_looking_downward(), show_axes); _render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
if (!no_partplate) //BBS: add outline logic if (!no_partplate) //BBS: add outline logic
_render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id, true); _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true);
_render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running()); _render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running());
} }
/* preview render */ /* preview render */
@ -1849,8 +1863,8 @@ void GLCanvas3D::render(bool only_init)
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running()); _render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
_render_sla_slices(); _render_sla_slices();
_render_selection(); _render_selection();
_render_bed(!camera.is_looking_downward(), show_axes); _render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
_render_platelist(!camera.is_looking_downward(), only_current, true, hover_id); _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, true, hover_id);
// BBS: GUI refactor: add canvas size as parameters // BBS: GUI refactor: add canvas size as parameters
_render_gcode(cnv_size.get_width(), cnv_size.get_height()); _render_gcode(cnv_size.get_width(), cnv_size.get_height());
} }
@ -1858,7 +1872,7 @@ void GLCanvas3D::render(bool only_init)
else if (m_canvas_type == ECanvasType::CanvasAssembleView) { else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
//BBS: add outline logic //BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running()); _render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//_render_bed(!camera.is_looking_downward(), show_axes); //_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
_render_plane(); _render_plane();
//BBS: add outline logic insteadof selection under assemble view //BBS: add outline logic insteadof selection under assemble view
//_render_selection(); //_render_selection();
@ -1992,7 +2006,7 @@ void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w,
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view, bool for_picking) const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view, bool for_picking)
{ {
GLShaderProgram* shader = wxGetApp().get_shader("thumbnail"); GLShaderProgram* shader = wxGetApp().get_shader("thumbnail_attr");
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();
switch (OpenGLManager::get_framebuffers_type()) switch (OpenGLManager::get_framebuffers_type())
@ -5180,7 +5194,7 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa
//original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera
//now change to left_up as {0,0}, and top is 0, bottom is canvas_h //now change to left_up as {0,0}, and top is 0, bottom is canvas_h
#if BBS_TOOLBAR_ON_TOP #if BBS_TOOLBAR_ON_TOP
const float x = left * float(wxGetApp().plater()->get_camera().get_zoom()) + 0.5f * canvas_w; const float x = (1 + left) * canvas_w / 2;
ImGuiWrapper::push_toolbar_style(get_scale()); ImGuiWrapper::push_toolbar_style(get_scale());
imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
#else #else
@ -5265,9 +5279,8 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
//original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera
//now change to left_up as {0,0}, and top is 0, bottom is canvas_h //now change to left_up as {0,0}, and top is 0, bottom is canvas_h
#if BBS_TOOLBAR_ON_TOP #if BBS_TOOLBAR_ON_TOP
float zoom = (float)wxGetApp().plater()->get_camera().get_zoom();
float left_pos = m_main_toolbar.get_item("arrange")->render_left_pos; float left_pos = m_main_toolbar.get_item("arrange")->render_left_pos;
const float x = 0.5 * canvas_w + left_pos * zoom; const float x = (1 + left_pos) * canvas_w / 2;
imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f); imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f);
#else #else
@ -5536,19 +5549,15 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
} }
else { else {
camera.zoom_to_box(volumes_box); camera.zoom_to_box(volumes_box);
const Vec3d& target = camera.get_target();
double distance = camera.get_distance();
camera.select_view("iso"); camera.select_view("iso");
camera.apply_view_matrix();
camera.apply_projection(plate_build_volume);
} }
camera.apply_view_matrix(); camera.apply_view_matrix();
const Transform3d &view_matrix = camera.get_view_matrix();
camera.apply_projection(plate_build_volume); camera.apply_projection(plate_build_volume);
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); //GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (!for_picking && (shader == nullptr)) { if (!for_picking && (shader == nullptr)) {
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly"); BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
return; return;
@ -5561,6 +5570,8 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
const Transform3d &projection_matrix = camera.get_projection_matrix();
if (for_picking) { if (for_picking) {
//if (OpenGLManager::can_multisample()) //if (OpenGLManager::can_multisample())
// This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
@ -5573,9 +5584,6 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
// do not cull backfaces to show broken geometry, if any // do not cull backfaces to show broken geometry, if any
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
//glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
//glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
for (GLVolume* vol : visible_volumes) { for (GLVolume* vol : visible_volumes) {
// Object picking mode. Render the object with a color encoding the object index. // Object picking mode. Render the object with a color encoding the object index.
// we reserve color = (0,0,0) for occluders (as the printbed) // we reserve color = (0,0,0) for occluders (as the printbed)
@ -5587,15 +5595,19 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
unsigned int g = (id & (0x000000FF << 8)) >> 8; unsigned int g = (id & (0x000000FF << 8)) >> 8;
unsigned int b = (id & (0x000000FF << 16)) >> 16; unsigned int b = (id & (0x000000FF << 16)) >> 16;
unsigned int a = 0xFF; unsigned int a = 0xFF;
glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); vol->model.set_color({(GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255});
/*curr_color[0] = (GLfloat)r * INV_255; /*curr_color[0] = (GLfloat)r * INV_255;
curr_color[1] = (GLfloat)g * INV_255; curr_color[1] = (GLfloat)g * INV_255;
curr_color[2] = (GLfloat)b * INV_255; curr_color[2] = (GLfloat)b * INV_255;
curr_color[3] = (GLfloat)a * INV_255; curr_color[3] = (GLfloat)a * INV_255;
shader->set_uniform("uniform_color", curr_color);*/ shader->set_uniform("uniform_color", curr_color);*/
bool is_active = vol->is_active; const bool is_active = vol->is_active;
vol->is_active = true; vol->is_active = true;
const Transform3d matrix = view_matrix * vol->world_matrix();
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d) matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
vol->simple_render(nullptr, model_objects, extruder_colors); vol->simple_render(nullptr, model_objects, extruder_colors);
vol->is_active = is_active; vol->is_active = is_active;
} }
@ -5627,8 +5639,12 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray); shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
}*/ }*/
// the volume may have been deactivated by an active gizmo // the volume may have been deactivated by an active gizmo
bool is_active = vol->is_active; const bool is_active = vol->is_active;
vol->is_active = true; vol->is_active = true;
const Transform3d matrix = view_matrix * vol->world_matrix();
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d) matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
vol->simple_render(shader, model_objects, extruder_colors); vol->simple_render(shader, model_objects, extruder_colors);
vol->is_active = is_active; vol->is_active = is_active;
} }
@ -6404,7 +6420,8 @@ void GLCanvas3D::_picking_pass()
//BBS: only render plate in view 3D //BBS: only render plate in view 3D
if (m_canvas_type == ECanvasType::CanvasView3D) { if (m_canvas_type == ECanvasType::CanvasView3D) {
_render_plates_for_picking(); const Camera &camera = wxGetApp().plater()->get_camera();
_render_plates_for_picking(camera.get_view_matrix(), camera.get_projection_matrix());
} }
m_camera_clipping_plane = m_gizmos.get_clipping_plane(); m_camera_clipping_plane = m_gizmos.get_clipping_plane();
@ -6574,12 +6591,6 @@ void GLCanvas3D::_render_background()
} }
} }
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
// Draws a bottom to top gradient over the complete screen. // Draws a bottom to top gradient over the complete screen.
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
@ -6591,7 +6602,7 @@ void GLCanvas3D::_render_background()
m_background.reset(); m_background.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(6); init_data.reserve_indices(6);
@ -6602,30 +6613,25 @@ void GLCanvas3D::_render_background()
init_data.add_vertex(Vec2f(-1.0f, 1.0f), Vec2f(0.0f, 1.0f)); init_data.add_vertex(Vec2f(-1.0f, 1.0f), Vec2f(0.0f, 1.0f));
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
m_background.init_from(std::move(init_data)); m_background.init_from(std::move(init_data));
} }
GLShaderProgram* shader = wxGetApp().get_shader("background"); GLShaderProgram* shader = wxGetApp().get_shader("background_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("top_color", use_error_color ? ERROR_BG_LIGHT_COLOR : DEFAULT_BG_LIGHT_COLOR); shader->set_uniform("top_color", use_error_color ? ERROR_BG_LIGHT_COLOR : DEFAULT_BG_LIGHT_COLOR);
shader->set_uniform("bottom_color", bottom_color); shader->set_uniform("bottom_color", bottom_color);
m_background.render(); m_background.render();
shader->stop_using(); shader->stop_using();
} }
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glPopMatrix());
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glPopMatrix());
} }
void GLCanvas3D::_render_bed(bool bottom, bool show_axes) void GLCanvas3D::_render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes)
{ {
float scale_factor = 1.0; float scale_factor = 1.0;
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
@ -6643,27 +6649,27 @@ void GLCanvas3D::_render_bed(bool bottom, bool show_axes)
//bool show_texture = true; //bool show_texture = true;
//BBS set axes mode //BBS set axes mode
m_bed.set_axes_mode(m_main_toolbar.is_enabled()); m_bed.set_axes_mode(m_main_toolbar.is_enabled());
m_bed.render(*this, bottom, scale_factor, show_axes); m_bed.render(*this, view_matrix, projection_matrix, bottom, scale_factor, show_axes);
} }
void GLCanvas3D::_render_bed_for_picking(bool bottom) void GLCanvas3D::_render_bed_for_picking(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom)
{ {
float scale_factor = 1.0; float scale_factor = 1.0;
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
scale_factor = m_retina_helper->get_scale_factor(); scale_factor = m_retina_helper->get_scale_factor();
#endif // ENABLE_RETINA_GL #endif // ENABLE_RETINA_GL
//m_bed.render_for_picking(*this, bottom, scale_factor); //m_bed.render_for_picking(*this, view_matrix, projection_matrix, bottom, scale_factor);
} }
void GLCanvas3D::_render_platelist(bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali) const void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali)
{ {
wxGetApp().plater()->get_partplate_list().render(bottom, only_current, only_body, hover_id, render_cali); wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali);
} }
void GLCanvas3D::_render_plates_for_picking() const void GLCanvas3D::_render_plates_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix)
{ {
wxGetApp().plater()->get_partplate_list().render_for_picking_pass(); wxGetApp().plater()->get_partplate_list().render_for_picking_pass(view_matrix, projection_matrix);
} }
void GLCanvas3D::_render_plane() const void GLCanvas3D::_render_plane() const
@ -6736,7 +6742,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else else
m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances()); m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances());
GLShaderProgram* shader = wxGetApp().get_shader("gouraud"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_attr");
ECanvasType canvas_type = this->m_canvas_type; ECanvasType canvas_type = this->m_canvas_type;
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
@ -6751,10 +6757,11 @@ 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;
m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { const Camera& camera = wxGetApp().plater()->get_camera();
// Which volume to paint without the layer height profile shader? m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [object_id](const GLVolume& volume) {
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); // Which volume to paint without the layer height profile shader?
}); return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
});
m_layers_editing.render_volumes(*this, m_volumes); m_layers_editing.render_volumes(*this, m_volumes);
} }
else { else {
@ -6766,7 +6773,8 @@ 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
m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { 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) {
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;
} }
@ -6798,8 +6806,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else else
shader->set_uniform("show_wireframe", false); shader->set_uniform("show_wireframe", false);
}*/ }*/
const Camera& camera = wxGetApp().plater()->get_camera();
//BBS:add assemble view related logic //BBS:add assemble view related logic
m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [this, canvas_type](const GLVolume& volume) {
if (canvas_type == ECanvasType::CanvasAssembleView) { if (canvas_type == ECanvasType::CanvasAssembleView) {
return !volume.is_modifier; return !volume.is_modifier;
} }
@ -7171,16 +7180,13 @@ void GLCanvas3D::_render_style_editor()
void GLCanvas3D::_render_volumes_for_picking() const void GLCanvas3D::_render_volumes_for_picking() const
{ {
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
// do not cull backfaces to show broken geometry, if any // do not cull backfaces to show broken geometry, if any
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix();
for (size_t type = 0; type < 2; ++ type) { for (size_t type = 0; type < 2; ++ type) {
GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix);
@ -7194,14 +7200,14 @@ void GLCanvas3D::_render_volumes_for_picking() const
//const unsigned int id = 1 + volume.second.first; //const unsigned int id = 1 + volume.second.first;
volume.first->model.set_color(picking_decode(id)); volume.first->model.set_color(picking_decode(id));
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * volume.first->world_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
volume.first->render(); volume.first->render();
shader->stop_using(); shader->stop_using();
} }
} }
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
} }
@ -7241,32 +7247,19 @@ void GLCanvas3D::_render_main_toolbar()
if (!m_main_toolbar.is_enabled()) if (!m_main_toolbar.is_enabled())
return; return;
Size cnv_size = get_canvas_size(); const Size cnv_size = get_canvas_size();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float top = 0.5f * (float)cnv_size.get_height();
#if BBS_TOOLBAR_ON_TOP
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f;
float gizmo_width = m_gizmos.get_scaled_total_width(); const float gizmo_width = m_gizmos.get_scaled_total_width();
float assemble_width = m_assemble_view_toolbar.get_width(); const float assemble_width = m_assemble_view_toolbar.get_width();
float separator_width = m_separator_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; const float left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width - collapse_toolbar_width));
float left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width - collapse_toolbar_width)) * inv_zoom;
#else
float gizmo_height = m_gizmos.get_scaled_total_height();
float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
float main_toolbar_height = (float)m_main_toolbar.get_height();
float assemble_height = m_assemble_view_toolbar.get_height();
float top = 0.5f * (main_toolbar_height + gizmo_height + assemble_height) * inv_zoom;
float left = (0.5f * (float)cnv_size.get_width() - m_main_toolbar.get_width()) * inv_zoom;
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": top %1%, main_toolbar_height %2%, space_height %3% gizmo_height %4%") % top % main_toolbar_height % space_height % gizmo_height;
#endif
m_main_toolbar.set_position(top, left); m_main_toolbar.set_position(top, left);
m_main_toolbar.render(*this); m_main_toolbar.render(*this);
if (m_toolbar_highlighter.m_render_arrow) if (m_toolbar_highlighter.m_render_arrow)
{
m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item); m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item);
}
} }
//BBS: GUI refactor: GLToolbar adjust //BBS: GUI refactor: GLToolbar adjust
@ -7591,28 +7584,16 @@ void GLCanvas3D::_render_assemble_view_toolbar() const
if (!m_assemble_view_toolbar.is_enabled()) if (!m_assemble_view_toolbar.is_enabled())
return; return;
Size cnv_size = get_canvas_size(); const Size cnv_size = get_canvas_size();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
#if BBS_TOOLBAR_ON_TOP
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f;
float gizmo_width = m_gizmos.get_scaled_total_width(); const float gizmo_width = m_gizmos.get_scaled_total_width();
float assemble_width = m_assemble_view_toolbar.get_width(); const float assemble_width = m_assemble_view_toolbar.get_width();
float separator_width = m_separator_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; const float top = 0.5f * (float)cnv_size.get_height();
float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width - separator_width - collapse_toolbar_width)) * inv_zoom; const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width));
float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width) * inv_zoom; const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width);
//float left = 0.5f * (m_main_toolbar.get_width() + gizmo_width - m_assemble_view_toolbar.get_width() + collapse_toolbar_width) * inv_zoom;
#else
float gizmo_height = m_gizmos.get_scaled_total_height();
//float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
float main_toolbar_height = (float)m_main_toolbar.get_height();
float assemble_height = (float)m_assemble_view_toolbar.get_height();
float top = 0.5f * (assemble_height - main_toolbar_height - gizmo_height) * inv_zoom;
float left = (0.5f * (float)cnv_size.get_width() - m_assemble_view_toolbar.get_width()) * inv_zoom;
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": top %1%, main_toolbar_height %2%, space_height %3% gizmo_height %4%") % top % main_toolbar_height % space_height % gizmo_height;
#endif
m_assemble_view_toolbar.set_position(top, left); m_assemble_view_toolbar.set_position(top, left);
m_assemble_view_toolbar.render(*this); m_assemble_view_toolbar.render(*this);
} }
@ -7677,17 +7658,15 @@ void GLCanvas3D::_render_separator_toolbar_right() const
if (!m_separator_toolbar.is_enabled()) if (!m_separator_toolbar.is_enabled())
return; return;
Size cnv_size = get_canvas_size(); const Size cnv_size = get_canvas_size();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f;
float gizmo_width = m_gizmos.get_scaled_total_width(); const float gizmo_width = m_gizmos.get_scaled_total_width();
float assemble_width = m_assemble_view_toolbar.get_width(); const float assemble_width = m_assemble_view_toolbar.get_width();
float separator_width = m_separator_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; const float top = 0.5f * (float)cnv_size.get_height();
float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width - collapse_toolbar_width)) * inv_zoom; const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width));
float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width) * inv_zoom; const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width / 2);
m_separator_toolbar.set_position(top, left); m_separator_toolbar.set_position(top, left);
m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine);
@ -7698,17 +7677,15 @@ void GLCanvas3D::_render_separator_toolbar_left() const
if (!m_separator_toolbar.is_enabled()) if (!m_separator_toolbar.is_enabled())
return; return;
Size cnv_size = get_canvas_size(); const Size cnv_size = get_canvas_size();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; const float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f;
float gizmo_width = m_gizmos.get_scaled_total_width(); const float gizmo_width = m_gizmos.get_scaled_total_width();
float assemble_width = m_assemble_view_toolbar.get_width(); const float assemble_width = m_assemble_view_toolbar.get_width();
float separator_width = m_separator_toolbar.get_width(); const float separator_width = m_separator_toolbar.get_width();
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; const float top = 0.5f * (float)cnv_size.get_height();
float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width)) * inv_zoom; const float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width));
float left = main_toolbar_left + (m_main_toolbar.get_width()) * inv_zoom; const float left = main_toolbar_left + (m_main_toolbar.get_width());
m_separator_toolbar.set_position(top, left); m_separator_toolbar.set_position(top, left);
m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine);
@ -7718,12 +7695,10 @@ void GLCanvas3D::_render_collapse_toolbar() const
{ {
GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar();
Size cnv_size = get_canvas_size(); const Size cnv_size = get_canvas_size();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float top = 0.5f * (float)cnv_size.get_height();
//const float left = (0.5f * (float)cnv_size.get_width() - (float)collapse_toolbar.get_width() - band);
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; const float left = -0.5f * (float)cnv_size.get_width();
//float left = (0.5f * (float)cnv_size.get_width() - (float)collapse_toolbar.get_width() - band) * inv_zoom;
float left = -0.5f * (float)cnv_size.get_width() * inv_zoom;
collapse_toolbar.set_position(top, left); collapse_toolbar.set_position(top, left);
collapse_toolbar.render(*this); collapse_toolbar.render(*this);
@ -8002,52 +7977,51 @@ void GLCanvas3D::_render_assemble_info() const
#if ENABLE_SHOW_CAMERA_TARGET #if ENABLE_SHOW_CAMERA_TARGET
void GLCanvas3D::_render_camera_target() void GLCanvas3D::_render_camera_target()
{ {
static const double half_length = 5.0; static const float half_length = 5.0f;
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glLineWidth(2.0f)); glsafe(::glLineWidth(2.0f));
const Vec3d& target = wxGetApp().plater()->get_camera().get_target(); const Vec3f& target = wxGetApp().plater()->get_camera().get_target().cast<float>();
bool target_changed = !m_camera_target.target.isApprox(target); bool target_changed = !m_camera_target.target.isApprox(target.cast<double>());
m_camera_target.target = target; m_camera_target.target = target.cast<double>();
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (!m_camera_target.axis[i].is_initialized() || target_changed) { if (!m_camera_target.axis[i].is_initialized() || target_changed) {
m_camera_target.axis[i].reset(); m_camera_target.axis[i].reset();
GLModel::InitializationData init_data; GLModel::Geometry init_data;
GLModel::InitializationData::Entity entity; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
entity.type = GLModel::PrimitiveType::Lines; init_data.color = (i == X) ? ColorRGBA::X() : ((i == Y) ? ColorRGBA::Y() : ColorRGBA::Z());
entity.positions.reserve(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2);
// vertices
if (i == X) { if (i == X) {
entity.positions.emplace_back(target.x() - half_length, target.y(), target.z()); init_data.add_vertex(Vec3f(target.x() - half_length, target.y(), target.z()));
entity.positions.emplace_back(target.x() + half_length, target.y(), target.z()); init_data.add_vertex(Vec3f(target.x() + half_length, target.y(), target.z()));
} }
else if (i == Y) { else if (i == Y) {
entity.positions.emplace_back(target.x(), target.y() - half_length, target.z()); init_data.add_vertex(Vec3f(target.x(), target.y() - half_length, target.z()));
entity.positions.emplace_back(target.x(), target.y() + half_length, target.z()); init_data.add_vertex(Vec3f(target.x(), target.y() + half_length, target.z()));
} }
else { else {
entity.positions.emplace_back(target.x(), target.y(), target.z() - half_length); init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() - half_length));
entity.positions.emplace_back(target.x(), target.y(), target.z() + half_length); init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() + half_length));
}
entity.normals.reserve(2);
for (size_t j = 0; j < 2; ++j) {
entity.normals.emplace_back(Vec3f::UnitZ());
} }
entity.indices.reserve(2); // indices
entity.indices.emplace_back(0); init_data.add_line(0, 1);
entity.indices.emplace_back(1);
init_data.entities.emplace_back(entity); m_camera_target.axis[i].init_from(std::move(init_data));
m_camera_target.axis[i].init_from(init_data);
m_camera_target.axis[i].set_color(-1, (i == X) ? ColorRGBA::X() : (i == Y) ? ColorRGBA::Y() : ColorRGBA::Z());
} }
} }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
m_camera_target.axis[i].render(); m_camera_target.axis[i].render();
} }
@ -8100,7 +8074,7 @@ void GLCanvas3D::_render_sla_slices()
auto init_model = [](GLModel& model, const Pointf3s& triangles, const ColorRGBA& color) { auto init_model = [](GLModel& model, const Pointf3s& triangles, const ColorRGBA& color) {
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(triangles.size()) }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(triangles.size()); init_data.reserve_vertices(triangles.size());
init_data.reserve_indices(triangles.size() / 3); init_data.reserve_indices(triangles.size() / 3);
init_data.color = color; init_data.color = color;
@ -8110,10 +8084,7 @@ void GLCanvas3D::_render_sla_slices()
init_data.add_vertex((Vec3f)v.cast<float>()); init_data.add_vertex((Vec3f)v.cast<float>());
++vertices_count; ++vertices_count;
if (vertices_count % 3 == 0) { if (vertices_count % 3 == 0) {
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_triangle(vertices_count - 3, vertices_count - 2, vertices_count - 1);
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);
} }
} }
@ -8164,24 +8135,25 @@ void GLCanvas3D::_render_sla_slices()
} }
} }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
for (const SLAPrintObject::Instance& inst : obj->instances()) { for (const SLAPrintObject::Instance& inst : obj->instances()) {
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0.0)); const Transform3d view_model_matrix = camera.get_view_matrix() *
glsafe(::glRotatef(Geometry::rad2deg(inst.rotation), 0.0f, 0.0f, 1.0f)); Geometry::assemble_transform(Vec3d(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0.0),
if (obj->is_left_handed()) inst.rotation * Vec3d::UnitZ(), Vec3d::Ones(),
// The polygons are mirrored by X. obj->is_left_handed() ? Vec3d(-1.0f, 1.0f, 1.0f) : Vec3d::Ones());
glsafe(::glScalef(-1.0f, 1.0f, 1.0f));
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
bottom_obj_triangles.render(); bottom_obj_triangles.render();
top_obj_triangles.render(); top_obj_triangles.render();
bottom_sup_triangles.render(); bottom_sup_triangles.render();
top_sup_triangles.render(); top_sup_triangles.render();
glsafe(::glPopMatrix());
} }
shader->stop_using(); shader->stop_using();
@ -8371,7 +8343,7 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume)
GLVolume* volume = m_volumes.new_toolpath_volume(color); GLVolume* volume = m_volumes.new_toolpath_volume(color);
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
for (size_t i = 0; i < skirt_height; ++ i) { for (size_t i = 0; i < skirt_height; ++ i) {
volume->print_zs.emplace_back(print_zs[i]); volume->print_zs.emplace_back(print_zs[i]);
volume->offsets.emplace_back(init_data.indices_count()); volume->offsets.emplace_back(init_data.indices_count());
@ -8594,7 +8566,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
assert(vols.size() == geometries.size()); assert(vols.size() == geometries.size());
for (GLModel::Geometry& g : geometries) { for (GLModel::Geometry& g : geometries) {
g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
} }
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) { for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
const Layer *layer = ctxt.layers[idx_layer]; const Layer *layer = ctxt.layers[idx_layer];
@ -8793,7 +8765,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
assert(vols.size() == geometries.size()); assert(vols.size() == geometries.size());
for (GLModel::Geometry& g : geometries) { for (GLModel::Geometry& g : geometries) {
g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
} }
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) { for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer); const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);

View file

@ -261,9 +261,8 @@ class GLCanvas3D
GLModel baseline; GLModel baseline;
GLModel profile; GLModel profile;
GLModel background; GLModel background;
Rect old_bar_rect; float old_canvas_width{ 0.0f };
std::vector<double> old_layer_height_profile; std::vector<double> old_layer_height_profile;
bool dirty{ false };
}; };
Profile m_profile; Profile m_profile;
@ -294,7 +293,6 @@ class GLCanvas3D
static float get_cursor_z_relative(const GLCanvas3D& canvas); static float get_cursor_z_relative(const GLCanvas3D& canvas);
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y); static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
static Rect get_bar_rect_screen(const GLCanvas3D& canvas); static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
static float get_overlay_window_width() { return LayersEditing::s_overlay_window_width; } static float get_overlay_window_width() { return LayersEditing::s_overlay_window_width; }
float object_max_z() const { return m_object_max_z; } float object_max_z() const { return m_object_max_z; }
@ -304,8 +302,8 @@ class GLCanvas3D
private: private:
bool is_initialized() const; bool is_initialized() const;
void generate_layer_height_texture(); void generate_layer_height_texture();
void render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect); void render_active_object_annotations(const GLCanvas3D& canvas);
void render_profile(const Rect& bar_rect); void render_profile(const GLCanvas3D& canvas);
void update_slicing_parameters(); void update_slicing_parameters();
static float thickness_bar_width(const GLCanvas3D& canvas); static float thickness_bar_width(const GLCanvas3D& canvas);
@ -1117,11 +1115,11 @@ private:
void _picking_pass(); void _picking_pass();
void _rectangular_selection_picking_pass(); void _rectangular_selection_picking_pass();
void _render_background(); void _render_background();
void _render_bed(bool bottom, bool show_axes); void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes);
void _render_bed_for_picking(bool bottom); void _render_bed_for_picking(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom);
//BBS: add part plate related logic //BBS: add part plate related logic
void _render_platelist(bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false) const; void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false);
void _render_plates_for_picking() const; void _render_plates_for_picking(const Transform3d& view_matrix, const Transform3d& projection_matrix);
//BBS: add outline drawing logic //BBS: add outline drawing logic
void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline = true); void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline = true);
//BBS: GUI refactor: add canvas size as parameters //BBS: GUI refactor: add canvas size as parameters

View file

@ -52,16 +52,6 @@ static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_norm
} }
#endif // ENABLE_SMOOTH_NORMALS #endif // ENABLE_SMOOTH_NORMALS
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) void GLModel::Geometry::add_vertex(const Vec2f& position)
{ {
assert(format.vertex_layout == EVertexLayout::P2); assert(format.vertex_layout == EVertexLayout::P2);
@ -107,70 +97,22 @@ void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec3f& normal)
vertices.emplace_back(normal.z()); vertices.emplace_back(normal.z());
} }
void GLModel::Geometry::add_ushort_index(unsigned short id) void GLModel::Geometry::add_index(unsigned int id)
{ {
if (format.index_type != EIndexType::USHORT) { indices.emplace_back(id);
assert(false);
return;
}
indices.resize(indices.size() + sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id, sizeof(unsigned short));
} }
void GLModel::Geometry::add_uint_index(unsigned int id) void GLModel::Geometry::add_line(unsigned int id1, unsigned int id2)
{ {
if (format.index_type != EIndexType::UINT) { indices.emplace_back(id1);
assert(false); indices.emplace_back(id2);
return;
}
indices.resize(indices.size() + sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id, sizeof(unsigned int));
} }
void GLModel::Geometry::add_ushort_line(unsigned short id1, unsigned short id2) void GLModel::Geometry::add_triangle(unsigned int id1, unsigned int id2, unsigned int id3)
{ {
if (format.index_type != EIndexType::USHORT) { indices.emplace_back(id1);
assert(false); indices.emplace_back(id2);
return; indices.emplace_back(id3);
}
indices.resize(indices.size() + 2 * sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned short), &id1, sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id2, sizeof(unsigned short));
}
void GLModel::Geometry::add_uint_line(unsigned int id1, unsigned int id2)
{
if (format.index_type != EIndexType::UINT) {
assert(false);
return;
}
indices.resize(indices.size() + 2 * sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned int), &id1, sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id2, sizeof(unsigned int));
}
void GLModel::Geometry::add_ushort_triangle(unsigned short id1, unsigned short id2, unsigned short id3)
{
if (format.index_type != EIndexType::USHORT) {
assert(false);
return;
}
indices.resize(indices.size() + 3 * sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - 3 * sizeof(unsigned short), &id1, sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned short), &id2, sizeof(unsigned short));
::memcpy(indices.data() + indices.size() - sizeof(unsigned short), &id3, sizeof(unsigned short));
}
void GLModel::Geometry::add_uint_triangle(unsigned int id1, unsigned int id2, unsigned int id3)
{
if (format.index_type != EIndexType::UINT) {
assert(false);
return;
}
indices.resize(indices.size() + 3 * sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - 3 * sizeof(unsigned int), &id1, sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - 2 * sizeof(unsigned int), &id2, sizeof(unsigned int));
::memcpy(indices.data() + indices.size() - sizeof(unsigned int), &id3, sizeof(unsigned int));
} }
Vec2f GLModel::Geometry::extract_position_2(size_t id) const Vec2f GLModel::Geometry::extract_position_2(size_t id) const
@ -256,60 +198,29 @@ void GLModel::Geometry::set_vertex(size_t id, const Vec3f& position, const Vec3f
} }
} }
void GLModel::Geometry::set_ushort_index(size_t id, unsigned short index) void GLModel::Geometry::set_index(size_t id, unsigned int index)
{ {
assert(id < indices_count()); assert(id < indices_count());
if (id < indices_count()) if (id < indices_count())
::memcpy(indices.data() + id * sizeof(unsigned short), &index, sizeof(unsigned short)); indices[id] = index;
} }
void GLModel::Geometry::set_uint_index(size_t id, unsigned int index) unsigned int GLModel::Geometry::extract_index(size_t id) const
{ {
assert(id < indices_count());
if (id < indices_count())
::memcpy(indices.data() + id * sizeof(unsigned int), &index, sizeof(unsigned int));
}
unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
{
if (format.index_type != EIndexType::UINT) {
assert(false);
return -1;
}
if (indices_count() <= id) { if (indices_count() <= id) {
assert(false); assert(false);
return -1; return -1;
} }
unsigned int ret = (unsigned int)-1; return indices[id];
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned int));
return ret;
}
unsigned short GLModel::Geometry::extract_ushort_index(size_t id) const
{
if (format.index_type != EIndexType::USHORT) {
assert(false);
return -1;
}
if (indices_count() <= id) {
assert(false);
return -1;
}
unsigned short ret = (unsigned short)-1;
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned short));
return ret;
} }
void GLModel::Geometry::remove_vertex(size_t id) void GLModel::Geometry::remove_vertex(size_t id)
{ {
assert(id < vertices_count()); assert(id < vertices_count());
if (id < vertices_count()) { if (id < vertices_count()) {
size_t stride = vertex_stride_floats(format); const size_t stride = vertex_stride_floats(format);
std::vector<float>::iterator it = vertices.begin() + id * stride; std::vector<float>::const_iterator it = vertices.begin() + id * stride;
vertices.erase(it, it + stride); vertices.erase(it, it + stride);
} }
} }
@ -391,21 +302,17 @@ size_t GLModel::Geometry::tex_coord_offset_floats(const Format& format)
}; };
} }
size_t GLModel::Geometry::index_stride_bytes(const Format& format) size_t GLModel::Geometry::index_stride_bytes(const Geometry& data)
{ {
switch (format.index_type) switch (data.index_type)
{ {
case EIndexType::UINT: { return sizeof(unsigned int); } case EIndexType::UINT: { return sizeof(unsigned int); }
case EIndexType::USHORT: { return sizeof(unsigned short); } case EIndexType::USHORT: { return sizeof(unsigned short); }
case EIndexType::UBYTE: { return sizeof(unsigned char); }
default: { assert(false); return 0; } default: { assert(false); return 0; }
}; };
} }
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) bool GLModel::Geometry::has_position(const Format& format)
{ {
switch (format.vertex_layout) switch (format.vertex_layout)
@ -491,7 +398,7 @@ void GLModel::init_from(const indexed_triangle_set& its)
} }
Geometry& data = m_render_data.geometry; Geometry& data = m_render_data.geometry;
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(3 * its.indices.size()) }; data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3 };
data.reserve_vertices(3 * its.indices.size()); data.reserve_vertices(3 * its.indices.size());
data.reserve_indices(3 * its.indices.size()); data.reserve_indices(3 * its.indices.size());
@ -505,10 +412,7 @@ void GLModel::init_from(const indexed_triangle_set& its)
data.add_vertex(vertex[j], n); data.add_vertex(vertex[j], n);
} }
vertices_counter += 3; vertices_counter += 3;
if (data.format.index_type == GLModel::Geometry::EIndexType::USHORT) data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
data.add_ushort_triangle((unsigned short)vertices_counter - 3, (unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
else
data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
} }
// update bounding box // update bounding box
@ -531,7 +435,7 @@ void GLModel::init_from(const Polygons& polygons, float z)
} }
Geometry& data = m_render_data.geometry; Geometry& data = m_render_data.geometry;
data.format = { Geometry::EPrimitiveType::Lines, Geometry::EVertexLayout::P3, Geometry::EIndexType::UINT }; data.format = { Geometry::EPrimitiveType::Lines, Geometry::EVertexLayout::P3 };
size_t segments_count = 0; size_t segments_count = 0;
for (const Polygon& polygon : polygons) { for (const Polygon& polygon : polygons) {
@ -550,7 +454,7 @@ void GLModel::init_from(const Polygons& polygons, float z)
data.add_vertex(Vec3f(unscale<float>(p0.x()), unscale<float>(p0.y()), z)); data.add_vertex(Vec3f(unscale<float>(p0.x()), unscale<float>(p0.y()), z));
data.add_vertex(Vec3f(unscale<float>(p1.x()), unscale<float>(p1.y()), z)); data.add_vertex(Vec3f(unscale<float>(p1.x()), unscale<float>(p1.y()), z));
vertices_counter += 2; vertices_counter += 2;
data.add_uint_line(vertices_counter - 2, vertices_counter - 1); data.add_line(vertices_counter - 2, vertices_counter - 1);
} }
} }
@ -598,7 +502,7 @@ void GLModel::reset()
m_render_data.vertices_count = 0; m_render_data.vertices_count = 0;
m_render_data.indices_count = 0; m_render_data.indices_count = 0;
m_render_data.geometry.vertices = std::vector<float>(); m_render_data.geometry.vertices = std::vector<float>();
m_render_data.geometry.indices = std::vector<unsigned char>(); m_render_data.geometry.indices = std::vector<unsigned int>();
m_bounding_box = BoundingBoxf3(); m_bounding_box = BoundingBoxf3();
m_filename = std::string(); m_filename = std::string();
} }
@ -618,13 +522,14 @@ static GLenum get_primitive_mode(const GLModel::Geometry::Format& format)
} }
} }
static GLenum get_index_type(const GLModel::Geometry::Format& format) static GLenum get_index_type(const GLModel::Geometry& data)
{ {
switch (format.index_type) switch (data.index_type)
{ {
default: default:
case GLModel::Geometry::EIndexType::UINT: { return GL_UNSIGNED_INT; } case GLModel::Geometry::EIndexType::UINT: { return GL_UNSIGNED_INT; }
case GLModel::Geometry::EIndexType::USHORT: { return GL_UNSIGNED_SHORT; } case GLModel::Geometry::EIndexType::USHORT: { return GL_UNSIGNED_SHORT; }
case GLModel::Geometry::EIndexType::UBYTE: { return GL_UNSIGNED_BYTE; }
} }
} }
@ -642,7 +547,6 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
return; return;
GLShaderProgram* shader = wxGetApp().get_current_shader(); GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -655,7 +559,7 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
const Geometry& data = m_render_data.geometry; const Geometry& data = m_render_data.geometry;
const GLenum mode = get_primitive_mode(data.format); const GLenum mode = get_primitive_mode(data.format);
const GLenum index_type = get_index_type(data.format); const GLenum index_type = get_index_type(data);
const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format);
const bool position = Geometry::has_position(data.format); const bool position = Geometry::has_position(data.format);
@ -664,74 +568,44 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id));
bool use_attributes = boost::algorithm::iends_with(shader->get_name(), "_attr");
int position_id = -1; int position_id = -1;
int normal_id = -1; int normal_id = -1;
int tex_coord_id = -1; int tex_coord_id = -1;
if (position) { if (position) {
if (use_attributes) { position_id = shader->get_attrib_location("v_position");
position_id = shader->get_attrib_location("v_position"); if (position_id != -1) {
if (position_id != -1) { glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format)));
glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(position_id));
glsafe(::glEnableVertexAttribArray(position_id));
}
}
else {
glsafe(::glVertexPointer(Geometry::position_stride_floats(data.format), GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format)));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
} }
} }
if (normal) { if (normal) {
if (use_attributes) { normal_id = shader->get_attrib_location("v_normal");
normal_id = shader->get_attrib_location("v_normal"); if (normal_id != -1) {
if (normal_id != -1) { glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format)));
glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(normal_id));
glsafe(::glEnableVertexAttribArray(normal_id));
}
}
else {
glsafe(::glNormalPointer(GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format)));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
} }
} }
if (tex_coord) { if (tex_coord) {
if (use_attributes) { tex_coord_id = shader->get_attrib_location("v_tex_coord");
tex_coord_id = shader->get_attrib_location("v_tex_coord"); if (tex_coord_id != -1) {
if (tex_coord_id != -1) { glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::tex_coord_offset_bytes(data.format)));
glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::tex_coord_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(tex_coord_id));
glsafe(::glEnableVertexAttribArray(tex_coord_id));
}
}
else {
glsafe(::glTexCoordPointer(Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, vertex_stride_bytes, (const void*)Geometry::tex_coord_offset_bytes(data.format)));
glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY));
} }
} }
shader->set_uniform("uniform_color", data.color); shader->set_uniform("uniform_color", data.color);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
glsafe(::glDrawElements(mode, range.second - range.first, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format)))); glsafe(::glDrawElements(mode, range.second - range.first, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data))));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (use_attributes) { if (tex_coord_id != -1)
if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id));
glsafe(::glDisableVertexAttribArray(tex_coord_id)); if (normal_id != -1)
if (normal_id != -1) glsafe(::glDisableVertexAttribArray(normal_id));
glsafe(::glDisableVertexAttribArray(normal_id)); if (position_id != -1)
if (position_id != -1) glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glDisableVertexAttribArray(position_id));
}
else {
if (tex_coord)
glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY));
if (normal)
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (position)
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
}
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
@ -742,18 +616,18 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
return; return;
GLShaderProgram* shader = wxGetApp().get_current_shader(); GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced")) if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced_attr"))
return; return;
// vertex attributes // vertex attributes
GLint position_id = shader->get_attrib_location("v_position"); const GLint position_id = shader->get_attrib_location("v_position");
GLint normal_id = shader->get_attrib_location("v_normal"); const GLint normal_id = shader->get_attrib_location("v_normal");
if (position_id == -1 || normal_id == -1) if (position_id == -1 || normal_id == -1)
return; return;
// instance attributes // instance attributes
GLint offset_id = shader->get_attrib_location("i_offset"); const GLint offset_id = shader->get_attrib_location("i_offset");
GLint scales_id = shader->get_attrib_location("i_scales"); const GLint scales_id = shader->get_attrib_location("i_scales");
if (offset_id == -1 || scales_id == -1) if (offset_id == -1 || scales_id == -1)
return; return;
@ -773,8 +647,8 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
const Geometry& data = m_render_data.geometry; const Geometry& data = m_render_data.geometry;
GLenum mode = get_primitive_mode(data.format); const GLenum mode = get_primitive_mode(data.format);
GLenum index_type = get_index_type(data.format); const GLenum index_type = get_index_type(data);
shader->set_uniform("uniform_color", data.color); shader->set_uniform("uniform_color", data.color);
@ -833,26 +707,36 @@ bool GLModel::send_to_gpu()
// indices // indices
glsafe(::glGenBuffers(1, &m_render_data.ibo_id)); glsafe(::glGenBuffers(1, &m_render_data.ibo_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW)); if (m_render_data.vertices_count <= 256) {
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); // convert indices to unsigned char to save gpu memory
std::vector<unsigned char> reduced_indices(data.indices.size());
for (size_t i = 0; i < data.indices.size(); ++i) {
reduced_indices[i] = (unsigned char)data.indices[i];
}
data.index_type = Geometry::EIndexType::UBYTE;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, reduced_indices.size() * sizeof(unsigned char), reduced_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
else if (m_render_data.vertices_count <= 65536) {
// convert indices to unsigned short to save gpu memory
std::vector<unsigned short> reduced_indices(data.indices.size());
for (size_t i = 0; i < data.indices.size(); ++i) {
reduced_indices[i] = (unsigned short)data.indices[i];
}
data.index_type = Geometry::EIndexType::USHORT;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, reduced_indices.size() * sizeof(unsigned short), reduced_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
else {
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
m_render_data.indices_count = indices_count(); m_render_data.indices_count = indices_count();
data.indices = std::vector<unsigned char>(); data.indices = std::vector<unsigned int>();
return true; return true;
} }
static void append_vertex(GLModel::Geometry& data, const Vec3f& position, const Vec3f& normal)
{
data.add_vertex(position, normal);
}
static void append_triangle(GLModel::Geometry& data, unsigned short v1, unsigned short v2, unsigned short v3)
{
data.add_ushort_index(v1);
data.add_ushort_index(v2);
data.add_ushort_index(v3);
}
template<typename Fn> template<typename Fn>
inline bool all_vertices_inside(const GLModel::Geometry& geometry, Fn fn) inline bool all_vertices_inside(const GLModel::Geometry& geometry, Fn fn)
{ {
@ -907,13 +791,12 @@ bool contains(const BuildVolume& volume, const GLModel& model, bool ignore_botto
} }
} }
GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height) GLModel::Geometry stilized_arrow(unsigned int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
{ {
resolution = std::max<unsigned short>(4, resolution); resolution = std::max<unsigned int>(4, resolution);
resolution = std::min<unsigned short>(10922, resolution); // ensure no unsigned short overflow of indices
GLModel::Geometry data; GLModel::Geometry data;
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
data.reserve_vertices(6 * resolution + 2); data.reserve_vertices(6 * resolution + 2);
data.reserve_indices(6 * resolution * 3); data.reserve_indices(6 * resolution * 3);
@ -921,7 +804,7 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl
std::vector<float> cosines(resolution); std::vector<float> cosines(resolution);
std::vector<float> sines(resolution); std::vector<float> sines(resolution);
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const float angle = angle_step * float(i); const float angle = angle_step * float(i);
cosines[i] = ::cos(angle); cosines[i] = ::cos(angle);
sines[i] = -::sin(angle); sines[i] = -::sin(angle);
@ -930,75 +813,74 @@ GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, fl
const float total_height = tip_height + stem_height; const float total_height = tip_height + stem_height;
// tip vertices/normals // tip vertices/normals
append_vertex(data, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, 0.0f, total_height), (Vec3f)Vec3f::UnitZ());
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); data.add_vertex(Vec3f(tip_radius * sines[i], tip_radius * cosines[i], stem_height), Vec3f(sines[i], cosines[i], 0.0f));
} }
// tip triangles // tip triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short v3 = (i < resolution - 1) ? i + 2 : 1; const unsigned int v3 = (i < resolution - 1) ? i + 2 : 1;
append_triangle(data, 0, i + 1, v3); data.add_triangle(0, i + 1, v3);
} }
// tip cap outer perimeter vertices // tip cap outer perimeter vertices
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(tip_radius * sines[i], tip_radius * cosines[i], stem_height), (Vec3f)(-Vec3f::UnitZ()));
} }
// tip cap inner perimeter vertices // tip cap inner perimeter vertices
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(stem_radius * sines[i], stem_radius * cosines[i], stem_height), (Vec3f)(-Vec3f::UnitZ()));
} }
// tip cap triangles // tip cap triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1; const unsigned int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
const unsigned short v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1; const unsigned int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
append_triangle(data, i + resolution + 1, v3, v2); data.add_triangle(i + resolution + 1, v3, v2);
append_triangle(data, i + resolution + 1, i + 2 * resolution + 1, v3); data.add_triangle(i + resolution + 1, i + 2 * resolution + 1, v3);
} }
// stem bottom vertices // stem bottom vertices
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f }); data.add_vertex(Vec3f(stem_radius * sines[i], stem_radius * cosines[i], stem_height), Vec3f(sines[i], cosines[i], 0.0f));
} }
// stem top vertices // stem top vertices
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f }); data.add_vertex(Vec3f(stem_radius * sines[i], stem_radius * cosines[i], 0.0f), Vec3f(sines[i], cosines[i], 0.0f));
} }
// stem triangles // stem triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1; const unsigned int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
const unsigned short v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1; const unsigned int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
append_triangle(data, i + 3 * resolution + 1, v3, v2); data.add_triangle(i + 3 * resolution + 1, v3, v2);
append_triangle(data, i + 3 * resolution + 1, i + 4 * resolution + 1, v3); data.add_triangle(i + 3 * resolution + 1, i + 4 * resolution + 1, v3);
} }
// stem cap vertices // stem cap vertices
append_vertex(data, Vec3f::Zero(), -Vec3f::UnitZ()); data.add_vertex((Vec3f)Vec3f::Zero(), (Vec3f)(-Vec3f::UnitZ()));
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(stem_radius * sines[i], stem_radius * cosines[i], 0.0f), (Vec3f)(-Vec3f::UnitZ()));
} }
// stem cap triangles // stem cap triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2; const unsigned int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
append_triangle(data, 5 * resolution + 1, v3, i + 5 * resolution + 2); data.add_triangle(5 * resolution + 1, v3, i + 5 * resolution + 2);
} }
return data; return data;
} }
GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness) GLModel::Geometry circular_arrow(unsigned int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
{ {
resolution = std::max<unsigned short>(2, resolution); resolution = std::max<unsigned int>(2, resolution);
resolution = std::min<unsigned short>(8188, resolution); // ensure no unsigned short overflow of indices
GLModel::Geometry data; GLModel::Geometry data;
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
data.reserve_vertices(8 * (resolution + 1) + 30); data.reserve_vertices(8 * (resolution + 1) + 30);
data.reserve_indices((8 * resolution + 16) * 3); data.reserve_indices((8 * resolution + 16) * 3);
@ -1012,146 +894,146 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float
// tip // tip
// top face vertices // top face vertices
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, outer_radius, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { -tip_height, radius, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(-tip_height, radius, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, inner_radius, half_thickness), (Vec3f)Vec3f::UnitZ());
// top face triangles // top face triangles
append_triangle(data, 0, 1, 2); data.add_triangle(0, 1, 2);
append_triangle(data, 0, 2, 4); data.add_triangle(0, 2, 4);
append_triangle(data, 4, 2, 3); data.add_triangle(4, 2, 3);
// bottom face vertices // bottom face vertices
append_vertex(data, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, outer_radius, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(-tip_height, radius, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, inner_radius, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
// bottom face triangles // bottom face triangles
append_triangle(data, 5, 7, 6); data.add_triangle(5, 7, 6);
append_triangle(data, 5, 9, 7); data.add_triangle(5, 9, 7);
append_triangle(data, 9, 8, 7); data.add_triangle(9, 8, 7);
// side faces vertices // side faces vertices
append_vertex(data, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, outer_radius, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, outer_radius, half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, half_thickness), (Vec3f)Vec3f::UnitX());
Vec3f normal(-half_tip_width, tip_height, 0.0f); Vec3f normal(-half_tip_width, tip_height, 0.0f);
normal.normalize(); normal.normalize();
append_vertex(data, { 0.0f, radius + half_tip_width, -half_thickness }, normal); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, -half_thickness), normal);
append_vertex(data, { -tip_height, radius, -half_thickness }, normal); data.add_vertex(Vec3f(-tip_height, radius, -half_thickness), normal);
append_vertex(data, { 0.0f, radius + half_tip_width, half_thickness }, normal); data.add_vertex(Vec3f(0.0f, radius + half_tip_width, half_thickness), normal);
append_vertex(data, { -tip_height, radius, half_thickness }, normal); data.add_vertex(Vec3f(-tip_height, radius, half_thickness), normal);
normal = { -half_tip_width, -tip_height, 0.0f }; normal = { -half_tip_width, -tip_height, 0.0f };
normal.normalize(); normal.normalize();
append_vertex(data, { -tip_height, radius, -half_thickness }, normal); data.add_vertex(Vec3f(-tip_height, radius, -half_thickness), normal);
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, normal); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, -half_thickness), normal);
append_vertex(data, { -tip_height, radius, half_thickness }, normal); data.add_vertex(Vec3f(-tip_height, radius, half_thickness), normal);
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, normal); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, half_thickness), normal);
append_vertex(data, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, inner_radius, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, radius - half_tip_width, half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(0.0f, inner_radius, half_thickness), (Vec3f)Vec3f::UnitX());
// side face triangles // side face triangles
for (unsigned short i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
const unsigned short ii = i * 4; const unsigned int ii = i * 4;
append_triangle(data, 10 + ii, 11 + ii, 13 + ii); data.add_triangle(10 + ii, 11 + ii, 13 + ii);
append_triangle(data, 10 + ii, 13 + ii, 12 + ii); data.add_triangle(10 + ii, 13 + ii, 12 + ii);
} }
// stem // stem
// top face vertices // top face vertices
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness), (Vec3f)Vec3f::UnitZ());
} }
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness), (Vec3f)Vec3f::UnitZ());
} }
// top face triangles // top face triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_triangle(data, 26 + i, 27 + i, 27 + resolution + i); data.add_triangle(26 + i, 27 + i, 27 + resolution + i);
append_triangle(data, 27 + i, 28 + resolution + i, 27 + resolution + i); data.add_triangle(27 + i, 28 + resolution + i, 27 + resolution + i);
} }
// bottom face vertices // bottom face vertices
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
} }
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
} }
// bottom face triangles // bottom face triangles
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_triangle(data, 28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i); data.add_triangle(28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
append_triangle(data, 29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i); data.add_triangle(29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
} }
// side faces vertices and triangles // side faces vertices and triangles
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
const float c = ::cos(angle); const float c = ::cos(angle);
const float s = ::sin(angle); const float s = ::sin(angle);
append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f }); data.add_vertex(Vec3f(inner_radius * s, inner_radius * c, -half_thickness), Vec3f(-s, -c, 0.0f));
} }
for (unsigned short i = 0; i <= resolution; ++i) { for (unsigned int i = 0; i <= resolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
const float c = ::cos(angle); const float c = ::cos(angle);
const float s = ::sin(angle); const float s = ::sin(angle);
append_vertex(data, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f }); data.add_vertex(Vec3f(inner_radius * s, inner_radius * c, half_thickness), Vec3f(-s, -c, 0.0f));
} }
unsigned short first_id = 26 + 4 * (resolution + 1); unsigned int first_id = 26 + 4 * (resolution + 1);
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short ii = first_id + i; const unsigned int ii = first_id + i;
append_triangle(data, ii, ii + 1, ii + resolution + 2); data.add_triangle(ii, ii + 1, ii + resolution + 2);
append_triangle(data, ii, ii + resolution + 2, ii + resolution + 1); data.add_triangle(ii, ii + resolution + 2, ii + resolution + 1);
} }
append_vertex(data, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(inner_radius, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(outer_radius, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(inner_radius, 0.0f, half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { outer_radius, 0.0f, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(outer_radius, 0.0f, half_thickness), (Vec3f)(-Vec3f::UnitY()));
first_id = 26 + 6 * (resolution + 1); first_id = 26 + 6 * (resolution + 1);
append_triangle(data, first_id, first_id + 1, first_id + 3); data.add_triangle(first_id, first_id + 1, first_id + 3);
append_triangle(data, first_id, first_id + 3, first_id + 2); data.add_triangle(first_id, first_id + 3, first_id + 2);
for (short i = resolution; i >= 0; --i) { for (int i = resolution; i >= 0; --i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
const float c = ::cos(angle); const float c = ::cos(angle);
const float s = ::sin(angle); const float s = ::sin(angle);
append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f }); data.add_vertex(Vec3f(outer_radius * s, outer_radius * c, -half_thickness), Vec3f(s, c, 0.0f));
} }
for (short i = resolution; i >= 0; --i) { for (int i = resolution; i >= 0; --i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
const float c = ::cos(angle); const float c = ::cos(angle);
const float s = ::sin(angle); const float s = ::sin(angle);
append_vertex(data, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f }); data.add_vertex(Vec3f(outer_radius * s, outer_radius * c, +half_thickness), Vec3f(s, c, 0.0f));
} }
first_id = 30 + 6 * (resolution + 1); first_id = 30 + 6 * (resolution + 1);
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
const unsigned short ii = first_id + i; const unsigned int ii = first_id + i;
append_triangle(data, ii, ii + 1, ii + resolution + 2); data.add_triangle(ii, ii + 1, ii + resolution + 2);
append_triangle(data, ii, ii + resolution + 2, ii + resolution + 1); data.add_triangle(ii, ii + resolution + 2, ii + resolution + 1);
} }
return data; return data;
@ -1160,7 +1042,7 @@ GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float
GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness) GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
{ {
GLModel::Geometry data; GLModel::Geometry data;
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
data.reserve_vertices(42); data.reserve_vertices(42);
data.reserve_indices(72); data.reserve_indices(72);
@ -1170,122 +1052,121 @@ GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_w
const float total_height = tip_height + stem_height; const float total_height = tip_height + stem_height;
// top face vertices // top face vertices
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(half_stem_width, 0.0f, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(half_stem_width, stem_height, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(half_tip_width, stem_height, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { 0.0, total_height, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, total_height, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_tip_width, stem_height, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_stem_width, stem_height, half_thickness), (Vec3f)Vec3f::UnitZ());
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, half_thickness), (Vec3f)Vec3f::UnitZ());
// top face triangles // top face triangles
append_triangle(data, 0, 1, 6); data.add_triangle(0, 1, 6);
append_triangle(data, 6, 1, 5); data.add_triangle(6, 1, 5);
append_triangle(data, 4, 5, 3); data.add_triangle(4, 5, 3);
append_triangle(data, 5, 1, 3); data.add_triangle(5, 1, 3);
append_triangle(data, 1, 2, 3); data.add_triangle(1, 2, 3);
// bottom face vertices // bottom face vertices
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(half_stem_width, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(half_stem_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(half_tip_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(0.0f, total_height, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_tip_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_stem_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitZ()));
// bottom face triangles // bottom face triangles
append_triangle(data, 7, 13, 8); data.add_triangle(7, 13, 8);
append_triangle(data, 13, 12, 8); data.add_triangle(13, 12, 8);
append_triangle(data, 12, 11, 10); data.add_triangle(12, 11, 10);
append_triangle(data, 8, 12, 10); data.add_triangle(8, 12, 10);
append_triangle(data, 9, 8, 10); data.add_triangle(9, 8, 10);
// side faces vertices // side faces vertices
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(half_stem_width, 0.0f, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(half_stem_width, stem_height, -half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(half_stem_width, 0.0f, half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitX()); data.add_vertex(Vec3f(half_stem_width, stem_height, half_thickness), (Vec3f)Vec3f::UnitX());
append_vertex(data, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_stem_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_tip_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_stem_width, stem_height, half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_tip_width, stem_height, half_thickness), (Vec3f)(-Vec3f::UnitY()));
Vec3f normal(tip_height, half_tip_width, 0.0f); Vec3f normal(tip_height, half_tip_width, 0.0f);
normal.normalize(); normal.normalize();
append_vertex(data, { half_tip_width, stem_height, -half_thickness }, normal); data.add_vertex(Vec3f(half_tip_width, stem_height, -half_thickness), normal);
append_vertex(data, { 0.0, total_height, -half_thickness }, normal); data.add_vertex(Vec3f(0.0f, total_height, -half_thickness), normal);
append_vertex(data, { half_tip_width, stem_height, half_thickness }, normal); data.add_vertex(Vec3f(half_tip_width, stem_height, half_thickness), normal);
append_vertex(data, { 0.0, total_height, half_thickness }, normal); data.add_vertex(Vec3f(0.0f, total_height, half_thickness), normal);
normal = { -tip_height, half_tip_width, 0.0f }; normal = { -tip_height, half_tip_width, 0.0f };
normal.normalize(); normal.normalize();
append_vertex(data, { 0.0, total_height, -half_thickness }, normal); data.add_vertex(Vec3f(0.0f, total_height, -half_thickness), normal);
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, normal); data.add_vertex(Vec3f(-half_tip_width, stem_height, -half_thickness), normal);
append_vertex(data, { 0.0, total_height, half_thickness }, normal); data.add_vertex(Vec3f(0.0f, total_height, half_thickness), normal);
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, normal); data.add_vertex(Vec3f(-half_tip_width, stem_height, half_thickness), normal);
append_vertex(data, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_tip_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_stem_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_tip_width, stem_height, half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_stem_width, stem_height, half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX()); data.add_vertex(Vec3f(-half_stem_width, stem_height, -half_thickness), (Vec3f)(-Vec3f::UnitX()));
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitX()));
append_vertex(data, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX()); data.add_vertex(Vec3f(-half_stem_width, stem_height, half_thickness), (Vec3f)(-Vec3f::UnitX()));
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, half_thickness), (Vec3f)(-Vec3f::UnitX()));
append_vertex(data, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_stem_width, 0.0f, -half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(-half_stem_width, 0.0f, half_thickness), (Vec3f)(-Vec3f::UnitY()));
append_vertex(data, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY()); data.add_vertex(Vec3f(half_stem_width, 0.0f, half_thickness), (Vec3f)(-Vec3f::UnitY()));
// side face triangles // side face triangles
for (unsigned short i = 0; i < 7; ++i) { for (unsigned int i = 0; i < 7; ++i) {
const unsigned short ii = i * 4; const unsigned int ii = i * 4;
append_triangle(data, 14 + ii, 15 + ii, 17 + ii); data.add_triangle(14 + ii, 15 + ii, 17 + ii);
append_triangle(data, 14 + ii, 17 + ii, 16 + ii); data.add_triangle(14 + ii, 17 + ii, 16 + ii);
} }
return data; return data;
} }
GLModel::Geometry diamond(unsigned short resolution) GLModel::Geometry diamond(unsigned int resolution)
{ {
resolution = std::max<unsigned short>(4, resolution); resolution = std::max<unsigned int>(4, resolution);
resolution = std::min<unsigned short>(65534, resolution); // ensure no unsigned short overflow of indices
GLModel::Geometry data; GLModel::Geometry data;
data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::USHORT }; data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
data.reserve_vertices(resolution + 2); data.reserve_vertices(resolution + 2);
data.reserve_indices((2 * (resolution + 1)) * 3); data.reserve_indices((2 * (resolution + 1)) * 3);
const float step = 2.0f * float(PI) / float(resolution); const float step = 2.0f * float(PI) / float(resolution);
// vertices // vertices
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int 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 }; const Vec3f p = { 0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f };
append_vertex(data, p, p.normalized()); data.add_vertex(p, (Vec3f)p.normalized());
} }
Vec3f p = { 0.0f, 0.0f, 0.5f }; Vec3f p = { 0.0f, 0.0f, 0.5f };
append_vertex(data, p, p.normalized()); data.add_vertex(p, (Vec3f)p.normalized());
p = { 0.0f, 0.0f, -0.5f }; p = { 0.0f, 0.0f, -0.5f };
append_vertex(data, p, p.normalized()); data.add_vertex(p, (Vec3f)p.normalized());
// triangles // triangles
// top // top
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_triangle(data, i + 0, i + 1, resolution); data.add_triangle(i + 0, i + 1, resolution);
} }
append_triangle(data, resolution - 1, 0, resolution); data.add_triangle(resolution - 1, 0, resolution);
// bottom // bottom
for (unsigned short i = 0; i < resolution; ++i) { for (unsigned int i = 0; i < resolution; ++i) {
append_triangle(data, i + 0, resolution + 1, i + 1); data.add_triangle(i + 0, resolution + 1, i + 1);
} }
append_triangle(data, resolution - 1, resolution + 1, 0); data.add_triangle(resolution - 1, resolution + 1, 0);
return data; return data;
} }

View file

@ -46,23 +46,25 @@ namespace GUI {
enum class EIndexType : unsigned char enum class EIndexType : unsigned char
{ {
UINT, // unsigned int UINT, // unsigned int
USHORT // unsigned short USHORT, // unsigned short
UBYTE // unsigned byte
}; };
struct Format struct Format
{ {
EPrimitiveType type{ EPrimitiveType::Triangles }; EPrimitiveType type{ EPrimitiveType::Triangles };
EVertexLayout vertex_layout{ EVertexLayout::P3N3 }; EVertexLayout vertex_layout{ EVertexLayout::P3N3 };
EIndexType index_type{ EIndexType::UINT };
}; };
Format format; Format format;
std::vector<float> vertices; std::vector<float> vertices;
std::vector<unsigned char> indices; std::vector<unsigned int> indices;
EIndexType index_type{ EIndexType::UINT };
ColorRGBA color{ ColorRGBA::BLACK() }; ColorRGBA color{ ColorRGBA::BLACK() };
void reserve_vertices(size_t vertices_count); void reserve_vertices(size_t vertices_count) { vertices.reserve(vertices_count * vertex_stride_floats(format)); }
void reserve_indices(size_t indices_count); void reserve_indices(size_t indices_count) { indices.reserve(indices_count * index_stride_bytes(*this)); }
void add_vertex(const Vec2f& position); // EVertexLayout::P2 void add_vertex(const Vec2f& position); // EVertexLayout::P2
void add_vertex(const Vec2f& position, const Vec2f& tex_coord); // EVertexLayout::P2T2 void add_vertex(const Vec2f& position, const Vec2f& tex_coord); // EVertexLayout::P2T2
@ -72,36 +74,29 @@ namespace GUI {
void set_vertex(size_t id, const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3 void set_vertex(size_t id, const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3
void set_ushort_index(size_t id, unsigned short index); void set_index(size_t id, unsigned int index);
void set_uint_index(size_t id, unsigned int index);
void add_ushort_index(unsigned short id); void add_index(unsigned int id);
void add_uint_index(unsigned int id); void add_line(unsigned int id1, unsigned int id2);
void add_triangle(unsigned int id1, unsigned int id2, unsigned int id3);
void add_ushort_line(unsigned short id1, unsigned short id2);
void add_uint_line(unsigned int id1, unsigned int id2);
void add_ushort_triangle(unsigned short id1, unsigned short id2, unsigned short id3);
void add_uint_triangle(unsigned int id1, unsigned int id2, unsigned int id3);
Vec2f extract_position_2(size_t id) const; Vec2f extract_position_2(size_t id) const;
Vec3f extract_position_3(size_t id) const; Vec3f extract_position_3(size_t id) const;
Vec3f extract_normal_3(size_t id) const; Vec3f extract_normal_3(size_t id) const;
Vec2f extract_tex_coord_2(size_t id) const; Vec2f extract_tex_coord_2(size_t id) const;
unsigned int extract_uint_index(size_t id) const; unsigned int extract_index(size_t id) const;
unsigned short extract_ushort_index(size_t id) const;
void remove_vertex(size_t id); void remove_vertex(size_t id);
bool is_empty() const { return vertices_count() == 0 || indices_count() == 0; } bool is_empty() const { return vertices_count() == 0 || indices_count() == 0; }
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); } size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
size_t indices_count() const { return indices.size() / index_stride_bytes(format); } size_t indices_count() const { return indices.size(); }
size_t vertices_size_floats() const { return vertices.size(); } size_t vertices_size_floats() const { return vertices.size(); }
size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); }
size_t indices_size_bytes() const { return indices.size(); } size_t indices_size_bytes() const { return indices.size() * index_stride_bytes(*this); }
static size_t vertex_stride_floats(const Format& format); static size_t vertex_stride_floats(const Format& format);
static size_t vertex_stride_bytes(const Format& format) { return vertex_stride_floats(format) * sizeof(float); } static size_t vertex_stride_bytes(const Format& format) { return vertex_stride_floats(format) * sizeof(float); }
@ -121,9 +116,7 @@ namespace GUI {
static size_t tex_coord_offset_floats(const Format& format); static size_t tex_coord_offset_floats(const Format& format);
static size_t tex_coord_offset_bytes(const Format& format) { return tex_coord_offset_floats(format) * sizeof(float); } static size_t tex_coord_offset_bytes(const Format& format) { return tex_coord_offset_floats(format) * sizeof(float); }
static size_t index_stride_bytes(const Format& format); static size_t index_stride_bytes(const Geometry& data);
static EIndexType index_type(size_t vertices_count);
static bool has_position(const Format& format); static bool has_position(const Format& format);
static bool has_normal(const Format& format); static bool has_normal(const Format& format);
@ -164,9 +157,10 @@ namespace GUI {
size_t vertices_size_floats() const { return vertices_count() * Geometry::vertex_stride_floats(m_render_data.geometry.format); } size_t vertices_size_floats() const { return vertices_count() * Geometry::vertex_stride_floats(m_render_data.geometry.format); }
size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); }
size_t indices_size_bytes() const { return indices_count() * Geometry::index_stride_bytes(m_render_data.geometry.format); } size_t indices_size_bytes() const { return indices_count() * Geometry::index_stride_bytes(m_render_data.geometry); }
const Geometry& get_geometry() const { return m_render_data.geometry; } const Geometry& get_geometry() const { return m_render_data.geometry; }
void init_from(Geometry&& data); void init_from(Geometry&& data);
void init_from(const TriangleMesh& mesh); void init_from(const TriangleMesh& mesh);
void init_from(const indexed_triangle_set& its); void init_from(const indexed_triangle_set& its);
@ -217,13 +211,13 @@ namespace GUI {
// the origin of the arrow is in the center of the stem cap // the origin of the arrow is in the center of the stem cap
// the arrow has its axis of symmetry along the Z axis and is pointing upward // the arrow has its axis of symmetry along the Z axis and is pointing upward
// used to render bed axes and sequential marker // used to render bed axes and sequential marker
GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height); GLModel::Geometry stilized_arrow(unsigned int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height);
// create an arrow whose stem is a quarter of circle, with the given dimensions and resolution // create an arrow whose stem is a quarter of circle, with the given dimensions and resolution
// the origin of the arrow is in the center of the circle // the origin of the arrow is in the center of the circle
// the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise // the arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise
// used to render sidebar hints for rotations // used to render sidebar hints for rotations
GLModel::Geometry circular_arrow(unsigned short resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness); GLModel::Geometry circular_arrow(unsigned int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness);
// create an arrow with the given dimensions // create an arrow with the given dimensions
// the origin of the arrow is in the center of the stem cap // the origin of the arrow is in the center of the stem cap
@ -234,7 +228,7 @@ namespace GUI {
// create a diamond with the given resolution // create a diamond with the given resolution
// the origin of the diamond is in its center // the origin of the diamond is in its center
// the diamond is contained into a box with size [1, 1, 1] // the diamond is contained into a box with size [1, 1, 1]
GLModel::Geometry diamond(unsigned short resolution); GLModel::Geometry diamond(unsigned int resolution);
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -74,40 +74,28 @@ namespace GUI {
if (!is_dragging()) if (!is_dragging())
return; return;
const Camera& camera = wxGetApp().plater()->get_camera(); const Size cnv_size = canvas.get_canvas_size();
float inv_zoom = (float)camera.get_inv_zoom(); const float cnv_width = (float)cnv_size.get_width();
const float cnv_height = (float)cnv_size.get_height();
Size cnv_size = canvas.get_canvas_size(); if (cnv_width == 0.0f || cnv_height == 0.0f)
float cnv_half_width = 0.5f * (float)cnv_size.get_width();
float cnv_half_height = 0.5f * (float)cnv_size.get_height();
if (cnv_half_width == 0.0f || cnv_half_height == 0.0f)
return; return;
Vec2d start(m_start_corner(0) - cnv_half_width, cnv_half_height - m_start_corner(1)); const float cnv_inv_width = 1.0f / cnv_width;
Vec2d end(m_end_corner(0) - cnv_half_width, cnv_half_height - m_end_corner(1)); const float cnv_inv_height = 1.0f / cnv_height;
const float left = 2.0f * (get_left() * cnv_inv_width - 0.5f);
const float left = (float)std::min(start(0), end(0)) * inv_zoom; const float right = 2.0f * (get_right() * cnv_inv_width - 0.5f);
const float top = (float)std::max(start(1), end(1)) * inv_zoom; const float top = -2.0f * (get_top() * cnv_inv_height - 0.5f);
const float right = (float)std::max(start(0), end(0)) * inv_zoom; const float bottom = -2.0f * (get_bottom() * cnv_inv_height - 0.5f);
const float bottom = (float)std::min(start(1), end(1)) * inv_zoom;
glsafe(::glLineWidth(1.5f)); glsafe(::glLineWidth(1.5f));
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
// ensure that the rectangle is renderered inside the frustrum
glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5)));
// ensure that the overlay fits the frustrum near z plane
const double gui_scale = camera.get_gui_scale();
glsafe(::glScaled(gui_scale, gui_scale, 1.0));
glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glPushAttrib(GL_ENABLE_BIT));
glsafe(::glLineStipple(4, 0xAAAA)); glsafe(::glLineStipple(4, 0xAAAA));
glsafe(::glEnable(GL_LINE_STIPPLE)); glsafe(::glEnable(GL_LINE_STIPPLE));
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
@ -117,7 +105,7 @@ namespace GUI {
m_rectangle.reset(); m_rectangle.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(4); init_data.reserve_indices(4);
@ -128,23 +116,23 @@ namespace GUI {
init_data.add_vertex(Vec2f(left, top)); init_data.add_vertex(Vec2f(left, top));
// indices // indices
init_data.add_ushort_index(0); init_data.add_index(0);
init_data.add_ushort_index(1); init_data.add_index(1);
init_data.add_ushort_index(2); init_data.add_index(2);
init_data.add_ushort_index(3); init_data.add_index(3);
m_rectangle.init_from(std::move(init_data)); m_rectangle.init_from(std::move(init_data));
} }
const ColorRGBA color(0.0f, 1.0f, 0.38f, 1.0f); shader->set_uniform("view_model_matrix", Transform3d::Identity());
m_rectangle.set_color(color); shader->set_uniform("projection_matrix", Transform3d::Identity());
m_rectangle.set_color({0.0f, 1.0f, 0.38f, 1.0f});
m_rectangle.render(); m_rectangle.render();
shader->stop_using(); shader->stop_using();
} }
glsafe(::glPopAttrib()); glsafe(::glPopAttrib());
glsafe(::glPopMatrix());
} }
} // namespace GUI } // namespace GUI

View file

@ -36,12 +36,12 @@ public:
bool is_dragging() const { return m_state != Off; } bool is_dragging() const { return m_state != Off; }
EState get_state() const { return m_state; } EState get_state() const { return m_state; }
float get_width() const { return std::abs(m_start_corner(0) - m_end_corner(0)); } float get_width() const { return std::abs(m_start_corner.x() - m_end_corner.x()); }
float get_height() const { return std::abs(m_start_corner(1) - m_end_corner(1)); } float get_height() const { return std::abs(m_start_corner.y() - m_end_corner.y()); }
float get_left() const { return std::min(m_start_corner(0), m_end_corner(0)); } float get_left() const { return std::min(m_start_corner.x(), m_end_corner.x()); }
float get_right() const { return std::max(m_start_corner(0), m_end_corner(0)); } float get_right() const { return std::max(m_start_corner.x(), m_end_corner.x()); }
float get_top() const { return std::max(m_start_corner(1), m_end_corner(1)); } float get_top() const { return std::max(m_start_corner.y(), m_end_corner.y()); }
float get_bottom() const { return std::min(m_start_corner(1), m_end_corner(1)); } float get_bottom() const { return std::min(m_start_corner.y(), m_end_corner.y()); }
private: private:
EState m_state{ Off }; EState m_state{ Off };

View file

@ -296,6 +296,11 @@ void GLShaderProgram::set_uniform(int id, const Matrix3f& value) const
glsafe(::glUniformMatrix3fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.data()))); glsafe(::glUniformMatrix3fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.data())));
} }
void GLShaderProgram::set_uniform(int id, const Matrix3d& value) const
{
set_uniform(id, (Matrix3f)value.cast<float>());
}
void GLShaderProgram::set_uniform(int id, const Vec3f& value) const void GLShaderProgram::set_uniform(int id, const Vec3f& value) const
{ {
if (id >= 0) if (id >= 0)

View file

@ -60,6 +60,7 @@ public:
void set_uniform(const char* name, const Transform3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Transform3f& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Transform3d& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Transform3d& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Matrix3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Matrix3f& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Matrix3d& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); }
void set_uniform(const char* name, const ColorRGB& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const ColorRGB& value) const { set_uniform(get_uniform_location(name), value); }
@ -79,6 +80,7 @@ public:
void set_uniform(int id, const Transform3f& value) const; void set_uniform(int id, const Transform3f& value) const;
void set_uniform(int id, const Transform3d& value) const; void set_uniform(int id, const Transform3d& value) const;
void set_uniform(int id, const Matrix3f& value) const; void set_uniform(int id, const Matrix3f& value) const;
void set_uniform(int id, const Matrix3d& value) const;
void set_uniform(int id, const Vec3f& value) const; void set_uniform(int id, const Vec3f& value) const;
void set_uniform(int id, const Vec3d& value) const; void set_uniform(int id, const Vec3d& value) const;
void set_uniform(int id, const ColorRGB& value) const; void set_uniform(int id, const ColorRGB& value) const;

View file

@ -34,25 +34,22 @@ std::pair<bool, std::string> GLShadersManager::init()
bool valid = true; bool valid = true;
// basic shader, used to render all what was previously rendered using the immediate mode // basic shader, used to render all what was previously rendered using the immediate mode
valid &= append_shader("flat", { "flat.vs", "flat.fs" });
valid &= append_shader("flat_attr", { "flat_attr.vs", "flat.fs" }); valid &= append_shader("flat_attr", { "flat_attr.vs", "flat.fs" });
// basic shader for textures, used to render textures // basic shader for textures, used to render textures
valid &= append_shader("flat_texture", { "flat_texture.vs", "flat_texture.fs" }); valid &= append_shader("flat_texture_attr", { "flat_texture_attr.vs", "flat_texture.fs" });
// used to render 3D scene background // used to render 3D scene background
valid &= append_shader("background", { "background.vs", "background.fs" }); valid &= append_shader("background_attr", { "background_attr.vs", "background.fs" });
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview // 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" }); valid &= append_shader("gouraud_light_attr", { "gouraud_light_attr.vs", "gouraud_light.fs" });
//used to render thumbnail //used to render thumbnail
valid &= append_shader("thumbnail", { "thumbnail.vs", "thumbnail.fs" }); valid &= append_shader("thumbnail_attr", {"thumbnail_attr.vs", "thumbnail.fs"});
// used to render first layer for calibration valid &= append_shader("thumbnail", {"thumbnail.vs", "thumbnail.fs"});
valid &= append_shader("cali", { "cali.vs", "cali.fs"});
// used to render printbed // used to render printbed
valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); valid &= append_shader("printbed_attr", { "printbed_attr.vs", "printbed.fs" });
// used to render options in gcode preview // used to render options in gcode preview
if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); valid &= append_shader("gouraud_light_instanced_attr", { "gouraud_light_instanced_attr.vs", "gouraud_light_instanced.fs" });
// used to render extrusion and travel paths as lines in gcode preview }
valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" });
// used to render objects in 3d editor // used to render objects in 3d editor
//if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) { //if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) {
@ -64,34 +61,26 @@ std::pair<bool, std::string> GLShadersManager::init()
); );
} }
else { else {
valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" } valid &= append_shader("gouraud_attr", { "gouraud_attr.vs", "gouraud.fs" }
#if ENABLE_ENVIRONMENT_MAP #if ENABLE_ENVIRONMENT_MAP
, { "ENABLE_ENVIRONMENT_MAP"sv } , { "ENABLE_ENVIRONMENT_MAP"sv }
#endif // ENABLE_ENVIRONMENT_MAP #endif // ENABLE_ENVIRONMENT_MAP
); );
} }
// used to render variable layers heights in 3d editor // used to render variable layers heights in 3d editor
valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" }); valid &= append_shader("variable_layer_height_attr", { "variable_layer_height_attr.vs", "variable_layer_height.fs" });
// used to render highlight contour around selected triangles inside the multi-material gizmo // used to render highlight contour around selected triangles inside the multi-material gizmo
valid &= append_shader("mm_contour", { "mm_contour.vs", "mm_contour.fs" }); valid &= append_shader("mm_contour_attr", { "mm_contour_attr.vs", "mm_contour_attr.fs" });
// Used to render painted triangles inside the multi-material gizmo. Triangle normals are computed inside fragment shader. // Used to render painted triangles inside the multi-material gizmo. Triangle normals are computed inside fragment shader.
// For Apple's on Arm CPU computed triangle normals inside fragment shader using dFdx and dFdy has the opposite direction. // For Apple's on Arm CPU computed triangle normals inside fragment shader using dFdx and dFdy has the opposite direction.
// Because of this, objects had darker colors inside the multi-material gizmo. // Because of this, objects had darker colors inside the multi-material gizmo.
// Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU. // Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU.
// Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed // Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed
// triangle normals inside fragment shader have the right direction. // triangle normals inside fragment shader have the right direction.
if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) { if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
//if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled()) valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" }, { "FLIP_TRIANGLE_NORMALS"sv });
// valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); else
//else valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" });
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
}
else {
//if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled())
// valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"});
//else
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"});
}
//BBS: add shader for outline //BBS: add shader for outline
valid &= append_shader("outline", { "outline.vs", "outline.fs" }); valid &= append_shader("outline", { "outline.vs", "outline.fs" });

View file

@ -663,7 +663,7 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id)); glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id));
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(6); init_data.reserve_indices(6);
@ -674,15 +674,17 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
init_data.add_vertex(Vec2f(left, top), Vec2f(uvs.left_top.u, uvs.left_top.v)); init_data.add_vertex(Vec2f(left, top), Vec2f(uvs.left_top.u, uvs.left_top.v));
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
GLModel model; GLModel model;
model.init_from(std::move(init_data)); model.init_from(std::move(init_data));
GLShaderProgram* shader = wxGetApp().get_shader("flat_texture"); GLShaderProgram* shader = wxGetApp().get_shader("flat_texture_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("view_model_matrix", Transform3d::Identity());
shader->set_uniform("projection_matrix", Transform3d::Identity());
model.render(); model.render();
shader->stop_using(); shader->stop_using();
} }

View file

@ -551,18 +551,16 @@ void GLToolbar::render(const GLCanvas3D& parent,GLToolbarItem::EType type)
{ {
default: default:
case Layout::Horizontal: { render_horizontal(parent,type); break; } case Layout::Horizontal: { render_horizontal(parent,type); break; }
case Layout::Vertical: { render_vertical(parent); break; } case Layout::Vertical: { render_vertical(parent); break; }
} }
} }
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
{ {
if (!m_enabled) if (!m_enabled)
return false; return false;
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY()); const Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
bool processed = false; bool processed = false;
// mouse anywhere // mouse anywhere
@ -610,7 +608,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
return false; return false;
} }
int item_id = contains_mouse(mouse_pos, parent); const int item_id = contains_mouse(mouse_pos, parent);
if (item_id != -1) { if (item_id != -1) {
// mouse inside toolbar // mouse inside toolbar
if (evt.LeftDown() || evt.LeftDClick()) { if (evt.LeftDown() || evt.LeftDClick()) {
@ -757,16 +755,12 @@ int GLToolbar::get_visible_items_cnt() const
void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover) void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover)
{ {
if ((m_pressed_toggable_id == -1) || (m_pressed_toggable_id == item_id)) if (m_pressed_toggable_id == -1 || m_pressed_toggable_id == item_id) {
{ if (0 <= item_id && item_id < (int)m_items.size()) {
if ((0 <= item_id) && (item_id < (int)m_items.size()))
{
GLToolbarItem* item = m_items[item_id]; GLToolbarItem* item = m_items[item_id];
if ((item != nullptr) && !item->is_separator() && !item->is_disabled() && (!check_hover || item->is_hovered())) if (item != nullptr && !item->is_separator() && !item->is_disabled() && (!check_hover || item->is_hovered())) {
{ if ((type == GLToolbarItem::Right && item->is_right_toggable()) ||
if (((type == GLToolbarItem::Right) && item->is_right_toggable()) || (type == GLToolbarItem::Left && item->is_left_toggable())) {
((type == GLToolbarItem::Left) && item->is_left_toggable()))
{
GLToolbarItem::EState state = item->get_state(); GLToolbarItem::EState state = item->get_state();
if (state == GLToolbarItem::Hover) if (state == GLToolbarItem::Hover)
item->set_state(GLToolbarItem::HoverPressed); item->set_state(GLToolbarItem::HoverPressed);
@ -784,12 +778,11 @@ void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas
switch (type) switch (type)
{ {
default: default:
case GLToolbarItem::Left: { item->do_left_action(); break; } case GLToolbarItem::Left: { item->do_left_action(); break; }
case GLToolbarItem::Right: { item->do_right_action(); break; } case GLToolbarItem::Right: { item->do_right_action(); break; }
} }
} }
else else {
{
if (m_type == Radio) if (m_type == Radio)
select_item(item->get_name()); select_item(item->get_name());
else else
@ -804,8 +797,7 @@ void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas
case GLToolbarItem::Right: { item->do_right_action(); break; } case GLToolbarItem::Right: { item->do_right_action(); break; }
} }
if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled)) if (m_type == Normal && item->get_state() != GLToolbarItem::Disabled) {
{
// the item may get disabled during the action, if not, set it back to normal state // the item may get disabled during the action, if not, set it back to normal state
item->set_state(GLToolbarItem::Normal); item->set_state(GLToolbarItem::Normal);
parent.render(); parent.render();
@ -825,55 +817,51 @@ void GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
{ {
default: default:
case Layout::Horizontal: { update_hover_state_horizontal(mouse_pos, parent); break; } case Layout::Horizontal: { update_hover_state_horizontal(mouse_pos, parent); break; }
case Layout::Vertical: { update_hover_state_vertical(mouse_pos, parent); break; } case Layout::Vertical: { update_hover_state_vertical(mouse_pos, parent); break; }
} }
} }
void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent) void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
{ {
// NB: mouse_pos is already scaled appropriately const Size cnv_size = parent.get_canvas_size();
const Vec2d scaled_mouse_pos((mouse_pos.x() - 0.5 * (double)cnv_size.get_width()), (0.5 * (double)cnv_size.get_height() - mouse_pos.y()));
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float icons_size = m_layout.icons_size * m_layout.scale;
float factor = m_layout.scale * inv_zoom; const float separator_size = m_layout.separator_size * m_layout.scale;
const float gap_size = m_layout.gap_size * m_layout.scale;
const float border = m_layout.border * m_layout.scale;
Size cnv_size = parent.get_canvas_size(); const float separator_stride = separator_size + gap_size;
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); const float icon_stride = icons_size + gap_size;
float scaled_icons_size = m_layout.icons_size * factor; float left = m_layout.left + border;
float scaled_separator_size = m_layout.separator_size * factor; float top = m_layout.top - border;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float separator_stride = scaled_separator_size + scaled_gap_size; for (GLToolbarItem* item : m_items) {
float icon_stride = scaled_icons_size + scaled_gap_size;
float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border;
for (GLToolbarItem* item : m_items)
{
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
if (item->is_separator()) if (item->is_separator())
left += separator_stride; left += separator_stride;
else else {
{ float right = left + icons_size;
float right = left + scaled_icons_size; const float bottom = top - icons_size;
float bottom = top - scaled_icons_size;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
right += scaled_icons_size * item->get_extra_size_ratio(); right += icons_size * item->get_extra_size_ratio();
GLToolbarItem::EState state = item->get_state();
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); const GLToolbarItem::EState state = item->get_state();
bool inside = (left <= (float)scaled_mouse_pos.x()) &&
((float)scaled_mouse_pos.x() <= right) &&
(bottom <= (float)scaled_mouse_pos.y()) &&
((float)scaled_mouse_pos.y() <= top);
switch (state) switch (state)
{ {
case GLToolbarItem::Normal: case GLToolbarItem::Normal:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::Hover); item->set_state(GLToolbarItem::Hover);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -882,8 +870,7 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
} }
case GLToolbarItem::Hover: case GLToolbarItem::Hover:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Normal); item->set_state(GLToolbarItem::Normal);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -892,8 +879,7 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
} }
case GLToolbarItem::Pressed: case GLToolbarItem::Pressed:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::HoverPressed); item->set_state(GLToolbarItem::HoverPressed);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -902,8 +888,7 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
} }
case GLToolbarItem::HoverPressed: case GLToolbarItem::HoverPressed:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Pressed); item->set_state(GLToolbarItem::Pressed);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -912,8 +897,7 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
} }
case GLToolbarItem::Disabled: case GLToolbarItem::Disabled:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::HoverDisabled); item->set_state(GLToolbarItem::HoverDisabled);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -922,8 +906,7 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
} }
case GLToolbarItem::HoverDisabled: case GLToolbarItem::HoverDisabled:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Disabled); item->set_state(GLToolbarItem::Disabled);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -939,59 +922,55 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D
left += icon_stride; left += icon_stride;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
left += scaled_icons_size * item->get_extra_size_ratio(); left += icons_size * item->get_extra_size_ratio();
} }
} }
} }
void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent) void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent)
{ {
// NB: mouse_pos is already scaled appropriately const Size cnv_size = parent.get_canvas_size();
const Vec2d scaled_mouse_pos((mouse_pos.x() - 0.5 * (double)cnv_size.get_width()), (0.5 * (double)cnv_size.get_height() - mouse_pos.y()));
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float icons_size = m_layout.icons_size * m_layout.scale;
float factor = m_layout.scale * inv_zoom; const float separator_size = m_layout.separator_size * m_layout.scale;
const float gap_size = m_layout.gap_size * m_layout.scale;
const float border = m_layout.border * m_layout.scale;
Size cnv_size = parent.get_canvas_size(); const float separator_stride = separator_size + gap_size;
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); const float icon_stride = icons_size + gap_size;
float scaled_icons_size = m_layout.icons_size * factor; float left = m_layout.left + border;
float scaled_separator_size = m_layout.separator_size * factor; float top = m_layout.top - border;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float separator_stride = scaled_separator_size + scaled_gap_size;
float icon_stride = scaled_icons_size + scaled_gap_size;
float left = m_layout.left + scaled_border; for (GLToolbarItem* item : m_items) {
float top = m_layout.top - scaled_border;
for (GLToolbarItem* item : m_items)
{
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
if (item->is_separator()) if (item->is_separator())
top -= separator_stride; top -= separator_stride;
else else {
{ float right = left + icons_size;
float right = left + scaled_icons_size; const float bottom = top - icons_size;
float bottom = top - scaled_icons_size;
if (item->is_action_with_text_image()) if (item->is_action_with_text_image())
right += m_layout.text_size * factor; right += m_layout.text_size * m_layout.scale;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
right += scaled_icons_size * item->get_extra_size_ratio(); right += icons_size * item->get_extra_size_ratio();
GLToolbarItem::EState state = item->get_state(); GLToolbarItem::EState state = item->get_state();
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); const bool inside = (left <= (float)scaled_mouse_pos.x()) &&
((float)scaled_mouse_pos.x() <= right) &&
(bottom <= (float)scaled_mouse_pos.y()) &&
((float)scaled_mouse_pos.y() <= top);
switch (state) switch (state)
{ {
case GLToolbarItem::Normal: case GLToolbarItem::Normal:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::Hover); item->set_state(GLToolbarItem::Hover);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1000,8 +979,7 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
case GLToolbarItem::Hover: case GLToolbarItem::Hover:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Normal); item->set_state(GLToolbarItem::Normal);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1010,8 +988,7 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
case GLToolbarItem::Pressed: case GLToolbarItem::Pressed:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::HoverPressed); item->set_state(GLToolbarItem::HoverPressed);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1020,8 +997,7 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
case GLToolbarItem::HoverPressed: case GLToolbarItem::HoverPressed:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Pressed); item->set_state(GLToolbarItem::Pressed);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1030,8 +1006,7 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
case GLToolbarItem::Disabled: case GLToolbarItem::Disabled:
{ {
if (inside) if (inside) {
{
item->set_state(GLToolbarItem::HoverDisabled); item->set_state(GLToolbarItem::HoverDisabled);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1040,8 +1015,7 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
case GLToolbarItem::HoverDisabled: case GLToolbarItem::HoverDisabled:
{ {
if (!inside) if (!inside) {
{
item->set_state(GLToolbarItem::Disabled); item->set_state(GLToolbarItem::Disabled);
parent.set_as_dirty(); parent.set_as_dirty();
} }
@ -1083,77 +1057,78 @@ int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent)
{ {
default: default:
case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); } case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); } case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
} }
} }
int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{ {
// NB: mouse_pos is already scaled appropriately const Size cnv_size = parent.get_canvas_size();
const Vec2d scaled_mouse_pos((mouse_pos.x() - 0.5 * (double)cnv_size.get_width()), (0.5 * (double)cnv_size.get_height() - mouse_pos.y()));
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float icons_size = m_layout.icons_size * m_layout.scale;
float factor = m_layout.scale * inv_zoom; const float separator_size = m_layout.separator_size * m_layout.scale;
const float gap_size = m_layout.gap_size * m_layout.scale;
const float border = m_layout.border * m_layout.scale;
Size cnv_size = parent.get_canvas_size(); float left = m_layout.left + border;
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); const float top = m_layout.top - border;
float scaled_icons_size = m_layout.icons_size * factor; for (size_t id = 0; id < m_items.size(); ++id) {
float scaled_separator_size = m_layout.separator_size * factor;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border;
for (size_t id=0; id<m_items.size(); ++id)
{
GLToolbarItem* item = m_items[id]; GLToolbarItem* item = m_items[id];
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
if (item->is_separator()) if (item->is_separator()) {
{ float right = left + separator_size;
float right = left + scaled_separator_size; const float bottom = top - icons_size;
float bottom = top - scaled_icons_size;
// mouse inside the separator // mouse inside the separator
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return id; return id;
left = right; left = right;
right += scaled_gap_size; right += gap_size;
if (id < m_items.size() - 1) if (id < m_items.size() - 1) {
{
// mouse inside the gap // mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return -2; return -2;
} }
left = right; left = right;
} }
else else {
{ float right = left + icons_size;
float right = left + scaled_icons_size; const float bottom = top - icons_size;
float bottom = top - scaled_icons_size;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
right += scaled_icons_size * item->get_extra_size_ratio(); right += icons_size * item->get_extra_size_ratio();
// mouse inside the icon // mouse inside the icon
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return id; return id;
left = right; left = right;
right += scaled_gap_size; right += gap_size;
if (id < m_items.size() - 1) if (id < m_items.size() - 1) {
{
// mouse inside the gap // mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return -2; return -2;
} }
@ -1166,73 +1141,75 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{ {
// NB: mouse_pos is already scaled appropriately const Size cnv_size = parent.get_canvas_size();
const Vec2d scaled_mouse_pos((mouse_pos.x() - 0.5 * (double)cnv_size.get_width()), (0.5 * (double)cnv_size.get_height() - mouse_pos.y()));
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const float icons_size = m_layout.icons_size * m_layout.scale;
float factor = m_layout.scale * inv_zoom; const float separator_size = m_layout.separator_size * m_layout.scale;
const float gap_size = m_layout.gap_size * m_layout.scale;
const float border = m_layout.border * m_layout.scale;
Size cnv_size = parent.get_canvas_size(); const float left = m_layout.left + border;
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); float top = m_layout.top - border;
float scaled_icons_size = m_layout.icons_size * factor; for (size_t id = 0; id < m_items.size(); ++id) {
float scaled_separator_size = m_layout.separator_size * factor;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border;
for (size_t id=0; id<m_items.size(); ++id)
{
GLToolbarItem* item = m_items[id]; GLToolbarItem* item = m_items[id];
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
if (item->is_separator()) if (item->is_separator()) {
{ const float right = left + icons_size;
float right = left + scaled_icons_size; float bottom = top - separator_size;
float bottom = top - scaled_separator_size;
// mouse inside the separator // mouse inside the separator
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return id; return id;
top = bottom; top = bottom;
bottom -= scaled_gap_size; bottom -= gap_size;
if (id < m_items.size() - 1) if (id < m_items.size() - 1) {
{
// mouse inside the gap // mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return -2; return -2;
} }
top = bottom; top = bottom;
} }
else else {
{ float right = left + icons_size;
float right = left + scaled_icons_size; float bottom = top - icons_size;
float bottom = top - scaled_icons_size;
if (item->is_action_with_text_image()) if (item->is_action_with_text_image())
right += m_layout.text_size * factor; right += m_layout.text_size * m_layout.scale;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
right += scaled_icons_size * item->get_extra_size_ratio(); right += icons_size * item->get_extra_size_ratio();
// mouse inside the icon // mouse inside the icon
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return id; return id;
top = bottom; top = bottom;
bottom -= scaled_gap_size; bottom -= gap_size;
if (id < m_items.size() - 1) if (id < m_items.size() - 1) {
{
// mouse inside the gap // mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if (left <= (float)scaled_mouse_pos.x() &&
(float)scaled_mouse_pos.x() <= right &&
bottom <= (float)scaled_mouse_pos.y() &&
(float)scaled_mouse_pos.y() <= top)
return -2; return -2;
} }
@ -1243,33 +1220,32 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
return -1; return -1;
} }
void GLToolbar::render_background(float left, float top, float right, float bottom, float border) const void GLToolbar::render_background(float left, float top, float right, float bottom, float border_w, float border_h) const
{ {
unsigned int tex_id = m_background_texture.texture.get_id(); const unsigned int tex_id = m_background_texture.texture.get_id();
float tex_width = (float)m_background_texture.texture.get_width(); const float tex_width = (float)m_background_texture.texture.get_width();
float tex_height = (float)m_background_texture.texture.get_height(); const float tex_height = (float)m_background_texture.texture.get_height();
if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0)) if (tex_id != 0 && tex_width > 0.0f && tex_height > 0.0f) {
{ const float inv_tex_width = 1.0f / tex_width;
float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; const float inv_tex_height = 1.0f / tex_height;
float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f;
float internal_left = left + border; const float internal_left = left + border_w;
float internal_right = right - border; const float internal_right = right - border_w;
float internal_top = top - border; const float internal_top = top - border_h;
float internal_bottom = bottom + border; const float internal_bottom = bottom + border_w;
float left_uv = 0.0f; const float left_uv = 0.0f;
float right_uv = 1.0f; const float right_uv = 1.0f;
float top_uv = 1.0f; const float top_uv = 1.0f;
float bottom_uv = 0.0f; const float bottom_uv = 0.0f;
float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width; const float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width;
float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width; const float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width;
float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height; const float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height;
float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height; const float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height;
// top-left corner // top-left corner
if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Top)) if (m_layout.horizontal_orientation == Layout::HO_Left || m_layout.vertical_orientation == Layout::VO_Top)
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
else else
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { left_uv, internal_top_uv }, { internal_left_uv, internal_top_uv }, { internal_left_uv, top_uv }, { left_uv, top_uv } }); GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { left_uv, internal_top_uv }, { internal_left_uv, internal_top_uv }, { internal_left_uv, top_uv }, { left_uv, top_uv } });
@ -1281,7 +1257,7 @@ void GLToolbar::render_background(float left, float top, float right, float bott
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } }); GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } });
// top-right corner // top-right corner
if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Top)) if (m_layout.horizontal_orientation == Layout::HO_Right || m_layout.vertical_orientation == Layout::VO_Top)
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
else else
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } }); GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } });
@ -1302,7 +1278,7 @@ void GLToolbar::render_background(float left, float top, float right, float bott
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } });
// bottom-left corner // bottom-left corner
if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Bottom)) if (m_layout.horizontal_orientation == Layout::HO_Left || m_layout.vertical_orientation == Layout::VO_Bottom)
GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
else else
GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { left_uv, bottom_uv }, { internal_left_uv, bottom_uv }, { internal_left_uv, internal_bottom_uv }, { left_uv, internal_bottom_uv } }); GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { left_uv, bottom_uv }, { internal_left_uv, bottom_uv }, { internal_left_uv, internal_bottom_uv }, { left_uv, internal_bottom_uv } });
@ -1314,7 +1290,7 @@ void GLToolbar::render_background(float left, float top, float right, float bott
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } });
// bottom-right corner // bottom-right corner
if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Bottom)) if (m_layout.horizontal_orientation == Layout::HO_Right || m_layout.vertical_orientation == Layout::VO_Bottom)
GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
else else
GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } }); GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } });
@ -1389,41 +1365,48 @@ void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighte
void GLToolbar::render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType type) void GLToolbar::render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType type)
{ {
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const Size cnv_size = parent.get_canvas_size();
float factor = inv_zoom * m_layout.scale; const float cnv_w = (float)cnv_size.get_width();
const float cnv_h = (float)cnv_size.get_height();
float scaled_icons_size = m_layout.icons_size * factor; if (cnv_w == 0 || cnv_h == 0)
float scaled_separator_size = m_layout.separator_size * factor; return;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float scaled_width = get_width() * inv_zoom;
float scaled_height = get_height() * inv_zoom;
float separator_stride = scaled_separator_size + scaled_gap_size; const float inv_cnv_w = 1.0f / cnv_w;
float icon_stride = scaled_icons_size + scaled_gap_size; const float inv_cnv_h = 1.0f / cnv_h;
float left = m_layout.left; const float icons_size_x = 2.0f * m_layout.icons_size * m_layout.scale * inv_cnv_w;
float top = m_layout.top; const float icons_size_y = 2.0f * m_layout.icons_size * m_layout.scale * inv_cnv_h;
float right = left + scaled_width; const float separator_size = 2.0f * m_layout.separator_size * m_layout.scale * inv_cnv_w;
const float gap_size = 2.0f * m_layout.gap_size * m_layout.scale * inv_cnv_w;
const float border_w = 2.0f * m_layout.border * m_layout.scale * inv_cnv_w;
const float border_h = 2.0f * m_layout.border * m_layout.scale * inv_cnv_h;
const float width = 2.0f * get_width() * inv_cnv_w;
const float height = 2.0f * get_height() * inv_cnv_h;
const float separator_stride = separator_size + gap_size;
const float icon_stride = icons_size_x + gap_size;
float left = 2.0f * m_layout.left * inv_cnv_w;
float top = 2.0f * m_layout.top * inv_cnv_h;
float right = left + width;
if (type == GLToolbarItem::SeparatorLine) if (type == GLToolbarItem::SeparatorLine)
right = left + scaled_width * 0.5; right = left + width * 0.5;
float bottom = top - scaled_height; const float bottom = top - height;
render_background(left, top, right, bottom, scaled_border); render_background(left, top, right, bottom, border_w, border_h);
left += scaled_border; left += border_w;
top -= scaled_border; top -= border_h;
// renders icons // renders icons
for (const GLToolbarItem* item : m_items) for (const GLToolbarItem* item : m_items) {
{
if (!item->is_visible()) if (!item->is_visible())
continue; continue;
if (item->is_separator()) if (item->is_separator())
left += separator_stride; left += separator_stride;
else else {
{
//BBS GUI refactor //BBS GUI refactor
item->render_left_pos = left; item->render_left_pos = left;
if (!item->is_action_with_text_image()) { if (!item->is_action_with_text_image()) {
@ -1432,13 +1415,13 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType
int tex_height = m_icons_texture.get_height(); int tex_height = m_icons_texture.get_height();
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return; return;
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); item->render(tex_id, left, left + icons_size_x, top - icons_size_y, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
} }
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
if (item->is_action_with_text()) if (item->is_action_with_text())
{ {
float scaled_text_size = item->get_extra_size_ratio() * scaled_icons_size; float scaled_text_size = item->get_extra_size_ratio() * icons_size_x;
item->render_text(left + scaled_icons_size, left + scaled_icons_size + scaled_text_size, top - scaled_icons_size, top); item->render_text(left + icons_size_x, left + icons_size_x + scaled_text_size, top - icons_size_y, top);
left += scaled_text_size; left += scaled_text_size;
} }
left += icon_stride; left += icon_stride;
@ -1448,28 +1431,37 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType
void GLToolbar::render_vertical(const GLCanvas3D& parent) void GLToolbar::render_vertical(const GLCanvas3D& parent)
{ {
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); const Size cnv_size = parent.get_canvas_size();
float factor = inv_zoom * m_layout.scale; const float cnv_w = (float)cnv_size.get_width();
const float cnv_h = (float)cnv_size.get_height();
float scaled_icons_size = m_layout.icons_size * factor; if (cnv_w == 0 || cnv_h == 0)
float scaled_separator_size = m_layout.separator_size * factor; return;
float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor;
float scaled_width = get_width() * inv_zoom;
float scaled_height = get_height() * inv_zoom;
float separator_stride = scaled_separator_size + scaled_gap_size; const float inv_cnv_w = 1.0f / cnv_w;
float icon_stride = scaled_icons_size + scaled_gap_size; const float inv_cnv_h = 1.0f / cnv_h;
float left = m_layout.left; const float icons_size_x = 2.0f * m_layout.icons_size * m_layout.scale * inv_cnv_w;
float top = m_layout.top; const float icons_size_y = 2.0f * m_layout.icons_size * m_layout.scale * inv_cnv_h;
float right = left + scaled_width; const float separator_size = 2.0f * m_layout.separator_size * m_layout.scale * inv_cnv_h;
float bottom = top - scaled_height; const float gap_size = 2.0f * m_layout.gap_size * m_layout.scale * inv_cnv_h;
const float border_w = 2.0f * m_layout.border * m_layout.scale * inv_cnv_w;
const float border_h = 2.0f * m_layout.border * m_layout.scale * inv_cnv_h;
const float width = 2.0f * get_width() * inv_cnv_w;
const float height = 2.0f * get_height() * inv_cnv_h;
render_background(left, top, right, bottom, scaled_border); const float separator_stride = separator_size + gap_size;
const float icon_stride = icons_size_y + gap_size;
left += scaled_border; float left = 2.0f * m_layout.left * inv_cnv_w;
top -= scaled_border; float top = 2.0f * m_layout.top * inv_cnv_h;
const float right = left + width;
const float bottom = top - height;
render_background(left, top, right, bottom, border_w, border_h);
left += border_w;
top -= border_h;
// renders icons // renders icons
for (const GLToolbarItem* item : m_items) { for (const GLToolbarItem* item : m_items) {
@ -1482,10 +1474,10 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent)
unsigned int tex_id; unsigned int tex_id;
int tex_width, tex_height; int tex_width, tex_height;
if (item->is_action_with_text_image()) { if (item->is_action_with_text_image()) {
float scaled_text_size = m_layout.text_size * factor; float scaled_text_size = m_layout.text_size * m_layout.scale * inv_cnv_w;
float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; float scaled_text_width = item->get_extra_size_ratio() * icons_size_x;
float scaled_text_border = 2.5 * factor; float scaled_text_border = 2.5 * m_layout.scale * inv_cnv_h;
float scaled_text_height = scaled_icons_size / 2.0f; float scaled_text_height = icons_size_y / 2.0f;
item->render_text(left, left + scaled_text_size, top - scaled_text_border - scaled_text_height, top - scaled_text_border); item->render_text(left, left + scaled_text_size, top - scaled_text_border - scaled_text_height, top - scaled_text_border);
float image_left = left + scaled_text_size; float image_left = left + scaled_text_size;
@ -1494,7 +1486,7 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent)
tex_height = item->m_data.image_texture.get_height(); tex_height = item->m_data.image_texture.get_height();
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return; return;
item->render_image(tex_id, image_left, image_left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); item->render_image(tex_id, image_left, image_left + icons_size_x, top - icons_size_y, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
} }
else { else {
tex_id = m_icons_texture.get_id(); tex_id = m_icons_texture.get_id();
@ -1502,14 +1494,14 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent)
tex_height = m_icons_texture.get_height(); tex_height = m_icons_texture.get_height();
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return; return;
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); item->render(tex_id, left, left + icons_size_x, top - icons_size_y, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
} }
if (item->is_action_with_text()) if (item->is_action_with_text())
{ {
float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; float scaled_text_width = item->get_extra_size_ratio() * icons_size_x;
float scaled_text_height = scaled_icons_size; float scaled_text_height = icons_size_y;
item->render_text(left + scaled_icons_size, left + scaled_icons_size + scaled_text_width, top - scaled_text_height, top); item->render_text(left + icons_size_x, left + icons_size_x + scaled_text_width, top - scaled_text_height, top);
} }
top -= icon_stride; top -= icon_stride;
} }

View file

@ -436,8 +436,8 @@ private:
int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
void render_background(float left, float top, float right, float bottom, float border) const; void render_background(float left, float top, float right, float bottom, float border_w, float border_h) const;
void render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType type); void render_horizontal(const GLCanvas3D &parent, GLToolbarItem::EType type);
void render_vertical(const GLCanvas3D& parent); void render_vertical(const GLCanvas3D& parent);
bool generate_icons_texture(); bool generate_icons_texture();

View file

@ -492,8 +492,6 @@ void GLGizmoAdvancedCut::on_render_for_picking()
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
BoundingBoxf3 box = m_parent.get_selection().get_bounding_box(); BoundingBoxf3 box = m_parent.get_selection().get_bounding_box();
#if ENABLE_FIXED_GRABBER #if ENABLE_FIXED_GRABBER
float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize);
@ -502,17 +500,17 @@ void GLGizmoAdvancedCut::on_render_for_picking()
#endif #endif
m_move_grabber.color = picking_color_component(0); m_move_grabber.color = picking_color_component(0);
GLShaderProgram *shader = wxGetApp().get_shader("flat"); GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera &camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_move_grabber.render_for_picking(mean_size); m_move_grabber.render_for_picking(mean_size);
shader->stop_using(); shader->stop_using();
} }
glsafe(::glPopMatrix());
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
auto inst_id = m_c->selection_info()->get_active_instance(); auto inst_id = m_c->selection_info()->get_active_instance();
if (inst_id < 0) if (inst_id < 0)
@ -868,7 +866,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
GLShaderProgram *shader = wxGetApp().get_shader("flat"); GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
@ -877,7 +875,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
m_plane.reset(); m_plane.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f }; init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_vertices(6); init_data.reserve_vertices(6);
@ -888,11 +886,14 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
} }
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
m_plane.init_from(std::move(init_data)); m_plane.init_from(std::move(init_data));
} }
const Camera &camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_plane.render(); m_plane.render();
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
@ -907,17 +908,17 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
m_grabber_connection.reset(); m_grabber_connection.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.color = ColorRGBA::YELLOW(); init_data.color = ColorRGBA::YELLOW();
init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); init_data.reserve_vertices(2);
init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); init_data.reserve_vertices(2);
// vertices // vertices
init_data.add_vertex((Vec3f)plane_center_rot.cast<float>()); init_data.add_vertex((Vec3f)plane_center_rot.cast<float>());
init_data.add_vertex((Vec3f)m_move_grabber.center.cast<float>()); init_data.add_vertex((Vec3f)m_move_grabber.center.cast<float>());
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_grabber_connection.init_from(std::move(init_data)); m_grabber_connection.init_from(std::move(init_data));
} }
@ -933,7 +934,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
} }
{ {
GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
@ -960,13 +961,15 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
cube.set_color(render_color); cube.set_color(render_color);
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(m_move_grabber.center.x(), m_move_grabber.center.y(), m_move_grabber.center.z())); const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_move_grabber.center) *
glsafe(::glMultMatrixd(m_rotate_matrix.data())); m_rotate_matrix *
Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), fullsize * Vec3d::Ones());
glsafe(::glScaled(fullsize, fullsize, fullsize)); const Transform3d& projection_matrix = camera.get_projection_matrix();
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d) view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
cube.render(); cube.render();
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
} }
@ -1064,23 +1067,26 @@ void GLGizmoAdvancedCut::render_cut_line()
void GLGizmoAdvancedCut::render_connector_model(GLModel &model, const ColorRGBA &color, Transform3d view_model_matrix, bool for_picking) void GLGizmoAdvancedCut::render_connector_model(GLModel &model, const ColorRGBA &color, Transform3d view_model_matrix, bool for_picking)
{ {
glPushMatrix();
GLShaderProgram *shader = nullptr; GLShaderProgram *shader = nullptr;
if (for_picking) if (for_picking)
shader = wxGetApp().get_shader("cali"); shader = wxGetApp().get_shader("flat_attr");
else else
shader = wxGetApp().get_shader("gouraud_light"); shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader) { if (shader) {
shader->start_using(); shader->start_using();
glsafe(::glMultMatrixd(view_model_matrix.data())); const Camera& camera = wxGetApp().plater()->get_camera();
view_model_matrix = camera.get_view_matrix() * view_model_matrix;
const Transform3d &projection_matrix = camera.get_projection_matrix();
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d) view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
model.set_color(color); model.set_color(color);
model.render(); model.render();
shader->stop_using(); shader->stop_using();
} }
glPopMatrix();
} }
void GLGizmoAdvancedCut::clear_selection() void GLGizmoAdvancedCut::clear_selection()

View file

@ -4,6 +4,7 @@
#include <GL/glew.h> #include <GL/glew.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_Colors.hpp" #include "slic3r/GUI/GUI_Colors.hpp"
// TODO: Display tooltips quicker on Linux // TODO: Display tooltips quicker on Linux
@ -97,11 +98,15 @@ GLModel& GLGizmoBase::Grabber::get_cube()
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking)
{ {
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr)
return;
if (!m_cube.is_initialized()) { if (!m_cube.is_initialized()) {
// This cannot be done in constructor, OpenGL is not yet // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
indexed_triangle_set its = its_make_cube(1., 1., 1.); indexed_triangle_set its = its_make_cube(1., 1., 1.);
its_translate(its, Vec3f(-0.5, -0.5, -0.5)); its_translate(its, -0.5f * Vec3f::Ones());
m_cube.init_from(its); m_cube.init_from(its);
} }
@ -115,14 +120,14 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
m_cube.set_color(render_color); m_cube.set_color(render_color);
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(center.x(), center.y(), center.z())); const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones());
glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0)); const Transform3d& projection_matrix = camera.get_projection_matrix();
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); shader->set_uniform("view_model_matrix", view_model_matrix);
glsafe(::glScaled(fullsize, fullsize, fullsize)); shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cube.render(); m_cube.render();
glsafe(::glPopMatrix());
} }
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
@ -257,7 +262,7 @@ void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
void GLGizmoBase::render_grabbers(float size) const void GLGizmoBase::render_grabbers(float size) const
{ {
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
@ -271,7 +276,7 @@ void GLGizmoBase::render_grabbers(float size) const
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{ {
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();

View file

@ -68,6 +68,7 @@ protected:
bool dragging{ false }; bool dragging{ false };
Vec3d center{ Vec3d::Zero() }; Vec3d center{ Vec3d::Zero() };
Vec3d angles{ Vec3d::Zero() }; Vec3d angles{ Vec3d::Zero() };
Transform3d matrix{ Transform3d::Identity() };
ColorRGBA color{GRABBER_NORMAL_COL}; ColorRGBA color{GRABBER_NORMAL_COL};
ColorRGBA hover_color{GRABBER_HOVER_COL}; ColorRGBA hover_color{GRABBER_HOVER_COL};

View file

@ -155,7 +155,7 @@ bool GLGizmoFdmSupports::on_key_down_select_tool_type(int keyCode) {
void GLGizmoFdmSupports::render_triangles(const Selection& selection) const void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
{ {
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
auto* shader = wxGetApp().get_shader("mm_gouraud"); auto* shader = wxGetApp().get_shader("mm_gouraud_attr");
if (!shader) if (!shader)
return; return;
shader->start_using(); shader->start_using();
@ -177,8 +177,11 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CW)); glsafe(::glFrontFace(GL_CW));
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixd(trafo_matrix.data())); const Transform3d matrix = camera.get_view_matrix() * trafo_matrix;
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg)); float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg));
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()); Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
@ -188,9 +191,8 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
shader->set_uniform("slope.actived", m_parent.is_using_slope()); shader->set_uniform("slope.actived", m_parent.is_using_slope());
shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix); shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
shader->set_uniform("slope.normal_z", normal_z); shader->set_uniform("slope.normal_z", normal_z);
m_triangle_selectors[mesh_id]->render(m_imgui); m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
glsafe(::glPopMatrix());
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CCW)); glsafe(::glFrontFace(GL_CCW));
} }
@ -895,7 +897,7 @@ void GLGizmoFdmSupports::run_thread()
goto _finished; goto _finished;
} }
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers()) for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers())
{ {
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities) for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)

View file

@ -2,6 +2,7 @@
#include "GLGizmoFlatten.hpp" #include "GLGizmoFlatten.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp" #include "libslic3r/Geometry/ConvexHull.hpp"
@ -63,7 +64,7 @@ void GLGizmoFlatten::on_render()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -75,16 +76,18 @@ void GLGizmoFlatten::on_render()
if (selection.is_single_full_instance()) { if (selection.is_single_full_instance()) {
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); const Transform3d view_model_matrix = camera.get_view_matrix() *
glsafe(::glMultMatrixd(m.data())); Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (this->is_plane_update_necessary()) if (this->is_plane_update_necessary())
update_planes(); update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i) { for (int i = 0; i < (int)m_planes.size(); ++i) {
m_planes[i].vbo.set_color(i == m_hover_id ? GLGizmoBase::FLATTEN_HOVER_COLOR : GLGizmoBase::FLATTEN_COLOR); m_planes[i].vbo.set_color(i == m_hover_id ? GLGizmoBase::FLATTEN_HOVER_COLOR : GLGizmoBase::FLATTEN_COLOR);
m_planes[i].vbo.render(); m_planes[i].vbo.render();
} }
glsafe(::glPopMatrix());
} }
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
@ -95,7 +98,7 @@ void GLGizmoFlatten::on_render()
void GLGizmoFlatten::on_render_for_picking() void GLGizmoFlatten::on_render_for_picking()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -106,16 +109,18 @@ void GLGizmoFlatten::on_render_for_picking()
if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) { if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) {
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); const Transform3d view_model_matrix = camera.get_view_matrix() *
glsafe(::glMultMatrixd(m.data())); Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (this->is_plane_update_necessary()) if (this->is_plane_update_necessary())
update_planes(); update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i) { for (int i = 0; i < (int)m_planes.size(); ++i) {
m_planes[i].vbo.set_color(picking_color_component(i)); m_planes[i].vbo.set_color(picking_color_component(i));
m_planes[i].vbo.render(); m_planes[i].vbo.render();
} }
glsafe(::glPopMatrix());
} }
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
@ -337,16 +342,13 @@ void GLGizmoFlatten::update_planes()
// the vertices in order, so triangulation is trivial. // the vertices in order, so triangulation is trivial.
for (auto& plane : m_planes) { for (auto& plane : m_planes) {
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(plane.vertices.size()) }; init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3 };
init_data.reserve_vertices(plane.vertices.size()); init_data.reserve_vertices(plane.vertices.size());
init_data.reserve_indices(plane.vertices.size()); init_data.reserve_indices(plane.vertices.size());
// vertices + indices // vertices + indices
for (size_t i = 0; i < plane.vertices.size(); ++i) { 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>()); 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_index((unsigned int)i);
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)); plane.vbo.init_from(std::move(init_data));
// FIXME: vertices should really be local, they need not // FIXME: vertices should really be local, they need not

View file

@ -103,28 +103,30 @@ void GLGizmoHollow::on_render_for_picking()
void GLGizmoHollow::render_points(const Selection& selection, bool picking) void GLGizmoHollow::render_points(const Selection& selection, bool picking)
{ {
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
ScopeGuard guard([shader]() { shader->stop_using(); }); ScopeGuard guard([shader]() { shader->stop_using(); });
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); 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(); const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix();
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); const Transform3d& view_matrix = camera.get_view_matrix();
glsafe(::glMultMatrixd(instance_matrix.data())); const Transform3d& projection_matrix = camera.get_projection_matrix();
shader->set_uniform("projection_matrix", projection_matrix);
ColorRGBA render_color; ColorRGBA render_color;
const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
size_t cache_size = drain_holes.size(); const size_t cache_size = drain_holes.size();
for (size_t i = 0; i < cache_size; ++i) { for (size_t i = 0; i < cache_size; ++i) {
const sla::DrainHole& drain_hole = drain_holes[i]; const sla::DrainHole& drain_hole = drain_holes[i];
const bool& point_selected = m_selected[i]; const bool point_selected = m_selected[i];
if (is_mesh_point_clipped(drain_hole.pos.cast<double>())) if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
continue; continue;
@ -147,9 +149,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
m_cylinder.set_color(render_color); m_cylinder.set_color(render_color);
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
glsafe(::glPushMatrix()); const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z()));
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CW); glFrontFace(GL_CW);
@ -157,18 +157,17 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
// Matrices set, we can render the point mark now. // Matrices set, we can render the point mark now.
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
Eigen::AngleAxisd aa(q); const Eigen::AngleAxisd aa(q);
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); const Transform3d view_model_matrix = view_matrix * instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) *
glsafe(::glTranslated(0., 0., -drain_hole.height)); Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cylinder.render(); m_cylinder.render();
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glsafe(::glPopMatrix());
} }
glsafe(::glPopMatrix());
} }
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const

View file

@ -192,7 +192,7 @@ void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection)
void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
{ {
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
auto *shader = wxGetApp().get_shader("mm_gouraud"); auto* shader = wxGetApp().get_shader("mm_gouraud_attr");
if (!shader) if (!shader)
return; return;
shader->start_using(); shader->start_using();
@ -221,18 +221,20 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix(); trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix();
} }
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; const bool is_left_handed = trafo_matrix.matrix().determinant() < 0.0;
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CW)); glsafe(::glFrontFace(GL_CW));
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixd(trafo_matrix.data())); const Transform3d matrix = camera.get_view_matrix() * trafo_matrix;
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
shader->set_uniform("volume_world_matrix", trafo_matrix); shader->set_uniform("volume_world_matrix", trafo_matrix);
shader->set_uniform("volume_mirrored", is_left_handed); shader->set_uniform("volume_mirrored", is_left_handed);
m_triangle_selectors[mesh_id]->render(m_imgui); m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
glsafe(::glPopMatrix());
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CCW)); glsafe(::glFrontFace(GL_CCW));
} }

View file

@ -140,7 +140,7 @@ void GLGizmoMove3D::on_render()
m_grabber_connections[id].model.reset(); m_grabber_connections[id].model.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.color = AXES_COLOR[id]; init_data.color = AXES_COLOR[id];
init_data.reserve_vertices(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2); init_data.reserve_indices(2);
@ -150,7 +150,7 @@ void GLGizmoMove3D::on_render()
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>()); init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_grabber_connections[id].model.init_from(std::move(init_data)); m_grabber_connections[id].model.init_from(std::move(init_data));
//} //}
@ -162,11 +162,13 @@ void GLGizmoMove3D::on_render()
} }
}; };
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
// draw axes line shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
// draw axes // draw axes
for (unsigned int i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
render_grabber_connection(i); render_grabber_connection(i);
@ -240,12 +242,12 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking)
{ {
#if ENABLE_FIXED_GRABBER #if ENABLE_FIXED_GRABBER
float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize); const float mean_size = (float)(GLGizmoBase::Grabber::FixedGrabberSize);
#else #else
float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); const float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
#endif #endif
double size = 0.75 * GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::INV_ZOOM; const double size = 0.75 * GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::INV_ZOOM;
ColorRGBA color = m_grabbers[axis].color; ColorRGBA color = m_grabbers[axis].color;
if (!picking && m_hover_id != -1) { if (!picking && m_hover_id != -1) {
@ -254,7 +256,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
} }
} }
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -262,22 +264,21 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.1f); shader->set_uniform("emission_factor", 0.1f);
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_grabbers[axis].center);
if (axis == X) if (axis == X)
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
else if (axis == Y) else if (axis == Y)
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX());
view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 2.0 * size));
//glsafe(::glTranslated(0.0, 0.0, 2.0 * size)); shader->set_uniform("view_model_matrix", view_model_matrix);
glsafe(::glScaled(0.75 * size, 0.75 * size, 2.0 * size)); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cone.render(); m_cone.render();
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
} }
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -75,7 +75,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl
void GLGizmoPainterBase::render_triangles(const Selection& selection) const void GLGizmoPainterBase::render_triangles(const Selection& selection) const
{ {
auto* shader = wxGetApp().get_shader("gouraud"); auto* shader = wxGetApp().get_shader("gouraud_attr");
if (! shader) if (! shader)
return; return;
shader->start_using(); shader->start_using();
@ -105,8 +105,11 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CW)); glsafe(::glFrontFace(GL_CW));
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixd(trafo_matrix.data())); const Transform3d matrix = camera.get_view_matrix() * trafo_matrix;
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
// For printers with multiple extruders, it is necessary to pass trafo_matrix // For printers with multiple extruders, it is necessary to pass trafo_matrix
// to the shader input variable print_box.volume_world_matrix before // to the shader input variable print_box.volume_world_matrix before
@ -114,9 +117,8 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const
// wrong transformation matrix is used for "Clipping of view". // wrong transformation matrix is used for "Clipping of view".
shader->set_uniform("volume_world_matrix", trafo_matrix); shader->set_uniform("volume_world_matrix", trafo_matrix);
m_triangle_selectors[mesh_id]->render(m_imgui); m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
glsafe(::glPopMatrix());
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CCW)); glsafe(::glFrontFace(GL_CCW));
} }
@ -165,43 +167,34 @@ void GLGizmoPainterBase::render_cursor()
void GLGizmoPainterBase::render_cursor_circle() void GLGizmoPainterBase::render_cursor_circle()
{ {
const Camera &camera = wxGetApp().plater()->get_camera();
const float zoom = float(camera.get_zoom());
const float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
const Size cnv_size = m_parent.get_canvas_size(); const Size cnv_size = m_parent.get_canvas_size();
const float cnv_half_width = 0.5f * float(cnv_size.get_width()); const float cnv_width = float(cnv_size.get_width());
const float cnv_half_height = 0.5f * float(cnv_size.get_height()); const float cnv_height = float(cnv_size.get_height());
if (cnv_half_width == 0.0f || cnv_half_height == 0.0f) if (cnv_width == 0.0f || cnv_height == 0.0f)
return; return;
const Vec2d mouse_pos(m_parent.get_local_mouse_position().x(), m_parent.get_local_mouse_position().y());
Vec2d center(mouse_pos.x() - cnv_half_width, cnv_half_height - mouse_pos.y()); const float cnv_inv_width = 1.0f / cnv_width;
center = center * inv_zoom; const float cnv_inv_height = 1.0f / cnv_height;
const Vec2d center = m_parent.get_local_mouse_position();
const float radius = m_cursor_radius * float(wxGetApp().plater()->get_camera().get_zoom());
glsafe(::glLineWidth(1.5f)); glsafe(::glLineWidth(1.5f));
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
glsafe(::glLoadIdentity());
// ensure that the circle is renderered inside the frustrum
glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5)));
// ensure that the overlay fits the frustrum near z plane
const double gui_scale = camera.get_gui_scale();
glsafe(::glScaled(gui_scale, gui_scale, 1.0));
glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glPushAttrib(GL_ENABLE_BIT));
glsafe(::glLineStipple(4, 0xAAAA)); glsafe(::glLineStipple(4, 0xAAAA));
glsafe(::glEnable(GL_LINE_STIPPLE)); glsafe(::glEnable(GL_LINE_STIPPLE));
if (!m_circle.is_initialized() || !m_old_center.isApprox(center) || std::abs(m_old_cursor_radius - m_cursor_radius) > EPSILON) { if (!m_circle.is_initialized() || !m_old_center.isApprox(center) || std::abs(m_old_cursor_radius - radius) > EPSILON) {
m_old_cursor_radius = radius;
m_old_center = center; m_old_center = center;
m_old_cursor_radius = m_cursor_radius;
m_circle.reset(); m_circle.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
static const unsigned int StepsCount = 32; static const unsigned int StepsCount = 32;
static const float StepSize = 2.0f * float(PI) / float(StepsCount); static const float StepSize = 2.0f * float(PI) / float(StepsCount);
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f };
init_data.reserve_vertices(StepsCount); init_data.reserve_vertices(StepsCount);
init_data.reserve_indices(StepsCount); init_data.reserve_indices(StepsCount);
@ -209,8 +202,9 @@ void GLGizmoPainterBase::render_cursor_circle()
// vertices + indices // vertices + indices
for (unsigned short i = 0; i < StepsCount; ++i) { for (unsigned short i = 0; i < StepsCount; ++i) {
const float angle = float(i * StepSize); const float angle = float(i * StepSize);
init_data.add_vertex(Vec2f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius)); init_data.add_vertex(Vec2f(2.0f * ((center.x() + ::cos(angle) * radius) * cnv_inv_width - 0.5f),
init_data.add_ushort_index(i); -2.0f * ((center.y() + ::sin(angle) * radius) * cnv_inv_height - 0.5f)));
init_data.add_index(i);
} }
m_circle.init_from(std::move(init_data)); m_circle.init_from(std::move(init_data));
@ -225,15 +219,16 @@ void GLGizmoPainterBase::render_cursor_circle()
m_circle.set_color(render_color); m_circle.set_color(render_color);
GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("view_model_matrix", Transform3d::Identity());
shader->set_uniform("projection_matrix", Transform3d::Identity());
m_circle.render(); m_circle.render();
shader->stop_using(); shader->stop_using();
} }
glsafe(::glPopAttrib()); glsafe(::glPopAttrib());
glsafe(::glPopMatrix());
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
} }
@ -245,20 +240,13 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
s_sphere->init_from(its_make_sphere(1.0, double(PI) / 12.0)); s_sphere->init_from(its_make_sphere(1.0, double(PI) / 12.0));
} }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse(); 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(); 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.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));
if (is_left_handed) if (is_left_handed)
glFrontFace(GL_CW); glFrontFace(GL_CW);
@ -270,6 +258,14 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
render_color = this->get_cursor_sphere_right_button_color(); render_color = this->get_cursor_sphere_right_button_color();
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * trafo *
Geometry::assemble_transform(m_rr.hit.cast<double>()) * complete_scaling_matrix_inverse *
Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), m_cursor_radius * Vec3d::Ones());
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
assert(s_sphere != nullptr); assert(s_sphere != nullptr);
s_sphere->set_color(render_color); s_sphere->set_color(render_color);
s_sphere->render(); s_sphere->render();
@ -277,13 +273,17 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
shader->stop_using(); shader->stop_using();
if (is_left_handed) if (is_left_handed)
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glsafe(::glPopMatrix());
} }
// BBS // BBS
void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) const void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) const
{ {
GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr)
return;
shader->start_using();
const BoundingBoxf3 box = bounding_box(); const BoundingBoxf3 box = bounding_box();
Vec3d hit_world = trafo * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2)); Vec3d hit_world = trafo * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2));
float max_z = (float)box.max.z(); float max_z = (float)box.max.z();
@ -309,14 +309,18 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co
for (int i = 0; i < zs.size(); i++) { for (int i = 0; i < zs.size(); i++) {
update_contours(vol_mesh, zs[i], max_z, min_z); update_contours(vol_mesh, zs[i], max_z, min_z);
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_cut_contours.shift);
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glLineWidth(2.0f)); glsafe(::glLineWidth(2.0f));
m_cut_contours.contours.render(); m_cut_contours.contours.render();
glsafe(::glPopMatrix());
} }
} }
shader->stop_using();
} }
BoundingBoxf3 GLGizmoPainterBase::bounding_box() const BoundingBoxf3 GLGizmoPainterBase::bounding_box() const
@ -1056,7 +1060,7 @@ ColorRGBA TriangleSelectorGUI::get_seed_fill_color(const ColorRGBA& base_color)
1.f}; 1.f};
} }
void TriangleSelectorGUI::render(ImGuiWrapper* imgui) void TriangleSelectorGUI::render(ImGuiWrapper* imgui, const Transform3d& matrix)
{ {
if (m_update_render_data) { if (m_update_render_data) {
update_render_data(); update_render_data();
@ -1066,7 +1070,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
auto* shader = wxGetApp().get_current_shader(); auto* shader = wxGetApp().get_current_shader();
if (! shader) if (! shader)
return; return;
assert(shader->get_name() == "gouraud"); assert(shader->get_name() == "gouraud_attr" || shader->get_name() == "mm_gouraud_attr");
ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);}); ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);});
shader->set_uniform("offset_depth_buffer", true); shader->set_uniform("offset_depth_buffer", true);
for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color),
@ -1084,7 +1088,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
iva.render(); iva.render();
} }
render_paint_contour(); render_paint_contour(matrix);
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
if (imgui) if (imgui)
@ -1109,12 +1113,12 @@ void TriangleSelectorGUI::update_render_data()
} }
GLModel::Geometry iva_enforcers_data; GLModel::Geometry iva_enforcers_data;
iva_enforcers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; iva_enforcers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
GLModel::Geometry iva_blockers_data; GLModel::Geometry iva_blockers_data;
iva_blockers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; iva_blockers_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
std::array<GLModel::Geometry, 3> iva_seed_fills_data; std::array<GLModel::Geometry, 3> iva_seed_fills_data;
for (auto& data : 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 }; data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
for (const Triangle &tr : m_triangles) { for (const Triangle &tr : m_triangles) {
bool is_valid = tr.valid(); bool is_valid = tr.valid();
@ -1140,7 +1144,7 @@ void TriangleSelectorGUI::update_render_data()
iva.add_vertex(v0, n); iva.add_vertex(v0, n);
iva.add_vertex(v1, n); iva.add_vertex(v1, n);
iva.add_vertex(v2, n); iva.add_vertex(v2, n);
iva.add_uint_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2); iva.add_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2);
cnt += 3; cnt += 3;
} }
@ -1164,7 +1168,7 @@ bool TrianglePatch::is_fragment() const
float TriangleSelectorPatch::gap_area = TriangleSelectorPatch::GapAreaMin; float TriangleSelectorPatch::gap_area = TriangleSelectorPatch::GapAreaMin;
void TriangleSelectorPatch::render(ImGuiWrapper* imgui) void TriangleSelectorPatch::render(ImGuiWrapper* imgui, const Transform3d& matrix)
{ {
if (m_update_render_data) { if (m_update_render_data) {
update_render_data(); update_render_data();
@ -1174,8 +1178,8 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui)
auto* shader = wxGetApp().get_current_shader(); auto* shader = wxGetApp().get_current_shader();
if (!shader) if (!shader)
return; return;
assert(shader->get_name() == "mm_gouraud"); assert(shader->get_name() == "gouraud_attr" || shader->get_name() == "mm_gouraud_attr");
GLint position_id = -1; GLint position_id = -1;
GLint barycentric_id = -1; GLint barycentric_id = -1;
if (wxGetApp().plater()->is_wireframe_enabled()) { if (wxGetApp().plater()->is_wireframe_enabled()) {
position_id = shader->get_attrib_location("v_position"); position_id = shader->get_attrib_location("v_position");
@ -1212,7 +1216,7 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui)
} }
} }
render_paint_contour(); render_paint_contour(matrix);
} }
void TriangleSelectorPatch::update_triangles_per_type() void TriangleSelectorPatch::update_triangles_per_type()
@ -1631,10 +1635,14 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
if (curr_shader != nullptr) if (curr_shader != nullptr)
curr_shader->stop_using(); curr_shader->stop_using();
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); ::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
for (vtype i : {ORIGINAL, SPLIT, INVALID}) { for (vtype i : {ORIGINAL, SPLIT, INVALID}) {
GLModel& va = m_varrays[i]; GLModel& va = m_varrays[i];
@ -1661,35 +1669,37 @@ void TriangleSelectorGUI::update_paint_contour()
GLModel::Geometry init_data; GLModel::Geometry init_data;
const std::vector<Vec2i> contour_edges = this->get_seed_fill_contour(); 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.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2 * contour_edges.size()); init_data.reserve_vertices(2 * contour_edges.size());
init_data.reserve_indices(2 * contour_edges.size()); init_data.reserve_indices(2 * contour_edges.size());
init_data.color = ColorRGBA::WHITE();
// vertices + indices // vertices + indices
unsigned int vertices_count = 0; unsigned int vertices_count = 0;
for (const Vec2i& edge : contour_edges) { for (const Vec2i& edge : contour_edges) {
init_data.add_vertex(m_vertices[edge(0)].v); init_data.add_vertex(m_vertices[edge(0)].v);
init_data.add_vertex(m_vertices[edge(1)].v); init_data.add_vertex(m_vertices[edge(1)].v);
vertices_count += 2; vertices_count += 2;
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_line(vertices_count - 2, vertices_count - 1);
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()) if (!init_data.is_empty())
m_paint_contour.init_from(std::move(init_data)); m_paint_contour.init_from(std::move(init_data));
} }
void TriangleSelectorGUI::render_paint_contour() void TriangleSelectorGUI::render_paint_contour(const Transform3d& matrix)
{ {
auto* curr_shader = wxGetApp().get_current_shader(); auto* curr_shader = wxGetApp().get_current_shader();
if (curr_shader != nullptr) if (curr_shader != nullptr)
curr_shader->stop_using(); curr_shader->stop_using();
auto* contour_shader = wxGetApp().get_shader("mm_contour"); auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
if (contour_shader != nullptr) { if (contour_shader != nullptr) {
contour_shader->start_using(); contour_shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
contour_shader->set_uniform("view_model_matrix", camera.get_view_matrix() * matrix);
contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glDepthFunc(GL_LEQUAL)); glsafe(::glDepthFunc(GL_LEQUAL));
m_paint_contour.render(); m_paint_contour.render();
glsafe(::glDepthFunc(GL_LESS)); glsafe(::glDepthFunc(GL_LESS));

View file

@ -34,10 +34,8 @@ public:
: TriangleSelector(mesh, edge_limit) {} : TriangleSelector(mesh, edge_limit) {}
virtual ~TriangleSelectorGUI() = default; virtual ~TriangleSelectorGUI() = default;
// Render current selection. Transformation matrices are supposed virtual void render(ImGuiWrapper* imgui, const Transform3d& matrix);
// to be already set. void render(const Transform3d& matrix) { this->render(nullptr, matrix); }
virtual void render(ImGuiWrapper *imgui);
void render() { this->render(nullptr); }
void set_wireframe_needed(bool need_wireframe) { m_need_wireframe = need_wireframe; } void set_wireframe_needed(bool need_wireframe) { m_need_wireframe = need_wireframe; }
bool get_wireframe_needed() { return m_need_wireframe; } bool get_wireframe_needed() { return m_need_wireframe; }
@ -79,7 +77,7 @@ protected:
GLModel m_paint_contour; GLModel m_paint_contour;
void update_paint_contour(); void update_paint_contour();
void render_paint_contour(); void render_paint_contour(const Transform3d& matrix);
bool m_need_wireframe {false}; bool m_need_wireframe {false};
}; };
@ -105,7 +103,7 @@ public:
// Render current selection. Transformation matrices are supposed // Render current selection. Transformation matrices are supposed
// to be already set. // to be already set.
void render(ImGuiWrapper* imgui) override; void render(ImGuiWrapper* imgui, const Transform3d& matrix) override;
// TriangleSelector.m_triangles => m_gizmo_scene.triangle_patches // TriangleSelector.m_triangles => m_gizmo_scene.triangle_patches
void update_triangles_per_type(); void update_triangles_per_type();
// m_gizmo_scene.triangle_patches => TriangleSelector.m_triangles // m_gizmo_scene.triangle_patches => TriangleSelector.m_triangles

View file

@ -126,14 +126,19 @@ void GLGizmoRotate::on_render()
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glPushMatrix()); m_grabbers.front().matrix = local_transform(selection);
transform_to_local(selection);
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * m_grabbers.front().matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const bool radius_changed = std::abs(m_old_radius - m_radius) > EPSILON; const bool radius_changed = std::abs(m_old_radius - m_radius) > EPSILON;
m_old_radius = m_radius; m_old_radius = m_radius;
@ -152,6 +157,8 @@ void GLGizmoRotate::on_render()
render_grabber_connection(color, radius_changed); render_grabber_connection(color, radius_changed);
shader->stop_using(); shader->stop_using();
} }
glsafe(::glPushMatrix());
transform_to_local(selection);
render_grabber(box); render_grabber(box);
render_grabber_extension(box, false); render_grabber_extension(box, false);
@ -165,15 +172,11 @@ void GLGizmoRotate::on_render_for_picking()
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix()); m_grabbers.front().matrix = local_transform(selection);
transform_to_local(selection);
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = selection.get_bounding_box();
render_grabbers_for_picking(box); render_grabbers_for_picking(box);
render_grabber_extension(box, true); render_grabber_extension(box, true);
glsafe(::glPopMatrix());
} }
//BBS: add input window for move //BBS: add input window for move
@ -214,7 +217,7 @@ void GLGizmoRotate::render_circle(const ColorRGBA& color, bool radius_changed)
m_circle.reset(); m_circle.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(ScaleStepsCount); init_data.reserve_vertices(ScaleStepsCount);
init_data.reserve_indices(ScaleStepsCount); init_data.reserve_indices(ScaleStepsCount);
@ -222,7 +225,7 @@ void GLGizmoRotate::render_circle(const ColorRGBA& color, bool radius_changed)
for (unsigned short i = 0; i < ScaleStepsCount; ++i) { for (unsigned short i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * ScaleStepRad); const float angle = float(i * ScaleStepRad);
init_data.add_vertex(Vec3f(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f)); init_data.add_vertex(Vec3f(::cos(angle) * m_radius, ::sin(angle) * m_radius, 0.0f));
init_data.add_ushort_index(i); init_data.add_index(i);
} }
m_circle.init_from(std::move(init_data)); m_circle.init_from(std::move(init_data));
@ -241,7 +244,7 @@ void GLGizmoRotate::render_scale(const ColorRGBA& color, bool radius_changed)
m_scale.reset(); m_scale.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2 * ScaleStepsCount); init_data.reserve_vertices(2 * ScaleStepsCount);
init_data.reserve_indices(2 * ScaleStepsCount); init_data.reserve_indices(2 * ScaleStepsCount);
@ -257,8 +260,8 @@ void GLGizmoRotate::render_scale(const ColorRGBA& color, bool radius_changed)
init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); init_data.add_vertex(Vec3f(in_x, in_y, 0.0f));
init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); init_data.add_vertex(Vec3f(out_x, out_y, 0.0f));
init_data.add_ushort_index(i * 2); init_data.add_index(i * 2);
init_data.add_ushort_index(i * 2 + 1); init_data.add_index(i * 2 + 1);
} }
m_scale.init_from(std::move(init_data)); m_scale.init_from(std::move(init_data));
@ -278,7 +281,7 @@ void GLGizmoRotate::render_snap_radii(const ColorRGBA& color, bool radius_change
m_snap_radii.reset(); m_snap_radii.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2 * ScaleStepsCount); init_data.reserve_vertices(2 * ScaleStepsCount);
init_data.reserve_indices(2 * ScaleStepsCount); init_data.reserve_indices(2 * ScaleStepsCount);
@ -294,8 +297,8 @@ void GLGizmoRotate::render_snap_radii(const ColorRGBA& color, bool radius_change
init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); init_data.add_vertex(Vec3f(in_x, in_y, 0.0f));
init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); init_data.add_vertex(Vec3f(out_x, out_y, 0.0f));
init_data.add_ushort_index(i * 2); init_data.add_index(i * 2);
init_data.add_ushort_index(i * 2 + 1); init_data.add_index(i * 2 + 1);
} }
m_snap_radii.init_from(std::move(init_data)); m_snap_radii.init_from(std::move(init_data));
@ -311,7 +314,7 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_
m_reference_radius.reset(); m_reference_radius.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2); init_data.reserve_indices(2);
@ -320,7 +323,7 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_
init_data.add_vertex(Vec3f(m_radius * (1.0f + GrabberOffset), 0.0f, 0.0f)); init_data.add_vertex(Vec3f(m_radius * (1.0f + GrabberOffset), 0.0f, 0.0f));
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_reference_radius.init_from(std::move(init_data)); m_reference_radius.init_from(std::move(init_data));
} }
@ -341,7 +344,7 @@ void GLGizmoRotate::render_angle_arc(const ColorRGBA& color, bool radius_changed
m_angle_arc.reset(); m_angle_arc.reset();
if (m_angle > 0.0f) { if (m_angle > 0.0f) {
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(1 + AngleResolution); init_data.reserve_vertices(1 + AngleResolution);
init_data.reserve_indices(1 + AngleResolution); init_data.reserve_indices(1 + AngleResolution);
@ -349,7 +352,7 @@ void GLGizmoRotate::render_angle_arc(const ColorRGBA& color, bool radius_changed
for (unsigned short i = 0; i <= AngleResolution; ++i) { for (unsigned short i = 0; i <= AngleResolution; ++i) {
const float angle = float(i) * step_angle; const float angle = float(i) * step_angle;
init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f)); init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f));
init_data.add_ushort_index(i); init_data.add_index(i);
} }
m_angle_arc.init_from(std::move(init_data)); m_angle_arc.init_from(std::move(init_data));
@ -367,7 +370,7 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu
m_grabber_connection.old_center = m_grabbers.front().center; m_grabber_connection.old_center = m_grabbers.front().center;
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2); init_data.reserve_indices(2);
@ -376,7 +379,7 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu
init_data.add_vertex((Vec3f)m_grabbers.front().center.cast<float>()); init_data.add_vertex((Vec3f)m_grabbers.front().center.cast<float>());
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_grabber_connection.model.init_from(std::move(init_data)); m_grabber_connection.model.init_from(std::move(init_data));
} }
@ -401,36 +404,69 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
if (!picking && m_hover_id != -1) if (!picking && m_hover_id != -1)
color = m_grabbers.front().hover_color; color = m_grabbers.front().hover_color;
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
m_cone.set_color(color); m_cone.set_color(color);
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.1f); shader->set_uniform("emission_factor", 0.1f);
const Vec3d& center = m_grabbers.front().center; const Vec3d& center = m_grabbers.front().center;
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(center.x(), center.y(), center.z())); const Transform3d& view_matrix = camera.get_view_matrix();
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0)); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
glsafe(::glTranslated(0.0, 0.0, 1.5 * size)); Transform3d view_model_matrix = view_matrix * m_grabbers.front().matrix *
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size)); Geometry::assemble_transform(center, Vec3d(0.5 * PI, 0.0, m_angle)) *
Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cone.render(); m_cone.render();
glsafe(::glPopMatrix()); view_model_matrix = view_matrix * m_grabbers.front().matrix *
glsafe(::glPushMatrix()); Geometry::assemble_transform(center, Vec3d(-0.5 * PI, 0.0, m_angle)) *
glsafe(::glTranslated(center.x(), center.y(), center.z())); Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); shader->set_uniform("view_model_matrix", view_model_matrix);
glsafe(::glTranslated(0.0, 0.0, 1.5 * size)); shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
m_cone.render(); m_cone.render();
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
} }
Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
{
Transform3d ret;
switch (m_axis)
{
case X:
{
ret = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.5 * PI, 0.0)) * Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, -0.5 * PI));
break;
}
case Y:
{
ret = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, -0.5 * PI)) * Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, -0.5 * PI, 0.0));
break;
}
default:
case Z:
{
ret = Transform3d::Identity();
break;
}
}
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
ret = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true) * ret;
return Geometry::assemble_transform(m_center) * ret;
}
void GLGizmoRotate::transform_to_local(const Selection& selection) const void GLGizmoRotate::transform_to_local(const Selection& selection) const
{ {
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));

View file

@ -85,6 +85,8 @@ private:
void render_grabber(const BoundingBoxf3& box); void render_grabber(const BoundingBoxf3& box);
void render_grabber_extension(const BoundingBoxf3& box, bool picking); void render_grabber_extension(const BoundingBoxf3& box, bool picking);
Transform3d local_transform(const Selection& selection) const;
void transform_to_local(const Selection& selection) const; void transform_to_local(const Selection& selection) const;
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const; Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;

View file

@ -2,6 +2,7 @@
#include "GLGizmoScale.hpp" #include "GLGizmoScale.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -185,11 +186,11 @@ void GLGizmoScale3D::on_render()
m_box = selection.get_bounding_box(); m_box = selection.get_bounding_box();
const Vec3d& center = m_box.center(); const Vec3d& center = m_box.center();
Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL)); const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL));
// x axis // x axis
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z()); m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z());
@ -230,14 +231,17 @@ void GLGizmoScale3D::on_render()
const BoundingBoxf3& selection_box = selection.get_bounding_box(); const BoundingBoxf3& selection_box = selection.get_bounding_box();
float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0); const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0);
//draw connections //draw connections
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5) // BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
//if (single_instance || single_volume) { //if (single_instance || single_volume) {
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (m_grabbers[4].enabled && m_grabbers[5].enabled) if (m_grabbers[4].enabled && m_grabbers[5].enabled)
render_grabbers_connection(4, 5, m_grabbers[4].color); render_grabbers_connection(4, 5, m_grabbers[4].color);
render_grabbers_connection(6, 7, m_grabbers[2].color); render_grabbers_connection(6, 7, m_grabbers[2].color);
@ -279,7 +283,7 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
m_grabber_connections[id].model.reset(); m_grabber_connections[id].model.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2); init_data.reserve_vertices(2);
init_data.reserve_indices(2); init_data.reserve_indices(2);
@ -288,7 +292,7 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
init_data.add_vertex((Vec3f)m_grabbers[id_2].center.cast<float>()); init_data.add_vertex((Vec3f)m_grabbers[id_2].center.cast<float>());
// indices // indices
init_data.add_ushort_line(0, 1); init_data.add_line(0, 1);
m_grabber_connections[id].model.init_from(std::move(init_data)); m_grabber_connections[id].model.init_from(std::move(init_data));
} }

View file

@ -98,7 +98,7 @@ bool GLGizmoSeam::on_key_down_select_tool_type(int keyCode) {
void GLGizmoSeam::render_triangles(const Selection& selection) const void GLGizmoSeam::render_triangles(const Selection& selection) const
{ {
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
auto* shader = wxGetApp().get_shader("mm_gouraud"); auto* shader = wxGetApp().get_shader("mm_gouraud_attr");
if (!shader) if (!shader)
return; return;
shader->start_using(); shader->start_using();
@ -120,8 +120,11 @@ void GLGizmoSeam::render_triangles(const Selection& selection) const
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CW)); glsafe(::glFrontFace(GL_CW));
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glMultMatrixd(trafo_matrix.data())); const Transform3d matrix = camera.get_view_matrix() * trafo_matrix;
shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg)); float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg));
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()); Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
@ -129,11 +132,10 @@ void GLGizmoSeam::render_triangles(const Selection& selection) const
shader->set_uniform("volume_world_matrix", trafo_matrix); shader->set_uniform("volume_world_matrix", trafo_matrix);
shader->set_uniform("volume_mirrored", is_left_handed); shader->set_uniform("volume_mirrored", is_left_handed);
shader->set_uniform("slope.actived", m_parent.is_using_slope()); shader->set_uniform("slope.actived", m_parent.is_using_slope());
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>())); shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
shader->set_uniform("slope.normal_z", normal_z); shader->set_uniform("slope.normal_z", normal_z);
m_triangle_selectors[mesh_id]->render(m_imgui); m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
glsafe(::glPopMatrix());
if (is_left_handed) if (is_left_handed)
glsafe(::glFrontFace(GL_CCW)); glsafe(::glFrontFace(GL_CCW));
} }

View file

@ -641,19 +641,25 @@ void GLGizmoSimplify::on_render()
return; return;
const Transform3d trafo_matrix = selected_volume->world_matrix(); const Transform3d trafo_matrix = selected_volume->world_matrix();
glsafe(::glPushMatrix()); auto* gouraud_shader = wxGetApp().get_shader("gouraud_light_attr");
glsafe(::glMultMatrixd(trafo_matrix.data()));
auto *gouraud_shader = wxGetApp().get_shader("gouraud_light");
glsafe(::glPushAttrib(GL_DEPTH_TEST)); glsafe(::glPushAttrib(GL_DEPTH_TEST));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
gouraud_shader->start_using(); gouraud_shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_model_matrix = camera.get_view_matrix() * trafo_matrix;
gouraud_shader->set_uniform("view_model_matrix", view_model_matrix);
gouraud_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
gouraud_shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_glmodel.render(); m_glmodel.render();
gouraud_shader->stop_using(); gouraud_shader->stop_using();
if (m_show_wireframe) { if (m_show_wireframe) {
auto* contour_shader = wxGetApp().get_shader("mm_contour"); auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
contour_shader->start_using(); contour_shader->start_using();
contour_shader->set_uniform("view_model_matrix", view_model_matrix);
contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const ColorRGBA color = m_glmodel.get_color();
m_glmodel.set_color(ColorRGBA::WHITE());
glsafe(::glLineWidth(1.0f)); glsafe(::glLineWidth(1.0f));
glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE));
//ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); }); //ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); });
@ -661,11 +667,11 @@ void GLGizmoSimplify::on_render()
//glsafe(::glPolygonOffset(5.0, 5.0)); //glsafe(::glPolygonOffset(5.0, 5.0));
m_glmodel.render(); m_glmodel.render();
glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL));
m_glmodel.set_color(color);
contour_shader->stop_using(); contour_shader->stop_using();
} }
glsafe(::glPopAttrib()); glsafe(::glPopAttrib());
glsafe(::glPopMatrix());
} }

View file

@ -127,7 +127,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
if (! has_points && ! has_holes) if (! has_points && ! has_holes)
return; return;
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -136,12 +136,13 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); 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(); const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix();
const float z_shift = m_c->selection_info()->get_sla_shift();
glsafe(::glPushMatrix()); const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glTranslated(0.0, 0.0, z_shift)); const Transform3d& view_matrix = camera.get_view_matrix();
glsafe(::glMultMatrixd(instance_matrix.data())); const Transform3d& projection_matrix = camera.get_projection_matrix();
shader->set_uniform("projection_matrix", projection_matrix);
ColorRGBA render_color; ColorRGBA render_color;
for (size_t i = 0; i < cache_size; ++i) { for (size_t i = 0; i < cache_size; ++i) {
@ -179,9 +180,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
shader->set_uniform("emission_factor", 0.5f); 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. // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
glsafe(::glPushMatrix()); const Transform3d support_matrix = Geometry::assemble_transform(support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
glsafe(::glTranslatef(support_point.pos.x(), support_point.pos.y(), support_point.pos.z()));
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CW); glFrontFace(GL_CW);
@ -194,27 +193,29 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal); m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
const Eigen::AngleAxisd aa(q); const Eigen::AngleAxisd aa(q);
glsafe(::glPushMatrix());
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z()));
const double cone_radius = 0.25; // mm const double cone_radius = 0.25; // mm
const double cone_height = 0.75; const double cone_height = 0.75;
glsafe(::glTranslatef(0.f, 0.f, cone_height + support_point.head_front_radius * RenderPointScale)); const Transform3d view_model_matrix = view_matrix * instance_matrix * support_matrix * Transform3d(aa.toRotationMatrix()) *
glsafe(::glRotated(180., 1., 0., 0.)); Geometry::assemble_transform((cone_height + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(),
glsafe(::glScaled(cone_radius, cone_radius, cone_height)); Vec3d(PI, 0.0, 0.0), Vec3d(cone_radius, cone_radius, cone_height));
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cone.render(); m_cone.render();
glsafe(::glPopMatrix());
} }
const double radius = (double)support_point.head_front_radius * RenderPointScale; const double radius = (double)support_point.head_front_radius * RenderPointScale;
glsafe(::glScaled(radius, radius, radius)); const Transform3d view_model_matrix = view_matrix * instance_matrix * support_matrix *
Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), radius * Vec3d::Ones());
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_sphere.render(); m_sphere.render();
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glsafe(::glPopMatrix());
} }
// Now render the drain holes: // Now render the drain holes:
@ -226,31 +227,26 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
if (is_mesh_point_clipped(drain_hole.pos.cast<double>())) if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
continue; continue;
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
glsafe(::glPushMatrix());
glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z()));
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CW); glFrontFace(GL_CW);
// Matrices set, we can render the point mark now. // Matrices set, we can render the point mark now.
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
const Eigen::AngleAxisd aa(q); const Eigen::AngleAxisd aa(q);
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z())); const Transform3d view_model_matrix = view_matrix * instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) *
glsafe(::glTranslated(0., 0., -drain_hole.height)); Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_cylinder.render(); m_cylinder.render();
if (vol->is_left_handed()) if (vol->is_left_handed())
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glsafe(::glPopMatrix());
} }
} }
glsafe(::glPopMatrix());
} }

View file

@ -448,7 +448,7 @@ void GLGizmoText::on_render()
ColorRGBA color = picking_color_component(0); ColorRGBA color = picking_color_component(0);
m_grabbers[0].color = color; m_grabbers[0].color = color;
GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
m_grabbers[0].render_for_picking(mean_size); m_grabbers[0].render_for_picking(mean_size);
@ -500,14 +500,12 @@ void GLGizmoText::on_render_for_picking()
ColorRGBA color = picking_color_component(0); ColorRGBA color = picking_color_component(0);
m_grabbers[0].color = color; m_grabbers[0].color = color;
GLShaderProgram *shader = wxGetApp().get_shader("flat"); GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
glsafe(::glPushMatrix());
shader->start_using(); shader->start_using();
m_grabbers[0].render_for_picking(mean_size); m_grabbers[0].render_for_picking(mean_size);
shader->stop_using(); shader->stop_using();
glsafe(::glPopMatrix());
} }
} }
} }

View file

@ -214,15 +214,14 @@ void InstancesHider::render_cut() const
ClippingPlane clp = *get_pool()->object_clipper()->get_clipping_plane(); ClippingPlane clp = *get_pool()->object_clipper()->get_clipping_plane();
clp.set_normal(-clp.get_normal()); clp.set_normal(-clp.get_normal());
clipper->set_limiting_plane(clp); clipper->set_limiting_plane(clp);
} else }
else
clipper->set_limiting_plane(ClippingPlane::ClipsNothing()); clipper->set_limiting_plane(ClippingPlane::ClipsNothing());
glsafe(::glPushMatrix());
glsafe(::glPushAttrib(GL_DEPTH_TEST)); glsafe(::glPushAttrib(GL_DEPTH_TEST));
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
clipper->render_cut(mv->is_model_part() ? ColorRGBA(0.8f, 0.3f, 0.0f, 1.0f) : color_from_model_volume(*mv)); clipper->render_cut(mv->is_model_part() ? ColorRGBA(0.8f, 0.3f, 0.0f, 1.0f) : color_from_model_volume(*mv));
glsafe(::glPopAttrib()); glsafe(::glPopAttrib());
glsafe(::glPopMatrix());
++clipper_id; ++clipper_id;
} }
@ -412,7 +411,7 @@ void ObjectClipper::render_cut() const
size_t clipper_id = 0; size_t clipper_id = 0;
for (const ModelVolume* mv : mo->volumes) { for (const ModelVolume* mv : mo->volumes) {
Geometry::Transformation vol_trafo = mv->get_transformation(); const Geometry::Transformation vol_trafo = mv->get_transformation();
Geometry::Transformation trafo = inst_trafo * vol_trafo; Geometry::Transformation trafo = inst_trafo * vol_trafo;
if (is_assem_cnv) { if (is_assem_cnv) {
trafo.set_offset(trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0) + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0)); trafo.set_offset(trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0) + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0));
@ -427,10 +426,8 @@ void ObjectClipper::render_cut() const
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), std::numeric_limits<double>::max())); clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), std::numeric_limits<double>::max()));
else else
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
glsafe(::glPushMatrix());
// BBS // BBS
clipper->render_cut({ 0.25f, 0.25f, 0.25f, 1.0f }); clipper->render_cut({ 0.25f, 0.25f, 0.25f, 1.0f });
glsafe(::glPopMatrix());
++clipper_id; ++clipper_id;
} }
@ -557,7 +554,7 @@ void SupportsClipper::render_cut() const
const SelectionInfo* sel_info = get_pool()->selection_info(); const SelectionInfo* sel_info = get_pool()->selection_info();
const ModelObject* mo = sel_info->model_object(); const ModelObject* mo = sel_info->model_object();
Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation(); const Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation();
//Geometry::Transformation vol_trafo = mo->volumes.front()->get_transformation(); //Geometry::Transformation vol_trafo = mo->volumes.front()->get_transformation();
Geometry::Transformation trafo = inst_trafo;// * vol_trafo; Geometry::Transformation trafo = inst_trafo;// * vol_trafo;
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
@ -576,9 +573,7 @@ void SupportsClipper::render_cut() const
m_clipper->set_plane(*ocl->get_clipping_plane()); m_clipper->set_plane(*ocl->get_clipping_plane());
m_clipper->set_transformation(supports_trafo); m_clipper->set_transformation(supports_trafo);
glsafe(::glPushMatrix());
m_clipper->render_cut({ 1.0f, 0.f, 0.37f, 1.0f }); m_clipper->render_cut({ 1.0f, 0.f, 0.37f, 1.0f });
glsafe(::glPopMatrix());
} }

View file

@ -85,7 +85,9 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
float width = get_scaled_total_width(); float width = get_scaled_total_width();
#if BBS_TOOLBAR_ON_TOP #if BBS_TOOLBAR_ON_TOP
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();;
float top_x = std::max(m_parent.get_main_toolbar_width() + border, 0.5f * (cnv_w - width + m_parent.get_main_toolbar_width() + m_parent.get_collapse_toolbar_width() - m_parent.get_assemble_view_toolbar_width()) + border); const float separator_width = m_parent.get_separator_toolbar_width();
float top_x = std::max(0.0f, 0.5f * (cnv_w - (width + separator_width + m_parent.get_main_toolbar_width() - m_parent.get_collapse_toolbar_width() + m_parent.get_assemble_view_toolbar_width())));
top_x += m_parent.get_main_toolbar_width() + separator_width / 2 + border;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView)
top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width()); top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width());
float top_y = 0; float top_y = 0;
@ -1277,37 +1279,37 @@ void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot)
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_SLA_supports(true); dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_SLA_supports(true);
} }
void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border) const void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border_w, float border_h) const
{ {
const unsigned int tex_id = m_background_texture.texture.get_id(); const unsigned int tex_id = m_background_texture.texture.get_id();
const float tex_width = float(m_background_texture.texture.get_width()); const float tex_width = float(m_background_texture.texture.get_width());
const float tex_height = float(m_background_texture.texture.get_height()); const float tex_height = float(m_background_texture.texture.get_height());
if (tex_id != 0 && tex_width > 0 && tex_height > 0) { if (tex_id != 0 && tex_width > 0 && tex_height > 0) {
//BBS: GUI refactor: remove the corners of gizmo //BBS: GUI refactor: remove the corners of gizmo
const float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; const float inv_tex_width = 1.0f / tex_width;
const float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; const float inv_tex_height = 1.0f / tex_height;
const float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width; const float internal_left_uv = float(m_background_texture.metadata.left) * inv_tex_width;
const float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width; const float internal_right_uv = 1.0f - float(m_background_texture.metadata.right) * inv_tex_width;
const float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height; const float internal_top_uv = 1.0f - float(m_background_texture.metadata.top) * inv_tex_height;
const float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height; const float internal_bottom_uv = float(m_background_texture.metadata.bottom) * inv_tex_height;
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); GLTexture::render_sub_texture(tex_id, left, right, bottom, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
/* /*
const float internal_left = left + border; const float internal_left = left + border_w;
const float internal_right = right - border; const float internal_right = right - border_w;
const float internal_top = top - border; const float internal_top = top - border_h;
const float internal_bottom = bottom + border; const float internal_bottom = bottom + border_h;
// float left_uv = 0.0f; // float left_uv = 0.0f;
const float right_uv = 1.0f; const float right_uv = 1.0f;
const float top_uv = 1.0f; const float top_uv = 1.0f;
const float bottom_uv = 0.0f; const float bottom_uv = 0.0f;
const float internal_left_uv = float(m_background_texture.metadata.left) * inv_tex_width; const float internal_left_uv = float(m_background_texture.metadata.left) * inv_tex_width;
const float internal_right_uv = 1.0f - float(m_background_texture.metadata.right) * inv_tex_width; const float internal_right_uv = 1.0f - float(m_background_texture.metadata.right) * inv_tex_width;
const float internal_top_uv = 1.0f - float(m_background_texture.metadata.top) * inv_tex_height; const float internal_top_uv = 1.0f - float(m_background_texture.metadata.top) * inv_tex_height;
const float internal_bottom_uv = float(m_background_texture.metadata.bottom) * inv_tex_height; const float internal_bottom_uv = float(m_background_texture.metadata.bottom) * inv_tex_height;
// top-left corner // top-left corner
@ -1383,119 +1385,98 @@ void GLGizmosManager::render_arrow(const GLCanvas3D& parent, EType highlighted_t
//when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-top //when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-top
void GLGizmosManager::do_render_overlay() const void GLGizmosManager::do_render_overlay() const
{ {
std::vector<size_t> selectable_idxs = get_selectable_idxs(); const std::vector<size_t> selectable_idxs = get_selectable_idxs();
if (selectable_idxs.empty()) if (selectable_idxs.empty())
return; return;
float cnv_w = (float)m_parent.get_canvas_size().get_width(); const Size cnv_size = m_parent.get_canvas_size();
float cnv_h = (float)m_parent.get_canvas_size().get_height(); const float cnv_w = (float)cnv_size.get_width();
float zoom = (float)wxGetApp().plater()->get_camera().get_zoom(); const float cnv_h = (float)cnv_size.get_height();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
float height = get_scaled_total_height(); if (cnv_w == 0 || cnv_h == 0)
float width = get_scaled_total_width(); return;
float zoomed_border = m_layout.scaled_border() * inv_zoom;
float zoomed_top_x; const float inv_cnv_w = 1.0f / cnv_w;
const float inv_cnv_h = 1.0f / cnv_h;
const float height = 2.0f * get_scaled_total_height() * inv_cnv_h;
const float width = 2.0f * get_scaled_total_width() * inv_cnv_w;
const float border_h = 2.0f * m_layout.scaled_border() * inv_cnv_h;
const float border_w = 2.0f * m_layout.scaled_border() * inv_cnv_w;
float top_x;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
zoomed_top_x = 0.5f * m_parent.get_assembly_paint_toolbar_width() * inv_zoom; top_x = m_parent.get_assembly_paint_toolbar_width() * inv_cnv_w;
} }
else { else {
//BBS: GUI refactor: GLToolbar&&Gizmo adjust //BBS: GUI refactor: GLToolbar&&Gizmo adjust
#if BBS_TOOLBAR_ON_TOP
float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); float main_toolbar_width = (float)m_parent.get_main_toolbar_width();
float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width();
float collapse_width = (float)m_parent.get_collapse_toolbar_width(); float collapse_width = (float)m_parent.get_collapse_toolbar_width();
float separator_width = (float)m_parent.get_separator_toolbar_width();
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
//float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom;
float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom; float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width + separator_width - collapse_width));
//float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom;
zoomed_top_x = main_toolbar_left + (main_toolbar_width)*inv_zoom; top_x = main_toolbar_left + main_toolbar_width + separator_width / 2;
top_x = top_x * inv_cnv_w * 2;
} }
float zoomed_top_y = 0.5f * cnv_h * inv_zoom; float top_y = 1.0f;
#else
//float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom;
//float zoomed_top_y = (0.5f * height) * inv_zoom;
float zoomed_top_x = (0.5f * cnv_w - width) * inv_zoom;
float main_toolbar_height = (float)m_parent.get_main_toolbar_height();
float assemble_view_height = (float)m_parent.get_assemble_view_toolbar_height();
//float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
float zoomed_top_y = 0.5f * (height + assemble_view_height - main_toolbar_height) * inv_zoom;
#endif
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": zoomed_top_y %1%, space_height %2%, main_toolbar_height %3% zoomed_top_x %4%") % zoomed_top_y % space_height % main_toolbar_height % zoomed_top_x;
float zoomed_left = zoomed_top_x; render_background(top_x, top_y, top_x + width, top_y - height, border_w, border_h);
float zoomed_top = zoomed_top_y;
float zoomed_right = zoomed_left + width * inv_zoom;
float zoomed_bottom = zoomed_top - height * inv_zoom;
render_background(zoomed_left, zoomed_top, zoomed_right, zoomed_bottom, zoomed_border); top_x += border_w;
top_y -= border_h;
zoomed_top_x += zoomed_border; const float icons_size_x = 2.0f * m_layout.scaled_icons_size() * inv_cnv_w;
zoomed_top_y -= zoomed_border; const float icons_size_y = 2.0f * m_layout.scaled_icons_size() * inv_cnv_h;
float icons_size = m_layout.scaled_icons_size();
float zoomed_icons_size = icons_size * inv_zoom;
float zoomed_stride_y = m_layout.scaled_stride_y() * inv_zoom;
//BBS: GUI refactor: GLToolbar&&Gizmo adjust //BBS: GUI refactor: GLToolbar&&Gizmo adjust
float zoomed_stride_x = m_layout.scaled_stride_x() * inv_zoom; const float stride_x = 2.0f * m_layout.scaled_stride_x() * inv_cnv_w;
unsigned int icons_texture_id = m_icons_texture.get_id(); const unsigned int icons_texture_id = m_icons_texture.get_id();
int tex_width = m_icons_texture.get_width(); const int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height(); const int tex_height = m_icons_texture.get_height();
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1)) if (icons_texture_id == 0 || tex_width <= 1 || tex_height <= 1)
return; return;
float du = (float)(tex_width - 1) / (6.0f * (float)tex_width); // 6 is the number of possible states if the icons const float du = (float)(tex_width - 1) / (6.0f * (float)tex_width); // 6 is the number of possible states if the icons
float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height); const float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height);
// tiles in the texture are spaced by 1 pixel // tiles in the texture are spaced by 1 pixel
float u_offset = 1.0f / (float)tex_width; const float u_offset = 1.0f / (float)tex_width;
float v_offset = 1.0f / (float)tex_height; const float v_offset = 1.0f / (float)tex_height;
bool is_render_current = false; bool is_render_current = false;
for (size_t idx : selectable_idxs) for (size_t idx : selectable_idxs) {
{
GLGizmoBase* gizmo = m_gizmos[idx].get(); GLGizmoBase* gizmo = m_gizmos[idx].get();
unsigned int sprite_id = gizmo->get_sprite_id(); const unsigned int sprite_id = gizmo->get_sprite_id();
// higlighted state needs to be decided first so its highlighting in every other state // higlighted state needs to be decided first so its highlighting in every other state
int icon_idx = (m_highlight.first == idx ? (m_highlight.second ? 4 : 5) : (m_current == idx) ? 2 : ((m_hover == idx) ? 1 : (gizmo->is_activable()? 0 : 3))); const int icon_idx = (m_highlight.first == idx ? (m_highlight.second ? 4 : 5) : (m_current == idx) ? 2 : ((m_hover == idx) ? 1 : (gizmo->is_activable()? 0 : 3)));
float v_top = v_offset + sprite_id * dv; const float u_left = u_offset + icon_idx * du;
float u_left = u_offset + icon_idx * du; const float u_right = u_left + du - u_offset;
float v_bottom = v_top + dv - v_offset; const float v_top = v_offset + sprite_id * dv;
float u_right = u_left + du - u_offset; const float v_bottom = v_top + dv - v_offset;
GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + icons_size_x, top_y - icons_size_y, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (idx == m_current) { if (idx == m_current) {
//BBS: GUI refactor: GLToolbar&&Gizmo adjust //BBS: GUI refactor: GLToolbar&&Gizmo adjust
//render_input_window uses a different coordination(imgui) //render_input_window uses a different coordination(imgui)
//1. no need to scale by camera zoom, set {0,0} at left-up corner for imgui //1. no need to scale by camera zoom, set {0,0} at left-up corner for imgui
#if BBS_TOOLBAR_ON_TOP
//gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top); //gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top);
gizmo->render_input_window(0.5 * cnv_w + zoomed_top_x * zoom, height, cnv_h); gizmo->render_input_window(0.5 * cnv_w + 0.5f * top_x * cnv_w, get_scaled_total_height(), cnv_h);
is_render_current = true; is_render_current = true;
#else
float toolbar_top = cnv_h - wxGetApp().plater()->get_view_toolbar().get_height();
//gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top);
gizmo->render_input_window(cnv_w - width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top);
#endif
} }
#if BBS_TOOLBAR_ON_TOP top_x += stride_x;
zoomed_top_x += zoomed_stride_x;
#else
zoomed_top_y -= zoomed_stride_y;
#endif
} }
// BBS simplify gizmo is not a selected gizmo and need to render input window // BBS simplify gizmo is not a selected gizmo and need to render input window
if (!is_render_current && m_current != Undefined) { if (!is_render_current && m_current != Undefined) {
m_gizmos[m_current]->render_input_window(0.5 * cnv_w + zoomed_top_x * zoom, height, cnv_h); m_gizmos[m_current]->render_input_window(0.5 * cnv_w + 0.5f * top_x * cnv_w, get_scaled_total_height(), cnv_h);
} }
} }
@ -1542,14 +1523,12 @@ GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& g
return GLGizmosManager::EType::Undefined; return GLGizmosManager::EType::Undefined;
} }
bool GLGizmosManager::generate_icons_texture() const bool GLGizmosManager::generate_icons_texture()
{ {
std::string path = resources_dir() + "/images/"; std::string path = resources_dir() + "/images/";
std::vector<std::string> filenames; std::vector<std::string> filenames;
for (size_t idx=0; idx<m_gizmos.size(); ++idx) for (size_t idx = 0; idx<m_gizmos.size(); ++idx) {
{ if (m_gizmos[idx] != nullptr) {
if (m_gizmos[idx] != nullptr)
{
const std::string& icon_filename = m_gizmos[idx]->get_icon_filename(); const std::string& icon_filename = m_gizmos[idx]->get_icon_filename();
if (!icon_filename.empty()) if (!icon_filename.empty())
filenames.push_back(path + icon_filename); filenames.push_back(path + icon_filename);

View file

@ -325,11 +325,11 @@ public:
bool get_uniform_scaling() const { return m_object_manipulation.get_uniform_scaling();} bool get_uniform_scaling() const { return m_object_manipulation.get_uniform_scaling();}
private: private:
void render_background(float left, float top, float right, float bottom, float border) const; void render_background(float left, float top, float right, float bottom, float border_w, float border_h) const;
void do_render_overlay() const; void do_render_overlay() const;
bool generate_icons_texture() const; bool generate_icons_texture();
void update_on_off_state(const Vec2d& mouse_pos); void update_on_off_state(const Vec2d& mouse_pos);
std::string update_hover_state(const Vec2d& mouse_pos); std::string update_hover_state(const Vec2d& mouse_pos);

View file

@ -8,6 +8,7 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Plater.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -73,13 +74,19 @@ void MeshClipper::render_cut(const ColorRGBA& color)
if (! m_triangles_valid) if (! m_triangles_valid)
recalculate_triangles(); recalculate_triangles();
if (m_model.vertices_count() == 0 || m_model.indices_count() == 0)
return;
GLShaderProgram* curr_shader = wxGetApp().get_current_shader(); GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
if (curr_shader != nullptr) if (curr_shader != nullptr)
curr_shader->stop_using(); curr_shader->stop_using();
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_model.set_color(color); m_model.set_color(color);
m_model.render(); m_model.render();
shader->stop_using(); shader->stop_using();
@ -205,7 +212,7 @@ void MeshClipper::recalculate_triangles()
m_model.reset(); m_model.reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(m_triangles2d.size()) }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 };
init_data.reserve_vertices(m_triangles2d.size()); init_data.reserve_vertices(m_triangles2d.size());
init_data.reserve_indices(m_triangles2d.size()); init_data.reserve_indices(m_triangles2d.size());
@ -215,10 +222,7 @@ void MeshClipper::recalculate_triangles()
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 + 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>()); 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(); const size_t idx = it - m_triangles2d.cbegin();
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_triangle((unsigned int)idx, (unsigned int)idx + 1, (unsigned int)idx + 2);
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()) if (!init_data.is_empty())

View file

@ -351,7 +351,7 @@ static bool init_model_from_lines(GLModel &model, const Lines &lines, float z)
{ {
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(2 * lines.size()) }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2 * lines.size()); init_data.reserve_vertices(2 * lines.size());
init_data.reserve_indices(2 * lines.size()); init_data.reserve_indices(2 * lines.size());
@ -359,10 +359,7 @@ static bool init_model_from_lines(GLModel &model, const Lines &lines, float z)
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), z)); init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), z));
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), z)); init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), z));
const unsigned int vertices_counter = (unsigned int)init_data.vertices_count(); const unsigned int vertices_counter = (unsigned int)init_data.vertices_count();
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_line(vertices_counter - 2, vertices_counter - 1);
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);
} }
model.init_from(std::move(init_data)); model.init_from(std::move(init_data));
@ -374,7 +371,7 @@ static bool init_model_from_lines(GLModel &model, const Lines3 &lines)
{ {
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = {GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::index_type(2 * lines.size())}; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(2 * lines.size()); init_data.reserve_vertices(2 * lines.size());
init_data.reserve_indices(2 * lines.size()); init_data.reserve_indices(2 * lines.size());
@ -382,10 +379,7 @@ static bool init_model_from_lines(GLModel &model, const Lines3 &lines)
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), unscale<float>(l.a.z()))); init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), unscale<float>(l.a.z())));
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), unscale<float>(l.b.z()))); init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), unscale<float>(l.b.z())));
const unsigned int vertices_counter = (unsigned int) init_data.vertices_count(); const unsigned int vertices_counter = (unsigned int) init_data.vertices_count();
if (init_data.format.index_type == GLModel::Geometry::EIndexType::USHORT) init_data.add_line(vertices_counter - 2, vertices_counter - 1);
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);
} }
model.init_from(std::move(init_data)); model.init_from(std::move(init_data));
@ -583,9 +577,12 @@ void PartPlate::render_logo_texture(GLTexture &logo_texture, GLModel& logo_buffe
} }
if (logo_buffer.is_initialized()) { if (logo_buffer.is_initialized()) {
GLShaderProgram* shader = wxGetApp().get_shader("printbed"); GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera &camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("transparent_background", 0); shader->set_uniform("transparent_background", 0);
shader->set_uniform("svg_source", 0); shader->set_uniform("svg_source", 0);
@ -852,9 +849,12 @@ void PartPlate::show_tooltip(const std::string tooltip)
void PartPlate::render_icons(bool bottom, bool only_name, int hover_id) void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
{ {
GLShaderProgram* shader = wxGetApp().get_shader("printbed"); GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera &camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("transparent_background", bottom); shader->set_uniform("transparent_background", bottom);
//shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg")); //shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg"));
shader->set_uniform("svg_source", 0); shader->set_uniform("svg_source", 0);
@ -940,9 +940,12 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
void PartPlate::render_only_numbers(bool bottom) void PartPlate::render_only_numbers(bool bottom)
{ {
GLShaderProgram* shader = wxGetApp().get_shader("printbed"); GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
const Camera &camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("transparent_background", bottom); shader->set_uniform("transparent_background", bottom);
//shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg")); //shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg"));
shader->set_uniform("svg_source", 0); shader->set_uniform("svg_source", 0);
@ -968,14 +971,17 @@ void PartPlate::render_only_numbers(bool bottom)
} }
} }
void PartPlate::render_rectangle_for_picking(GLModel &buffer, const ColorRGBA render_color) void PartPlate::render_rectangle_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix, GLModel &buffer, const ColorRGBA render_color)
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
GLShaderProgram *shader = wxGetApp().get_shader("flat"); GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_matrix", projection_matrix);
//glsafe(::glDepthMask(GL_FALSE)); //glsafe(::glDepthMask(GL_FALSE));
buffer.set_color(render_color); buffer.set_color(render_color);
buffer.render(); buffer.render();
@ -1203,36 +1209,36 @@ void PartPlate::render_right_arrow(const ColorRGBA render_color, bool use_lighti
} }
*/ */
void PartPlate::on_render_for_picking() { void PartPlate::on_render_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix) {
//glsafe(::glDisable(GL_DEPTH_TEST)); //glsafe(::glDisable(GL_DEPTH_TEST));
int hover_id = 0; int hover_id = 0;
ColorRGBA color = picking_color_component(hover_id); ColorRGBA color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
//render_grabber(m_grabber_color, false); //render_grabber(m_grabber_color, false);
render_rectangle_for_picking(m_triangles, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_triangles, m_grabber_color);
hover_id = 1; hover_id = 1;
color = picking_color_component(hover_id); color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
//render_left_arrow(m_grabber_color, false); //render_left_arrow(m_grabber_color, false);
render_rectangle_for_picking(m_del_icon, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_del_icon, m_grabber_color);
hover_id = 2; hover_id = 2;
color = picking_color_component(hover_id); color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
render_rectangle_for_picking(m_orient_icon, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_orient_icon, m_grabber_color);
hover_id = 3; hover_id = 3;
color = picking_color_component(hover_id); color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
render_rectangle_for_picking(m_arrange_icon, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_arrange_icon, m_grabber_color);
hover_id = 4; hover_id = 4;
color = picking_color_component(hover_id); color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
//render_right_arrow(m_grabber_color, false); //render_right_arrow(m_grabber_color, false);
render_rectangle_for_picking(m_lock_icon, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_lock_icon, m_grabber_color);
hover_id = 5; hover_id = 5;
color = picking_color_component(hover_id); color = picking_color_component(hover_id);
m_grabber_color = color; m_grabber_color = color;
if (m_partplate_list->render_plate_settings) if (m_partplate_list->render_plate_settings)
render_rectangle_for_picking(m_plate_settings_icon, m_grabber_color); render_rectangle_for_picking(view_matrix, projection_matrix, m_plate_settings_icon, m_grabber_color);
} }
ColorRGBA PartPlate::picking_color_component(int idx) const ColorRGBA PartPlate::picking_color_component(int idx) const
@ -2494,7 +2500,7 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const
return print_volume.intersects(bb); return print_volume.intersects(bb);
} }
void PartPlate::render(bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali) void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali)
{ {
GLShaderProgram *shader = wxGetApp().get_shader("flat_attr"); GLShaderProgram *shader = wxGetApp().get_shader("flat_attr");
if (shader != nullptr) { if (shader != nullptr) {
@ -2503,8 +2509,8 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color,
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
const Transform3d matrix = wxGetApp().plater()->get_camera().get_projection_view_matrix(); shader->set_uniform("view_model_matrix", view_matrix);
shader->set_uniform("projection_view_model_matrix", matrix); shader->set_uniform("projection_matrix", projection_matrix);
if (!bottom) { if (!bottom) {
// draw background // draw background
@ -4352,7 +4358,7 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
/*rendering related functions*/ /*rendering related functions*/
//render //render
void PartPlateList::render(bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali) void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali)
{ {
const std::lock_guard<std::mutex> local_lock(m_plates_mutex); const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
std::vector<PartPlate*>::iterator it = m_plate_list.begin(); std::vector<PartPlate*>::iterator it = m_plate_list.begin();
@ -4377,25 +4383,25 @@ void PartPlateList::render(bool bottom, bool only_current, bool only_body, int h
if (current_index == m_current_plate) { if (current_index == m_current_plate) {
PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode; PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode;
if (plate_hover_index == current_index) if (plate_hover_index == current_index)
(*it)->render(bottom, only_body, false, height_mode, plate_hover_action, render_cali); (*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, plate_hover_action, render_cali);
else else
(*it)->render(bottom, only_body, false, height_mode, -1, render_cali); (*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, -1, render_cali);
} }
else { else {
if (plate_hover_index == current_index) if (plate_hover_index == current_index)
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali); (*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali);
else else
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali); (*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali);
} }
} }
} }
void PartPlateList::render_for_picking_pass() void PartPlateList::render_for_picking_pass(const Transform3d &view_matrix, const Transform3d &projection_matrix)
{ {
const std::lock_guard<std::mutex> local_lock(m_plates_mutex); const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
std::vector<PartPlate*>::iterator it = m_plate_list.begin(); std::vector<PartPlate*>::iterator it = m_plate_list.begin();
for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) { for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) {
(*it)->render_for_picking(); (*it)->render_for_picking(view_matrix, projection_matrix);
} }
} }

View file

@ -181,8 +181,8 @@ private:
void render_icons(bool bottom, bool only_name = false, int hover_id = -1); void render_icons(bool bottom, bool only_name = false, int hover_id = -1);
void render_only_numbers(bool bottom); void render_only_numbers(bool bottom);
void render_plate_name_texture(); void render_plate_name_texture();
void render_rectangle_for_picking(GLModel &buffer, const ColorRGBA render_color); void render_rectangle_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix, GLModel &buffer, const ColorRGBA render_color);
void on_render_for_picking(); void on_render_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix);
ColorRGBA picking_color_component(int idx) const; ColorRGBA picking_color_component(int idx) const;
public: public:
@ -341,8 +341,8 @@ public:
bool contains(const BoundingBoxf3& bb) const; bool contains(const BoundingBoxf3& bb) const;
bool intersects(const BoundingBoxf3& bb) const; bool intersects(const BoundingBoxf3& bb) const;
void render(bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false); void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false);
void render_for_picking() { on_render_for_picking(); } void render_for_picking(const Transform3d &view_matrix, const Transform3d &projection_matrix) { on_render_for_picking(view_matrix, projection_matrix); }
void set_selected(); void set_selected();
void set_unselected(); void set_unselected();
void set_hover_id(int id) { m_hover_id = id; } void set_hover_id(int id) { m_hover_id = id; }
@ -740,8 +740,8 @@ public:
/*rendering related functions*/ /*rendering related functions*/
void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; } void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
void render(bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false); void render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false);
void render_for_picking_pass(); void render_for_picking_pass(const Transform3d& view_matrix, const Transform3d& projection_matrix);
void set_render_option(bool bedtype_texture, bool plate_settings); void set_render_option(bool bedtype_texture, bool plate_settings);
void set_render_cali(bool value = true) { render_cali_logo = value; } void set_render_cali(bool value = true) { render_cali_logo = value; }
BoundingBoxf3& get_bounding_box() { return m_bounding_box; } BoundingBoxf3& get_bounding_box() { return m_bounding_box; }

View file

@ -1570,22 +1570,26 @@ void Selection::render_center(bool gizmo_is_dragging)
if (!m_valid || is_empty()) if (!m_valid || is_empty())
return; return;
const Vec3d center = gizmo_is_dragging ? m_cache.dragging_center : get_bounding_box().center(); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
glsafe(::glDisable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
glsafe(::glTranslated(center.x(), center.y(), center.z()));
GLShaderProgram* shader = wxGetApp().get_shader("flat");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
m_vbo_sphere.set_color(-1, ColorRGBA::WHITE());
const Vec3d center = gizmo_is_dragging ? m_cache.dragging_center : get_bounding_box().center();
glsafe(::glDisable(GL_DEPTH_TEST));
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(center);
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_vbo_sphere.set_color(ColorRGBA::WHITE());
m_vbo_sphere.render(); m_vbo_sphere.render();
shader->stop_using(); shader->stop_using();
glsafe(::glPopMatrix());
} }
#endif // ENABLE_RENDER_SELECTION_CENTER #endif // ENABLE_RENDER_SELECTION_CENTER
@ -1596,7 +1600,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
if (sidebar_field.empty()) if (sidebar_field.empty())
return; return;
GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat_attr" : "gouraud_light_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
@ -1604,16 +1608,14 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glPushMatrix()); const Transform3d base_matrix = Geometry::assemble_transform(get_bounding_box().center());
Transform3d orient_matrix = Transform3d::Identity();
if (!boost::starts_with(sidebar_field, "layer")) { if (!boost::starts_with(sidebar_field, "layer")) {
const Vec3d& center = get_bounding_box().center(); shader->set_uniform("emission_factor", 0.05f);
// BBS // BBS
if (is_single_full_instance()/* && !wxGetApp().obj_manipul()->get_world_coordinates()*/) { if (is_single_full_instance()/* && !wxGetApp().obj_manipul()->get_world_coordinates()*/) {
glsafe(::glTranslated(center.x(), center.y(), center.z()));
if (!boost::starts_with(sidebar_field, "position")) { if (!boost::starts_with(sidebar_field, "position")) {
Transform3d orient_matrix = Transform3d::Identity();
if (boost::starts_with(sidebar_field, "scale")) if (boost::starts_with(sidebar_field, "scale"))
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else if (boost::starts_with(sidebar_field, "rotation")) { else if (boost::starts_with(sidebar_field, "rotation")) {
@ -1621,51 +1623,45 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else if (boost::ends_with(sidebar_field, "y")) { else if (boost::ends_with(sidebar_field, "y")) {
const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation();
if (rotation(0) == 0.0) if (rotation.x() == 0.0)
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else else
orient_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); orient_matrix.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()));
} }
} }
glsafe(::glMultMatrixd(orient_matrix.data()));
} }
} else if (is_single_volume() || is_single_modifier()) { }
glsafe(::glTranslated(center.x(), center.y(), center.z())); else if (is_single_volume() || is_single_modifier()) {
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
if (!boost::starts_with(sidebar_field, "position")) if (!boost::starts_with(sidebar_field, "position"))
orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
glsafe(::glMultMatrixd(orient_matrix.data())); }
} else { else {
glsafe(::glTranslated(center(0), center(1), center(2))); if (requires_local_axes())
if (requires_local_axes()) { orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
const Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
glsafe(::glMultMatrixd(orient_matrix.data()));
}
} }
} }
if (!boost::starts_with(sidebar_field, "layer")) if (!boost::starts_with(sidebar_field, "layer"))
glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
if (boost::starts_with(sidebar_field, "position")) if (boost::starts_with(sidebar_field, "position"))
render_sidebar_position_hints(sidebar_field); render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix);
else if (boost::starts_with(sidebar_field, "rotation")) else if (boost::starts_with(sidebar_field, "rotation"))
render_sidebar_rotation_hints(sidebar_field); render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size")) else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
//BBS: GUI refactor: add uniform_scale from gizmo //BBS: GUI refactor: add uniform_scale from gizmo
render_sidebar_scale_hints(sidebar_field, uniform_scale); render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix);
else if (boost::starts_with(sidebar_field, "layer")) else if (boost::starts_with(sidebar_field, "layer"))
render_sidebar_layers_hints(sidebar_field); render_sidebar_layers_hints(sidebar_field, *shader);
glsafe(::glPopMatrix());
shader->stop_using(); shader->stop_using();
} }
bool Selection::requires_local_axes() const bool Selection::requires_local_axes() const
{ {
return (m_mode == Volume) && is_from_single_instance(); return m_mode == Volume && is_from_single_instance();
} }
void Selection::cut_to_clipboard() void Selection::cut_to_clipboard()
@ -1681,8 +1677,7 @@ void Selection::copy_to_clipboard()
m_clipboard.reset(); m_clipboard.reset();
for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) {
{
ModelObject* src_object = m_model->objects[object.first]; ModelObject* src_object = m_model->objects[object.first];
ModelObject* dst_object = m_clipboard.add_object(); ModelObject* dst_object = m_clipboard.add_object();
dst_object->name = src_object->name; dst_object->name = src_object->name;
@ -1695,26 +1690,22 @@ void Selection::copy_to_clipboard()
dst_object->layer_height_profile.assign(src_object->layer_height_profile); dst_object->layer_height_profile.assign(src_object->layer_height_profile);
dst_object->origin_translation = src_object->origin_translation; dst_object->origin_translation = src_object->origin_translation;
for (int i : object.second) for (int i : object.second) {
{
dst_object->add_instance(*src_object->instances[i]); dst_object->add_instance(*src_object->instances[i]);
} }
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
// Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance. // Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance.
const GLVolume* volume = (*m_volumes)[i]; const GLVolume* volume = (*m_volumes)[i];
if ((volume->object_idx() == object.first) && (volume->instance_idx() == *object.second.begin())) if (volume->object_idx() == object.first && volume->instance_idx() == *object.second.begin()) {
{
int volume_idx = volume->volume_idx(); int volume_idx = volume->volume_idx();
if ((0 <= volume_idx) && (volume_idx < (int)src_object->volumes.size())) if (0 <= volume_idx && volume_idx < (int)src_object->volumes.size()) {
{
ModelVolume* src_volume = src_object->volumes[volume_idx]; ModelVolume* src_volume = src_object->volumes[volume_idx];
ModelVolume* dst_volume = dst_object->add_volume(*src_volume); ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
dst_volume->set_new_unique_id(); dst_volume->set_new_unique_id();
} else {
assert(false);
} }
else
assert(false);
} }
} }
} }
@ -2167,7 +2158,7 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co
const Vec3f size = 0.2f * box.size().cast<float>(); const Vec3f size = 0.2f * box.size().cast<float>();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(48); init_data.reserve_vertices(48);
init_data.reserve_indices(48); init_data.reserve_indices(48);
@ -2230,7 +2221,7 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co
// indices // indices
for (unsigned short i = 0; i < 48; ++i) { for (unsigned short i = 0; i < 48; ++i) {
init_data.add_ushort_index(i); init_data.add_index(i);
} }
m_box.init_from(std::move(init_data)); m_box.init_from(std::move(init_data));
@ -2240,11 +2231,14 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, const ColorRGB& co
glsafe(::glLineWidth(2.0f * m_scale_factor)); glsafe(::glLineWidth(2.0f * m_scale_factor));
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_box.set_color(to_rgba(color)); m_box.set_color(to_rgba(color));
m_box.render(); m_box.render();
shader->stop_using(); shader->stop_using();
@ -2255,91 +2249,103 @@ static ColorRGBA get_color(Axis axis)
return GLGizmoBase::AXES_COLOR[axis]; return GLGizmoBase::AXES_COLOR[axis];
} }
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) void Selection::render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& matrix)
{ {
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_matrix = camera.get_view_matrix() * matrix;
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
if (boost::ends_with(sidebar_field, "x")) { if (boost::ends_with(sidebar_field, "x")) {
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); const Transform3d view_model_matrix = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ());
shader.set_uniform("view_model_matrix", view_model_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.set_color(get_color(X)); m_arrow.set_color(get_color(X));
m_arrow.render(); m_arrow.render();
} }
else if (boost::ends_with(sidebar_field, "y")) { else if (boost::ends_with(sidebar_field, "y")) {
shader.set_uniform("view_model_matrix", view_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.set_color(get_color(Y)); m_arrow.set_color(get_color(Y));
m_arrow.render(); m_arrow.render();
} }
else if (boost::ends_with(sidebar_field, "z")) { else if (boost::ends_with(sidebar_field, "z")) {
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); const Transform3d view_model_matrix = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX());
shader.set_uniform("view_model_matrix", view_model_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.set_color(get_color(Z)); m_arrow.set_color(get_color(Z));
m_arrow.render(); m_arrow.render();
} }
} }
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& matrix)
{ {
auto render_sidebar_rotation_hint = [this]() { auto render_sidebar_rotation_hint = [this](GLShaderProgram& shader, const Transform3d& matrix) {
Transform3d view_model_matrix = matrix;
shader.set_uniform("view_model_matrix", view_model_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_curved_arrow.render(); m_curved_arrow.render();
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); view_model_matrix = matrix * Geometry::assemble_transform(Vec3d::Zero(), PI * Vec3d::UnitZ());
shader.set_uniform("view_model_matrix", view_model_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_curved_arrow.render(); m_curved_arrow.render();
}; };
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_matrix = camera.get_view_matrix() * matrix;
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
if (boost::ends_with(sidebar_field, "x")) { if (boost::ends_with(sidebar_field, "x")) {
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
m_curved_arrow.set_color(get_color(X)); m_curved_arrow.set_color(get_color(X));
render_sidebar_rotation_hint(); render_sidebar_rotation_hint(shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY()));
} }
else if (boost::ends_with(sidebar_field, "y")) { else if (boost::ends_with(sidebar_field, "y")) {
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
m_curved_arrow.set_color(get_color(Y)); m_curved_arrow.set_color(get_color(Y));
render_sidebar_rotation_hint(); render_sidebar_rotation_hint(shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX()));
} }
else if (boost::ends_with(sidebar_field, "z")) { else if (boost::ends_with(sidebar_field, "z")) {
m_curved_arrow.set_color(get_color(Z)); m_curved_arrow.set_color(get_color(Z));
render_sidebar_rotation_hint(); render_sidebar_rotation_hint(shader, view_matrix);
} }
} }
//BBS: GUI refactor: add gizmo uniform_scale //BBS: GUI refactor: add gizmo uniform_scale
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale) void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale, GLShaderProgram& shader, const Transform3d& matrix)
{ {
// BBS // BBS
//bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling(); //bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale; bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale;
auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis, GLShaderProgram& shader, const Transform3d& matrix) {
m_arrow.set_color(uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); m_arrow.set_color(uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis));
GLShaderProgram* shader = wxGetApp().get_current_shader(); Transform3d view_model_matrix = matrix * Geometry::assemble_transform(5.0 * Vec3d::UnitY());
if (shader != nullptr) shader.set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("emission_factor", 0.0f); shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
glsafe(::glTranslated(0.0, 5.0, 0.0));
m_arrow.render(); m_arrow.render();
glsafe(::glTranslated(0.0, -10.0, 0.0)); view_model_matrix = matrix * Geometry::assemble_transform(-5.0 * Vec3d::UnitY(), PI * Vec3d::UnitZ());
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); shader.set_uniform("view_model_matrix", view_model_matrix);
shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.render(); m_arrow.render();
}; };
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_matrix = camera.get_view_matrix() * matrix;
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
if (boost::ends_with(sidebar_field, "x") || uniform_scale) { if (boost::ends_with(sidebar_field, "x") || uniform_scale) {
glsafe(::glPushMatrix()); render_sidebar_scale_hint(X, shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ()));
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
render_sidebar_scale_hint(X);
glsafe(::glPopMatrix());
} }
if (boost::ends_with(sidebar_field, "y") || uniform_scale) { if (boost::ends_with(sidebar_field, "y") || uniform_scale) {
glsafe(::glPushMatrix()); render_sidebar_scale_hint(Y, shader, view_matrix);
render_sidebar_scale_hint(Y);
glsafe(::glPopMatrix());
} }
if (boost::ends_with(sidebar_field, "z") || uniform_scale) { if (boost::ends_with(sidebar_field, "z") || uniform_scale) {
glsafe(::glPushMatrix()); render_sidebar_scale_hint(Z, shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX()));
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
render_sidebar_scale_hint(Z);
glsafe(::glPopMatrix());
} }
} }
void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) void Selection::render_sidebar_layers_hints(const std::string& sidebar_field, GLShaderProgram& shader)
{ {
static const float Margin = 10.0f; static const float Margin = 10.0f;
@ -2388,7 +2394,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
m_planes.models[0].reset(); m_planes.models[0].reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(6); init_data.reserve_indices(6);
@ -2399,8 +2405,8 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
init_data.add_vertex(Vec3f(p1.x(), p2.y(), z1)); init_data.add_vertex(Vec3f(p1.x(), p2.y(), z1));
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
m_planes.models[0].init_from(std::move(init_data)); m_planes.models[0].init_from(std::move(init_data));
} }
@ -2410,7 +2416,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
m_planes.models[1].reset(); m_planes.models[1].reset();
GLModel::Geometry init_data; GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(4); init_data.reserve_vertices(4);
init_data.reserve_indices(6); init_data.reserve_indices(6);
@ -2421,12 +2427,16 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field)
init_data.add_vertex(Vec3f(p1.x(), p2.y(), z2)); init_data.add_vertex(Vec3f(p1.x(), p2.y(), z2));
// indices // indices
init_data.add_ushort_triangle(0, 1, 2); init_data.add_triangle(0, 1, 2);
init_data.add_ushort_triangle(2, 3, 0); init_data.add_triangle(2, 3, 0);
m_planes.models[1].init_from(std::move(init_data)); m_planes.models[1].init_from(std::move(init_data));
} }
const Camera& camera = wxGetApp().plater()->get_camera();
shader.set_uniform("view_model_matrix", camera.get_view_matrix());
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
m_planes.models[0].set_color((camera_on_top && type == 1) || (!camera_on_top && type == 2) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); m_planes.models[0].set_color((camera_on_top && type == 1) || (!camera_on_top && type == 2) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR);
m_planes.models[0].render(); m_planes.models[0].render();
m_planes.models[1].set_color((camera_on_top && type == 2) || (!camera_on_top && type == 1) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR); m_planes.models[1].set_color((camera_on_top && type == 2) || (!camera_on_top && type == 1) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR);

View file

@ -408,11 +408,11 @@ private:
void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); } void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
void render_synchronized_volumes(); void render_synchronized_volumes();
void render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color); void render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color);
void render_sidebar_position_hints(const std::string& sidebar_field); void render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& matrix);
void render_sidebar_rotation_hints(const std::string& sidebar_field); void render_sidebar_rotation_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& matrix);
//BBS: GUI refactor: add uniform_scale from gizmo //BBS: GUI refactor: add uniform_scale from gizmo
void render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale); void render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale, GLShaderProgram& shader, const Transform3d& matrix);
void render_sidebar_layers_hints(const std::string& sidebar_field); void render_sidebar_layers_hints(const std::string& sidebar_field, GLShaderProgram& shader);
public: public:
enum SyncRotationType { enum SyncRotationType {

View file

@ -917,7 +917,7 @@ void CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f
ThumbnailData* thumbnail_data = &plate_data_list[0]->plate_thumbnail; ThumbnailData* thumbnail_data = &plate_data_list[0]->plate_thumbnail;
unsigned int thumbnail_width = 512, thumbnail_height = 512; unsigned int thumbnail_width = 512, thumbnail_height = 512;
const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, 0}; const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, 0};
GLShaderProgram* shader = wxGetApp().get_shader("thumbnail"); GLShaderProgram* shader = wxGetApp().get_shader("thumbnail_attr");
for (unsigned int obj_idx = 0; obj_idx < (unsigned int)model->objects.size(); ++ obj_idx) { for (unsigned int obj_idx = 0; obj_idx < (unsigned int)model->objects.size(); ++ obj_idx) {
const ModelObject &model_object = *model->objects[obj_idx]; const ModelObject &model_object = *model->objects[obj_idx];