Merge remote-tracking branch 'origin/et_raycast_picking_rebase' into et_opengl_es_rebase
This commit is contained in:
commit
d836a187d0
@ -351,12 +351,22 @@ Transform3d rotation_transform(const Vec3d& rotation)
|
||||
return transform;
|
||||
}
|
||||
|
||||
void scale_transform(Transform3d& transform, double scale)
|
||||
{
|
||||
return scale_transform(transform, scale * Vec3d::Ones());
|
||||
}
|
||||
|
||||
void scale_transform(Transform3d& transform, const Vec3d& scale)
|
||||
{
|
||||
transform = Transform3d::Identity();
|
||||
transform.scale(scale);
|
||||
}
|
||||
|
||||
Transform3d scale_transform(double scale)
|
||||
{
|
||||
return scale_transform(scale * Vec3d::Ones());
|
||||
}
|
||||
|
||||
Transform3d scale_transform(const Vec3d& scale)
|
||||
{
|
||||
Transform3d transform;
|
||||
|
@ -366,9 +366,11 @@ void rotation_transform(Transform3d& transform, const Vec3d& rotation);
|
||||
Transform3d rotation_transform(const Vec3d& rotation);
|
||||
|
||||
// Sets the given transform by assembling the given scale factors
|
||||
void scale_transform(Transform3d& transform, double scale);
|
||||
void scale_transform(Transform3d& transform, const Vec3d& scale);
|
||||
|
||||
// Returns the transform obtained by assembling the given scale factors
|
||||
Transform3d scale_transform(double scale);
|
||||
Transform3d scale_transform(const Vec3d& scale);
|
||||
|
||||
// Returns the euler angles extracted from the given rotation matrix
|
||||
|
@ -618,6 +618,9 @@ public:
|
||||
|
||||
// The triangular model.
|
||||
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::shared_ptr<const TriangleMesh> mesh_ptr() const { return m_mesh; }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
||||
void set_mesh(TriangleMesh &&mesh) { m_mesh = std::make_shared<const TriangleMesh>(std::move(mesh)); }
|
||||
void set_mesh(const indexed_triangle_set &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
||||
|
@ -12,8 +12,6 @@
|
||||
#define ENABLE_RENDER_SELECTION_CENTER 0
|
||||
// Shows an imgui dialog with camera related data
|
||||
#define ENABLE_CAMERA_STATISTICS 0
|
||||
// Render the picking pass instead of the main scene (use [T] key to toggle between regular rendering and picking pass only rendering)
|
||||
#define ENABLE_RENDER_PICKING_PASS 0
|
||||
// Enable extracting thumbnails from selected gcode and save them as png files
|
||||
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG 0
|
||||
// Disable synchronization of unselected instances
|
||||
@ -73,17 +71,17 @@
|
||||
#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable modified camera control using mouse
|
||||
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable modified rectangle selection
|
||||
#define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable alternative version of file_wildcards()
|
||||
#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable processing of gcode G2 and G3 lines
|
||||
#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable fix of used filament data exported to gcode file
|
||||
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable gizmo grabbers to share common models
|
||||
#define ENABLE_GIZMO_GRABBER_REFACTOR (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable copy of custom bed model and texture
|
||||
#define ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable picking using raytracing
|
||||
#define ENABLE_RAYCAST_PICKING (1 && ENABLE_LEGACY_OPENGL_REMOVAL)
|
||||
#define ENABLE_RAYCAST_PICKING_DEBUG (0 && ENABLE_RAYCAST_PICKING)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
@ -27,6 +27,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/GLShader.hpp
|
||||
GUI/GLCanvas3D.hpp
|
||||
GUI/GLCanvas3D.cpp
|
||||
GUI/SceneRaycaster.hpp
|
||||
GUI/SceneRaycaster.cpp
|
||||
GUI/OpenGLManager.hpp
|
||||
GUI/OpenGLManager.cpp
|
||||
GUI/Selection.hpp
|
||||
|
@ -249,6 +249,11 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
|
||||
m_axes.set_origin({ 0.0, 0.0, static_cast<double>(GROUND_Z) });
|
||||
m_axes.set_stem_length(0.1f * static_cast<float>(m_build_volume.bounding_volume().max_size()));
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// unregister from picking
|
||||
wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Bed);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// Let the calee to update the UI.
|
||||
return true;
|
||||
}
|
||||
@ -301,7 +306,11 @@ void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_model.model.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
#else
|
||||
m_model.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
m_model.set_color(-1, picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -341,7 +350,11 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box() const
|
||||
out.merge(out.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, out.max.z()));
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
// extend to contain model, if any
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
BoundingBoxf3 model_bb = m_model.model.get_bounding_box();
|
||||
#else
|
||||
BoundingBoxf3 model_bb = m_model.get_bounding_box();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
if (model_bb.defined) {
|
||||
model_bb.translate(m_model_offset);
|
||||
out.merge(model_bb);
|
||||
@ -391,7 +404,16 @@ void Bed3D::init_triangles()
|
||||
init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_model.model.get_filename().empty() && m_model.mesh_raycaster == nullptr)
|
||||
// register for picking
|
||||
register_raycasters_for_picking(init_data, Transform3d::Identity());
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_triangles.init_from(std::move(init_data));
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_triangles.set_color(DEFAULT_MODEL_COLOR);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
void Bed3D::init_gridlines()
|
||||
@ -771,9 +793,17 @@ void Bed3D::render_model()
|
||||
if (m_model_filename.empty())
|
||||
return;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_model.model.get_filename() != m_model_filename && m_model.model.init_from_file(m_model_filename)) {
|
||||
#else
|
||||
if (m_model.get_filename() != m_model_filename && m_model.init_from_file(m_model_filename)) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_model.model.set_color(DEFAULT_MODEL_COLOR);
|
||||
#else
|
||||
m_model.set_color(DEFAULT_MODEL_COLOR);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
m_model.set_color(-1, DEFAULT_MODEL_COLOR);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -781,11 +811,20 @@ void Bed3D::render_model()
|
||||
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
|
||||
m_model_offset = to_3d(m_build_volume.bounding_volume2d().center(), -0.03);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// register for picking
|
||||
register_raycasters_for_picking(m_model.model.get_geometry(), Geometry::assemble_transform(m_model_offset));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// update extended bounding box
|
||||
m_extended_bounding_box = this->calc_extended_bounding_box();
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (!m_model.model.get_filename().empty()) {
|
||||
#else
|
||||
if (!m_model.get_filename().empty()) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
@ -800,7 +839,11 @@ void Bed3D::render_model()
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z()));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_model.model.render();
|
||||
#else
|
||||
m_model.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -866,16 +909,35 @@ void Bed3D::render_default(bool bottom, bool picking, bool show_texture)
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const bool has_model = !m_model.model.get_filename().empty();
|
||||
#else
|
||||
const bool has_model = !m_model.get_filename().empty();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (!has_model && !bottom) {
|
||||
// draw background
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
m_triangles.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
m_triangles.render();
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (show_texture) {
|
||||
// draw grid
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
if (!OpenGLManager::get_gl_info().is_core_profile())
|
||||
#endif // ENABLE_GL_CORE_PROFILE
|
||||
glsafe(::glLineWidth(1.5f * m_scale_factor));
|
||||
m_gridlines.set_color(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR);
|
||||
m_gridlines.render();
|
||||
}
|
||||
else
|
||||
render_contour(view_matrix, projection_matrix);
|
||||
#else
|
||||
if (!picking && show_texture) {
|
||||
// draw grid
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
@ -887,6 +949,7 @@ void Bed3D::render_default(bool bottom, bool picking, bool show_texture)
|
||||
}
|
||||
else if (!show_texture)
|
||||
render_contour(view_matrix, projection_matrix);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
@ -979,5 +1042,26 @@ void Bed3D::release_VBOs()
|
||||
}
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void Bed3D::register_raycasters_for_picking(const GLModel::Geometry& geometry, const Transform3d& trafo)
|
||||
{
|
||||
assert(m_model.mesh_raycaster == nullptr);
|
||||
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(geometry.vertices_count());
|
||||
for (size_t i = 0; i < geometry.vertices_count(); ++i) {
|
||||
its.vertices.emplace_back(geometry.extract_position_3(i));
|
||||
}
|
||||
its.indices.reserve(geometry.indices_count() / 3);
|
||||
for (size_t i = 0; i < geometry.indices_count() / 3; ++i) {
|
||||
const size_t tri_id = i * 3;
|
||||
its.indices.emplace_back(geometry.extract_index(tri_id), geometry.extract_index(tri_id + 1), geometry.extract_index(tri_id + 2));
|
||||
}
|
||||
|
||||
m_model.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
wxGetApp().plater()->canvas3D()->add_raycaster_for_picking(SceneRaycaster::EType::Bed, 0, *m_model.mesh_raycaster, trafo);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
@ -8,6 +8,9 @@
|
||||
#else
|
||||
#include "GLModel.hpp"
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include "MeshUtils.hpp"
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -108,7 +111,11 @@ private:
|
||||
GLTexture m_texture;
|
||||
// temporary texture shown until the main texture has still no levels compressed
|
||||
GLTexture m_temp_texture;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel m_model;
|
||||
#else
|
||||
GLModel m_model;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
Vec3d m_model_offset{ Vec3d::Zero() };
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
unsigned int m_vbo_id{ 0 };
|
||||
@ -197,6 +204,10 @@ private:
|
||||
|
||||
void release_VBOs();
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void register_raycasters_for_picking(const GLModel::Geometry& geometry, const Transform3d& trafo);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
};
|
||||
|
||||
} // GUI
|
||||
|
@ -804,15 +804,24 @@ int GLVolumeCollection::load_object_volume(
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::shared_ptr<const TriangleMesh> mesh = model_volume->mesh_ptr();
|
||||
#else
|
||||
const TriangleMesh &mesh = model_volume->mesh();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
this->volumes.emplace_back(new GLVolume());
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.set_color(color_from_model_volume(*model_volume));
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
v.model.init_from(mesh, true);
|
||||
#else
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
v.model.init_from(*mesh);
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
#else
|
||||
v.model.init_from(mesh);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
#else
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
@ -877,8 +886,11 @@ void GLVolumeCollection::load_object_auxiliary(
|
||||
v.model.init_from(mesh, true);
|
||||
#else
|
||||
v.model.init_from(mesh);
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
#else
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
v.indexed_vertex_array.load_mesh(mesh, true);
|
||||
@ -941,8 +953,115 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
// Too narrow tower would interfere with the teeth. The estimate is not precise anyway.
|
||||
depth = std::max(depth, 10.f);
|
||||
float min_width = 30.f;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const float scaled_brim_height = 0.2f / height;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// We'll now create the box with jagged edge. y-coordinates of the pre-generated model
|
||||
// are shifted so that the front edge has y=0 and centerline of the back edge has y=depth:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// We split the box in three main pieces,
|
||||
// the two laterals are identical and the central is the one containing the jagged geometry
|
||||
|
||||
// lateral parts generator
|
||||
auto generate_lateral = [&](float min_x, float max_x) {
|
||||
const std::vector<Vec3f> vertices = {
|
||||
{ min_x, -(depth + brim_width), 0.0f },
|
||||
{ max_x, -(depth + brim_width), 0.0f },
|
||||
{ min_x, -(depth + brim_width), scaled_brim_height },
|
||||
{ max_x, -(depth + brim_width), scaled_brim_height },
|
||||
{ min_x, -depth, scaled_brim_height },
|
||||
{ max_x, -depth, scaled_brim_height },
|
||||
{ min_x, -depth, 1.0f },
|
||||
{ max_x, -depth, 1.0f },
|
||||
{ min_x, 0.0f, 1.0f },
|
||||
{ max_x, 0.0f, 1.0f },
|
||||
{ min_x, 0.0f, scaled_brim_height },
|
||||
{ max_x, 0.0f, scaled_brim_height },
|
||||
{ min_x, brim_width, scaled_brim_height },
|
||||
{ max_x, brim_width, scaled_brim_height },
|
||||
{ min_x, brim_width, 0.0f },
|
||||
{ max_x, brim_width, 0.0f }
|
||||
};
|
||||
const std::vector<Vec3i> triangles = {
|
||||
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 5 }, { 2, 5, 4 }, { 4, 5, 7 }, { 4, 7, 6 }, { 6, 7, 9 }, { 6, 9, 8 },
|
||||
{ 8, 9, 11 }, { 8, 11, 10 }, { 10, 11, 13 }, { 10, 13, 12 }, { 12, 13, 15 }, { 12, 15, 14 }, { 14, 15, 1 }, { 14, 1, 0 }
|
||||
};
|
||||
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(vertices.size());
|
||||
for (const Vec3f& v : vertices) {
|
||||
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
|
||||
}
|
||||
its.indices.reserve(triangles.size());
|
||||
for (const Vec3i& t : triangles) {
|
||||
its.indices.emplace_back(t);
|
||||
}
|
||||
return its;
|
||||
};
|
||||
|
||||
// central parts generator
|
||||
auto generate_central = [&]() {
|
||||
const std::vector<Vec3f> vertices = {
|
||||
{ 38.453f, -(depth + brim_width), 0.0f },
|
||||
{ 61.547f, -(depth + brim_width), 0.0f },
|
||||
{ 38.453f, -(depth + brim_width), scaled_brim_height },
|
||||
{ 61.547f, -(depth + brim_width), scaled_brim_height },
|
||||
{ 38.453f, -depth, scaled_brim_height },
|
||||
{ 61.547f, -depth, scaled_brim_height },
|
||||
{ 38.453f, -depth, 1.0f },
|
||||
{ 61.547f, -depth, 1.0f },
|
||||
{ 38.453f, 0.0f, 1.0f },
|
||||
{ 38.453f + 0.57735f * brim_width, brim_width, 1.0f },
|
||||
{ 44.2265f, 10.0f, 1.0f },
|
||||
{ 50.0f - 0.57735f * brim_width, brim_width, 1.0f },
|
||||
{ 50.0f, 0.0f, 1.0f },
|
||||
{ 55.7735f, -10.0f, 1.0f },
|
||||
{ 61.547f, 0.0f, 1.0f },
|
||||
{ 38.453f, 0.0f, scaled_brim_height },
|
||||
{ 38.453f, brim_width, scaled_brim_height },
|
||||
{ 38.453f + 0.57735f * brim_width, brim_width, scaled_brim_height },
|
||||
{ 50.0f - 0.57735f * brim_width, brim_width, scaled_brim_height },
|
||||
{ 50.0f, 0.0f, scaled_brim_height },
|
||||
{ 55.7735f, -10.0f, scaled_brim_height },
|
||||
{ 61.547f, 0.0f, scaled_brim_height },
|
||||
{ 61.547f, brim_width, scaled_brim_height },
|
||||
{ 38.453f, brim_width, 0.0f },
|
||||
{ 38.453f + 0.57735f * brim_width, brim_width, 0.0f },
|
||||
{ 44.2265f, 10.0f, 0.0f },
|
||||
{ 50.0f - 0.57735f * brim_width, brim_width, 0.0f },
|
||||
{ 61.547f, brim_width, 0.0f }
|
||||
};
|
||||
|
||||
const std::vector<Vec3i> triangles = {
|
||||
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 5 }, { 2, 5, 4 }, { 4, 5, 7 }, { 4, 7, 6 }, { 7, 14, 13 }, { 7, 13, 6 },
|
||||
{ 6, 13, 12 }, { 6, 12, 8 }, { 8, 12, 11 }, { 8, 11, 9 }, { 9, 11, 10 }, { 18, 19, 22 }, { 22, 19, 21 }, { 19, 20, 21 },
|
||||
{ 15, 17, 16 }, { 17, 15, 8 }, { 17, 8, 9 }, { 21, 13, 14 }, { 21, 20, 13 }, { 20, 19, 12 }, { 20, 12, 13 }, { 19, 18, 11 },
|
||||
{ 19, 11, 12 }, { 27, 26, 18 }, { 27, 18, 22 }, { 26, 25, 18 }, { 18, 25, 11 }, { 11, 25, 10 }, { 25, 24, 17 }, { 25, 17, 9 },
|
||||
{ 25, 9, 10 }, { 24, 23, 16 }, { 24, 16, 17 }, { 1, 26, 27 }, { 1, 23, 26 }, { 1, 0, 23 }, { 0, 23, 24 }, { 24, 25, 26 }
|
||||
};
|
||||
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(vertices.size());
|
||||
for (const Vec3f& v : vertices) {
|
||||
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
|
||||
}
|
||||
its.indices.reserve(triangles.size());
|
||||
for (const Vec3i& t : triangles) {
|
||||
its.indices.emplace_back(t);
|
||||
}
|
||||
return its;
|
||||
};
|
||||
|
||||
TriangleMesh tooth_mesh;
|
||||
indexed_triangle_set data = generate_lateral(0.0f, 38.453f);
|
||||
tooth_mesh.merge(TriangleMesh(std::move(data)));
|
||||
data = generate_central();
|
||||
tooth_mesh.merge(TriangleMesh(std::move(data)));
|
||||
data = generate_lateral(61.547f, 100.0f);
|
||||
tooth_mesh.merge(TriangleMesh(std::move(data)));
|
||||
#else
|
||||
float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 },
|
||||
{ 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } };
|
||||
static constexpr const int out_facets_idx[][3] = {
|
||||
@ -957,6 +1076,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
for (const int *face : out_facets_idx)
|
||||
its.indices.emplace_back(face);
|
||||
TriangleMesh tooth_mesh(std::move(its));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// We have the mesh ready. It has one tooth and width of min_width. We will now
|
||||
// append several of these together until we are close to the required width
|
||||
@ -964,24 +1084,110 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
size_t n = std::max(1, int(width / min_width)); // How many shall be merged?
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
mesh.merge(tooth_mesh);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
tooth_mesh.translate(100.0f, 0.0f, 0.0f);
|
||||
#else
|
||||
tooth_mesh.translate(min_width, 0.f, 0.f);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// Now we add the caps along the X axis
|
||||
const float scaled_brim_width_x = brim_width * n * width / min_width;
|
||||
auto generate_negx_cap = [&]() {
|
||||
const std::vector<Vec3f> vertices = {
|
||||
{ -scaled_brim_width_x, -(depth + brim_width), 0.0f },
|
||||
{ 0.0f, -(depth + brim_width), 0.0f },
|
||||
{ -scaled_brim_width_x, -(depth + brim_width), scaled_brim_height },
|
||||
{ 0.0f, -(depth + brim_width), scaled_brim_height },
|
||||
{ 0.0f, -depth, scaled_brim_height },
|
||||
{ 0.0f, -depth, 1.0f },
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, scaled_brim_height },
|
||||
{ 0.0f, brim_width, scaled_brim_height },
|
||||
{ -scaled_brim_width_x, brim_width, scaled_brim_height },
|
||||
{ 0.0f, brim_width, 0.0f },
|
||||
{ -scaled_brim_width_x, brim_width, 0.0f }
|
||||
};
|
||||
|
||||
const std::vector<Vec3i> triangles = {
|
||||
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 4 }, { 2, 4, 9 }, { 9, 4, 7 }, { 9, 7, 8 }, { 9, 8, 10 }, { 9, 10, 11 },
|
||||
{ 11, 10, 1 }, { 11, 1, 0 }, { 11, 0, 2 }, { 11, 2, 9 }, { 7, 4, 5 }, { 7, 5, 6 }
|
||||
};
|
||||
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(vertices.size());
|
||||
for (const Vec3f& v : vertices) {
|
||||
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
|
||||
}
|
||||
its.indices.reserve(triangles.size());
|
||||
for (const Vec3i& t : triangles) {
|
||||
its.indices.emplace_back(t);
|
||||
}
|
||||
return its;
|
||||
};
|
||||
|
||||
auto generate_posx_cap = [&]() {
|
||||
const float posx_cap_x = n * 100.0f;
|
||||
const std::vector<Vec3f> vertices = {
|
||||
{ posx_cap_x, -(depth + brim_width), 0.0f },
|
||||
{ posx_cap_x + scaled_brim_width_x, -(depth + brim_width), 0.0f },
|
||||
{ posx_cap_x, -(depth + brim_width), scaled_brim_height },
|
||||
{ posx_cap_x + scaled_brim_width_x, -(depth + brim_width), scaled_brim_height },
|
||||
{ posx_cap_x, -depth, scaled_brim_height },
|
||||
{ posx_cap_x, -depth, 1.0f },
|
||||
{ posx_cap_x, 0.0f, 1.0f },
|
||||
{ posx_cap_x, 0.0f, scaled_brim_height },
|
||||
{ posx_cap_x, brim_width, scaled_brim_height },
|
||||
{ posx_cap_x + scaled_brim_width_x, brim_width, scaled_brim_height },
|
||||
{ posx_cap_x, brim_width, 0.0f },
|
||||
{ posx_cap_x + scaled_brim_width_x, brim_width, 0.0f }
|
||||
};
|
||||
|
||||
const std::vector<Vec3i> triangles = {
|
||||
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 4 }, { 4, 3, 9 }, { 4, 9, 7 }, { 7, 9, 8 }, { 8, 9, 11 }, { 8, 11, 10 },
|
||||
{ 10, 11, 1 }, { 10, 1, 0 }, { 1, 11, 9 }, { 1, 9, 3 }, { 4, 7, 6 }, { 4, 6, 5 }
|
||||
};
|
||||
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(vertices.size());
|
||||
for (const Vec3f& v : vertices) {
|
||||
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
|
||||
}
|
||||
its.indices.reserve(triangles.size());
|
||||
for (const Vec3i& t : triangles) {
|
||||
its.indices.emplace_back(t);
|
||||
}
|
||||
return its;
|
||||
};
|
||||
|
||||
data = generate_negx_cap();
|
||||
mesh.merge(TriangleMesh(std::move(data)));
|
||||
data = generate_posx_cap();
|
||||
mesh.merge(TriangleMesh(std::move(data)));
|
||||
mesh.scale(Vec3f(width / (n * 100.0f), 1.0f, height)); // Scaling to proper width
|
||||
#else
|
||||
mesh.scale(Vec3f(width / (n * min_width), 1.f, height)); // Scaling to proper width
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
else
|
||||
mesh = make_cube(width, depth, height);
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
// We'll make another mesh to show the brim (fixed layer height):
|
||||
TriangleMesh brim_mesh = make_cube(width + 2.f * brim_width, depth + 2.f * brim_width, 0.2f);
|
||||
brim_mesh.translate(-brim_width, -brim_width, 0.f);
|
||||
mesh.merge(brim_mesh);
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume& v = *volumes.back();
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
v.model.init_from(mesh);
|
||||
v.model.set_color(color);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
v.indexed_vertex_array.load_mesh(mesh);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "libslic3r/Color.hpp"
|
||||
|
||||
#include "GLModel.hpp"
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include "MeshUtils.hpp"
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@ -392,6 +395,10 @@ public:
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GUI::GLModel model;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// raycaster used for picking
|
||||
std::unique_ptr<GUI::MeshRaycaster> mesh_raycaster;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
// Interleaved triangles & normals with indexed triangles & quads.
|
||||
GLIndexedVertexArray indexed_vertex_array;
|
||||
|
@ -91,6 +91,80 @@ void Camera::select_view(const std::string& direction)
|
||||
look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
double Camera::get_near_left() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return m_frustrum_zs.first * (m_projection_matrix.matrix()(0, 2) - 1.0) / m_projection_matrix.matrix()(0, 0);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return -1.0 / m_projection_matrix.matrix()(0, 0) - 0.5 * m_projection_matrix.matrix()(0, 0) * m_projection_matrix.matrix()(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::get_near_right() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return m_frustrum_zs.first * (m_projection_matrix.matrix()(0, 2) + 1.0) / m_projection_matrix.matrix()(0, 0);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return 1.0 / m_projection_matrix.matrix()(0, 0) - 0.5 * m_projection_matrix.matrix()(0, 0) * m_projection_matrix.matrix()(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::get_near_top() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return m_frustrum_zs.first * (m_projection_matrix.matrix()(1, 2) + 1.0) / m_projection_matrix.matrix()(1, 1);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return 1.0 / m_projection_matrix.matrix()(1, 1) - 0.5 * m_projection_matrix.matrix()(1, 1) * m_projection_matrix.matrix()(1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::get_near_bottom() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return m_frustrum_zs.first * (m_projection_matrix.matrix()(1, 2) - 1.0) / m_projection_matrix.matrix()(1, 1);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return -1.0 / m_projection_matrix.matrix()(1, 1) - 0.5 * m_projection_matrix.matrix()(1, 1) * m_projection_matrix.matrix()(1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::get_near_width() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return 2.0 * m_frustrum_zs.first / m_projection_matrix.matrix()(0, 0);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return 2.0 / m_projection_matrix.matrix()(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::get_near_height() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case EType::Perspective:
|
||||
return 2.0 * m_frustrum_zs.first / m_projection_matrix.matrix()(1, 1);
|
||||
default:
|
||||
case EType::Ortho:
|
||||
return 2.0 / m_projection_matrix.matrix()(1, 1);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
double Camera::get_fov() const
|
||||
{
|
||||
switch (m_type)
|
||||
@ -103,6 +177,21 @@ double Camera::get_fov() const
|
||||
};
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void Camera::set_viewport(int x, int y, unsigned int w, unsigned int h)
|
||||
{
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_viewport = { 0, 0, int(w), int(h) };
|
||||
#else
|
||||
glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data()));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
void Camera::apply_viewport() const
|
||||
{
|
||||
glsafe(::glViewport(m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]));
|
||||
}
|
||||
#else
|
||||
void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h)
|
||||
{
|
||||
glsafe(::glViewport(0, 0, w, h));
|
||||
@ -112,6 +201,7 @@ void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h)
|
||||
glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data()));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void Camera::apply_view_matrix()
|
||||
@ -170,6 +260,9 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
||||
}
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
apply_projection(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second);
|
||||
#else
|
||||
switch (m_type)
|
||||
{
|
||||
default:
|
||||
@ -197,6 +290,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
glsafe(::glMatrixMode(GL_PROJECTION));
|
||||
glsafe(::glLoadIdentity());
|
||||
@ -221,6 +315,37 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void Camera::apply_projection(double left, double right, double bottom, double top, double near_z, double far_z)
|
||||
{
|
||||
assert(left != right && bottom != top && near_z != far_z);
|
||||
const double inv_dx = 1.0 / (right - left);
|
||||
const double inv_dy = 1.0 / (top - bottom);
|
||||
const double inv_dz = 1.0 / (far_z - near_z);
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
default:
|
||||
case EType::Ortho:
|
||||
{
|
||||
m_projection_matrix.matrix() << 2.0 * inv_dx, 0.0, 0.0, -(left + right) * inv_dx,
|
||||
0.0, 2.0 * inv_dy, 0.0, -(bottom + top) * inv_dy,
|
||||
0.0, 0.0, -2.0 * inv_dz, -(near_z + far_z) * inv_dz,
|
||||
0.0, 0.0, 0.0, 1.0;
|
||||
break;
|
||||
}
|
||||
case EType::Perspective:
|
||||
{
|
||||
m_projection_matrix.matrix() << 2.0 * near_z * inv_dx, 0.0, (left + right) * inv_dx, 0.0,
|
||||
0.0, 2.0 * near_z * inv_dy, (bottom + top) * inv_dy, 0.0,
|
||||
0.0, 0.0, -(near_z + far_z) * inv_dz, -2.0 * near_z * far_z * inv_dz,
|
||||
0.0, 0.0, -1.0, 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor)
|
||||
{
|
||||
// Calculate the zoom factor needed to adjust the view around the given box.
|
||||
|
@ -89,9 +89,23 @@ public:
|
||||
double get_far_z() const { return m_frustrum_zs.second; }
|
||||
const std::pair<double, double>& get_z_range() const { return m_frustrum_zs; }
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
double get_near_left() const;
|
||||
double get_near_right() const;
|
||||
double get_near_top() const;
|
||||
double get_near_bottom() const;
|
||||
double get_near_width() const;
|
||||
double get_near_height() const;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
double get_fov() const;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void set_viewport(int x, int y, unsigned int w, unsigned int h);
|
||||
void apply_viewport() const;
|
||||
#else
|
||||
void apply_viewport(int x, int y, unsigned int w, unsigned int h);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void apply_view_matrix();
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -99,6 +113,10 @@ public:
|
||||
// If larger z span is needed, pass the desired values of near and far z (negative values are ignored)
|
||||
void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void apply_projection(double left, double right, double bottom, double top, double near_z, double far_z);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor);
|
||||
void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
||||
|
||||
|
@ -29,10 +29,11 @@ void CoordAxes::render(float emission_factor)
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
auto render_axis = [this](GLShaderProgram& shader, const Transform3d& transform) {
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d matrix = camera.get_view_matrix() * transform;
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
const Transform3d matrix = 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());
|
||||
shader.set_uniform("view_normal_matrix", (Matrix3d)(view_matrix.matrix().block(0, 0, 3, 3) * transform.matrix().block(0, 0, 3, 3).inverse().transpose()));
|
||||
m_arrow.render();
|
||||
#else
|
||||
auto render_axis = [this](const Transform3f& transform) {
|
||||
|
@ -1177,9 +1177,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
, m_tab_down(false)
|
||||
, m_cursor_type(Standard)
|
||||
, m_reload_delayed(false)
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
, m_show_picking_texture(false)
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
, m_render_sla_auxiliaries(true)
|
||||
, m_labels(*this)
|
||||
, m_slope(m_volumes)
|
||||
@ -1631,7 +1628,12 @@ void GLCanvas3D::render()
|
||||
// and the viewport was set incorrectly, leading to tripping glAsserts further down
|
||||
// the road (in apply_projection). That's why the minimum size is forced to 10.
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
camera.set_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height()));
|
||||
camera.apply_viewport();
|
||||
#else
|
||||
camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height()));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (camera.requires_zoom_to_bed) {
|
||||
zoom_to_bed();
|
||||
@ -1654,22 +1656,22 @@ void GLCanvas3D::render()
|
||||
wxGetApp().imgui()->new_frame();
|
||||
|
||||
if (m_picking_enabled) {
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (m_rectangle_selection.is_dragging() && !m_rectangle_selection.is_empty())
|
||||
#else
|
||||
if (m_rectangle_selection.is_dragging())
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
// picking pass using rectangle selection
|
||||
_rectangular_selection_picking_pass();
|
||||
else if (!m_volumes.empty())
|
||||
// regular picking pass
|
||||
_picking_pass();
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
else {
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
|
||||
imgui.text("Picking disabled");
|
||||
imgui.end();
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
if (!m_picking_enabled || !m_show_picking_texture) {
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
|
||||
const bool is_looking_downward = camera.is_looking_downward();
|
||||
|
||||
// draw scene
|
||||
@ -1714,9 +1716,11 @@ void GLCanvas3D::render()
|
||||
#else
|
||||
_render_bed(true, true);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
}
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
if (m_picking_enabled && !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging())
|
||||
m_scene_raycaster.render_hit(camera);
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
#if ENABLE_SHOW_CAMERA_TARGET
|
||||
_render_camera_target();
|
||||
@ -2216,6 +2220,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
#else
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
volume.model.init_from(mesh);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
volume.indexed_vertex_array.load_mesh(mesh);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -2231,7 +2238,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#else
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
|
||||
volume.model.init_from(new_mesh);
|
||||
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
|
||||
#else
|
||||
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -2379,6 +2392,23 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
manip->set_dirty();
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// refresh volume raycasters for picking
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Volume);
|
||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
||||
assert(m_volumes.volumes[i]->mesh_raycaster != nullptr);
|
||||
add_raycaster_for_picking(SceneRaycaster::EType::Volume, i, *m_volumes.volumes[i]->mesh_raycaster, m_volumes.volumes[i]->world_matrix());
|
||||
}
|
||||
|
||||
// refresh gizmo elements raycasters for picking
|
||||
GLGizmoBase* curr_gizmo = m_gizmos.get_current();
|
||||
if (curr_gizmo != nullptr)
|
||||
curr_gizmo->unregister_raycasters_for_picking();
|
||||
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Gizmo);
|
||||
if (curr_gizmo != nullptr && !m_selection.is_empty())
|
||||
curr_gizmo->register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// and force this canvas to be redrawn.
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -2751,14 +2781,6 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
}
|
||||
case 'O':
|
||||
case 'o': { _update_camera_zoom(-1.0); break; }
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
case 'T':
|
||||
case 't': {
|
||||
m_show_picking_texture = !m_show_picking_texture;
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
case 'Z':
|
||||
case 'z': {
|
||||
if (!m_selection.is_empty())
|
||||
@ -2931,13 +2953,8 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
_update_selection_from_hover();
|
||||
m_rectangle_selection.stop_dragging();
|
||||
m_mouse.ignore_left_up = true;
|
||||
#if !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
m_dirty = true;
|
||||
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
}
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
m_dirty = true;
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
// set_cursor(Standard);
|
||||
}
|
||||
else if (keyCode == WXK_ALT) {
|
||||
@ -2994,9 +3011,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
m_mouse.ignore_left_up = false;
|
||||
// set_cursor(Cross);
|
||||
}
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
m_dirty = true;
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
}
|
||||
else if (keyCode == WXK_ALT) {
|
||||
if (m_picking_enabled && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)) {
|
||||
@ -3418,19 +3433,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_layers_editing.state = LayersEditing::Editing;
|
||||
_perform_layer_editing_action(&evt);
|
||||
}
|
||||
#if !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
else if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::Seam
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) {
|
||||
m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect);
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
else {
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
const bool rectangle_selection_dragging = m_rectangle_selection.is_dragging();
|
||||
if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
|
||||
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports &&
|
||||
@ -3441,39 +3444,23 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
// Select volume in this 3D canvas.
|
||||
// Don't deselect a volume if layer editing is enabled or any gizmo is active. We want the object to stay selected
|
||||
// during the scene manipulation.
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && !rectangle_selection_dragging) {
|
||||
#else
|
||||
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (evt.LeftDown() && !m_hover_volume_idxs.empty()) {
|
||||
int volume_idx = get_first_hover_volume_idx();
|
||||
bool already_selected = m_selection.contains_volume(volume_idx);
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
bool shift_down = evt.ShiftDown();
|
||||
#else
|
||||
bool ctrl_down = evt.CmdDown();
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (already_selected && shift_down)
|
||||
m_selection.remove(volume_idx);
|
||||
else {
|
||||
m_selection.add(volume_idx, !shift_down, true);
|
||||
#else
|
||||
if (already_selected && ctrl_down)
|
||||
m_selection.remove(volume_idx);
|
||||
else {
|
||||
m_selection.add(volume_idx, !ctrl_down, true);
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
m_mouse.drag.move_requires_threshold = !already_selected;
|
||||
if (already_selected)
|
||||
m_mouse.set_move_start_threshold_position_2D_as_invalid();
|
||||
@ -3495,11 +3482,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (!m_hover_volume_idxs.empty() && !m_rectangle_selection.is_dragging()) {
|
||||
#else
|
||||
if (!m_hover_volume_idxs.empty()) {
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) {
|
||||
// Only accept the initial position, if it is inside the volume bounding box.
|
||||
const int volume_idx = get_first_hover_volume_idx();
|
||||
@ -3576,13 +3559,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
else if (evt.Dragging() && evt.LeftIsDown() && m_picking_enabled && m_rectangle_selection.is_dragging()) {
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
// keeps the mouse position updated while dragging the selection rectangle
|
||||
m_mouse.position = pos.cast<double>();
|
||||
m_rectangle_selection.dragging(m_mouse.position);
|
||||
#else
|
||||
m_rectangle_selection.dragging(pos.cast<double>());
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
m_dirty = true;
|
||||
}
|
||||
else if (evt.Dragging()) {
|
||||
@ -3645,6 +3624,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_mouse.position = pos.cast<double>();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (m_layers_editing.state != LayersEditing::Unknown) {
|
||||
m_layers_editing.state = LayersEditing::Unknown;
|
||||
_stop_timer();
|
||||
@ -3669,7 +3652,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
deselect_all();
|
||||
}
|
||||
else if (evt.RightUp()) {
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
m_mouse.position = pos.cast<double>();
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
// forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
|
||||
// the context menu is already shown
|
||||
render();
|
||||
@ -4626,7 +4611,12 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
||||
Camera camera;
|
||||
camera.set_type(camera_type);
|
||||
camera.set_scene_box(scene_bounding_box());
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
camera.set_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||
camera.apply_viewport();
|
||||
#else
|
||||
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
camera.zoom_to_box(volumes_box);
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -4928,7 +4918,11 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||
|
||||
// restore the default framebuffer size to avoid flickering on the 3D scene
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
wxGetApp().plater()->get_camera().apply_viewport();
|
||||
#else
|
||||
wxGetApp().plater()->get_camera().apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height());
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_init_toolbars()
|
||||
@ -5392,6 +5386,118 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLCanvas3D::_picking_pass()
|
||||
{
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX) || m_gizmos.is_dragging()) {
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
|
||||
imgui.text("Picking disabled");
|
||||
imgui.end();
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
m_hover_volume_idxs.clear();
|
||||
|
||||
const ClippingPlane clipping_plane = m_gizmos.get_clipping_plane().inverted_normal();
|
||||
const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(m_mouse.position, wxGetApp().plater()->get_camera(), &clipping_plane);
|
||||
if (hit.is_valid()) {
|
||||
switch (hit.type)
|
||||
{
|
||||
case SceneRaycaster::EType::Volume:
|
||||
{
|
||||
if (0 <= hit.raycaster_id && hit.raycaster_id < (int)m_volumes.volumes.size()) {
|
||||
const GLVolume* volume = m_volumes.volumes[hit.raycaster_id];
|
||||
if (volume->is_active && !volume->disabled && (volume->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) {
|
||||
// do not add the volume id if any gizmo is active and CTRL is pressed
|
||||
if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined || !wxGetKeyState(WXK_CONTROL)) {
|
||||
m_hover_volume_idxs.emplace_back(hit.raycaster_id);
|
||||
m_gizmos.set_hover_id(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
|
||||
break;
|
||||
}
|
||||
case SceneRaycaster::EType::Gizmo:
|
||||
{
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
bool inside = 0 <= m_mouse.position.x() && m_mouse.position.x() < cnv_size.get_width() &&
|
||||
0 <= m_mouse.position.y() && m_mouse.position.y() < cnv_size.get_height();
|
||||
m_gizmos.set_hover_id(inside ? hit.raycaster_id : -1);
|
||||
break;
|
||||
}
|
||||
case SceneRaycaster::EType::Bed:
|
||||
{
|
||||
m_gizmos.set_hover_id(-1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_gizmos.set_hover_id(-1);
|
||||
|
||||
_update_volumes_hover_state();
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
|
||||
std::string object_type = "None";
|
||||
switch (hit.type)
|
||||
{
|
||||
case SceneRaycaster::EType::Bed: { object_type = "Bed"; break; }
|
||||
case SceneRaycaster::EType::Gizmo: { object_type = "Gizmo element"; break; }
|
||||
case SceneRaycaster::EType::Volume:
|
||||
{
|
||||
if (m_volumes.volumes[hit.raycaster_id]->is_wipe_tower)
|
||||
object_type = "Volume (Wipe tower)";
|
||||
else if (m_volumes.volumes[hit.raycaster_id]->volume_idx() == -int(slaposPad))
|
||||
object_type = "Volume (SLA pad)";
|
||||
else if (m_volumes.volumes[hit.raycaster_id]->volume_idx() == -int(slaposSupportTree))
|
||||
object_type = "Volume (SLA supports)";
|
||||
else if (m_volumes.volumes[hit.raycaster_id]->is_modifier)
|
||||
object_type = "Volume (Modifier)";
|
||||
else
|
||||
object_type = "Volume (Part)";
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
char buf[1024];
|
||||
if (hit.type != SceneRaycaster::EType::None) {
|
||||
sprintf(buf, "Object ID: %d", hit.raycaster_id);
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Type: %s", object_type.c_str());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Position: %.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Normal: %.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
|
||||
imgui.text(std::string(buf));
|
||||
}
|
||||
else
|
||||
imgui.text("NO HIT");
|
||||
|
||||
ImGui::Separator();
|
||||
imgui.text("Registered for picking:");
|
||||
sprintf(buf, "Beds: %d", (int)m_scene_raycaster.beds_count());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Volumes: %d", (int)m_scene_raycaster.volumes_count());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Gizmo elements: %d", (int)m_scene_raycaster.gizmos_count());
|
||||
imgui.text(std::string(buf));
|
||||
imgui.end();
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
#else
|
||||
void GLCanvas3D::_picking_pass()
|
||||
{
|
||||
if (m_picking_enabled && !m_mouse.dragging && m_mouse.position != Vec2d(DBL_MAX, DBL_MAX)) {
|
||||
@ -5466,6 +5572,7 @@ void GLCanvas3D::_picking_pass()
|
||||
_update_volumes_hover_state();
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
{
|
||||
@ -5474,6 +5581,58 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
std::set<int> idxs;
|
||||
|
||||
if (m_picking_enabled) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const size_t width = std::max<size_t>(m_rectangle_selection.get_width(), 1);
|
||||
const size_t height = std::max<size_t>(m_rectangle_selection.get_height(), 1);
|
||||
|
||||
const OpenGLManager::EFramebufferType framebuffers_type = OpenGLManager::get_framebuffers_type();
|
||||
bool use_framebuffer = framebuffers_type != OpenGLManager::EFramebufferType::Unknown;
|
||||
|
||||
GLuint render_fbo = 0;
|
||||
GLuint render_tex = 0;
|
||||
GLuint render_depth = 0;
|
||||
if (use_framebuffer) {
|
||||
// setup a framebuffer which covers only the selection rectangle
|
||||
if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
|
||||
glsafe(::glGenFramebuffers(1, &render_fbo));
|
||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
|
||||
}
|
||||
else {
|
||||
glsafe(::glGenFramebuffersEXT(1, &render_fbo));
|
||||
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo));
|
||||
}
|
||||
glsafe(::glGenTextures(1, &render_tex));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
|
||||
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
|
||||
glsafe(::glGenRenderbuffers(1, &render_depth));
|
||||
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
|
||||
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height));
|
||||
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
|
||||
}
|
||||
else {
|
||||
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0));
|
||||
glsafe(::glGenRenderbuffersEXT(1, &render_depth));
|
||||
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth));
|
||||
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height));
|
||||
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth));
|
||||
}
|
||||
const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||
glsafe(::glDrawBuffers(1, drawBufs));
|
||||
if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
|
||||
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
use_framebuffer = false;
|
||||
}
|
||||
else {
|
||||
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
use_framebuffer = false;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (m_multisample_allowed)
|
||||
// This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
|
||||
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||
@ -5483,10 +5642,49 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const Camera& main_camera = wxGetApp().plater()->get_camera();
|
||||
Camera framebuffer_camera;
|
||||
const Camera* camera = &main_camera;
|
||||
if (use_framebuffer) {
|
||||
// setup a camera which covers only the selection rectangle
|
||||
const std::array<int, 4>& viewport = camera->get_viewport();
|
||||
const double near_left = camera->get_near_left();
|
||||
const double near_bottom = camera->get_near_bottom();
|
||||
const double near_width = camera->get_near_width();
|
||||
const double near_height = camera->get_near_height();
|
||||
|
||||
const double ratio_x = near_width / double(viewport[2]);
|
||||
const double ratio_y = near_height / double(viewport[3]);
|
||||
|
||||
const double rect_near_left = near_left + double(m_rectangle_selection.get_left()) * ratio_x;
|
||||
const double rect_near_bottom = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_bottom())) * ratio_y;
|
||||
double rect_near_right = near_left + double(m_rectangle_selection.get_right()) * ratio_x;
|
||||
double rect_near_top = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_top())) * ratio_y;
|
||||
|
||||
if (rect_near_left == rect_near_right)
|
||||
rect_near_right = rect_near_left + ratio_x;
|
||||
if (rect_near_bottom == rect_near_top)
|
||||
rect_near_top = rect_near_bottom + ratio_y;
|
||||
|
||||
framebuffer_camera.look_at(camera->get_position(), camera->get_target(), camera->get_dir_up());
|
||||
framebuffer_camera.apply_projection(rect_near_left, rect_near_right, rect_near_bottom, rect_near_top, camera->get_near_z(), camera->get_far_z());
|
||||
framebuffer_camera.set_viewport(0, 0, width, height);
|
||||
framebuffer_camera.apply_viewport();
|
||||
camera = &framebuffer_camera;
|
||||
}
|
||||
|
||||
_render_volumes_for_picking(*camera);
|
||||
#else
|
||||
_render_volumes_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
_render_bed_for_picking(camera->get_view_matrix(), camera->get_projection_matrix(), !camera->is_looking_downward());
|
||||
#else
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
_render_bed_for_picking(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward());
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward());
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -5494,6 +5692,12 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
if (m_multisample_allowed)
|
||||
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const size_t px_count = width * height;
|
||||
|
||||
const size_t left = use_framebuffer ? 0 : (size_t)m_rectangle_selection.get_left();
|
||||
const size_t top = use_framebuffer ? 0 : (size_t)get_canvas_size().get_height() - (size_t)m_rectangle_selection.get_top();
|
||||
#else
|
||||
int width = std::max((int)m_rectangle_selection.get_width(), 1);
|
||||
int height = std::max((int)m_rectangle_selection.get_height(), 1);
|
||||
int px_count = width * height;
|
||||
@ -5501,6 +5705,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
int left = (int)m_rectangle_selection.get_left();
|
||||
int top = get_canvas_size().get_height() - (int)m_rectangle_selection.get_top();
|
||||
if (left >= 0 && top >= 0) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#define USE_PARALLEL 1
|
||||
#if USE_PARALLEL
|
||||
struct Pixel
|
||||
@ -5542,7 +5747,30 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
||||
idxs.insert(volume_id);
|
||||
}
|
||||
#endif // USE_PARALLEL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (camera != &main_camera)
|
||||
main_camera.apply_viewport();
|
||||
|
||||
if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
|
||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
if (render_depth != 0)
|
||||
glsafe(::glDeleteRenderbuffers(1, &render_depth));
|
||||
if (render_fbo != 0)
|
||||
glsafe(::glDeleteFramebuffers(1, &render_fbo));
|
||||
}
|
||||
else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) {
|
||||
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
if (render_depth != 0)
|
||||
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
|
||||
if (render_fbo != 0)
|
||||
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
|
||||
}
|
||||
|
||||
if (render_tex != 0)
|
||||
glsafe(::glDeleteTextures(1, &render_tex));
|
||||
#else
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
m_hover_volume_idxs.assign(idxs.begin(), idxs.end());
|
||||
@ -5945,7 +6173,11 @@ void GLCanvas3D::_render_overlays()
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLCanvas3D::_render_volumes_for_picking(const Camera& camera) const
|
||||
#else
|
||||
void GLCanvas3D::_render_volumes_for_picking() const
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat_clip");
|
||||
@ -5961,7 +6193,11 @@ void GLCanvas3D::_render_volumes_for_picking() const
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
#else
|
||||
const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
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);
|
||||
for (const GLVolumeWithIdAndZ& volume : to_render)
|
||||
@ -5973,8 +6209,12 @@ void GLCanvas3D::_render_volumes_for_picking() const
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
volume.first->model.set_color(picking_decode(id));
|
||||
shader->start_using();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
shader->set_uniform("view_model_matrix", view_matrix * volume.first->world_matrix());
|
||||
#else
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * volume.first->world_matrix());
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
shader->set_uniform("volume_world_matrix", volume.first->world_matrix());
|
||||
shader->set_uniform("z_range", m_volumes.get_z_range());
|
||||
@ -6447,10 +6687,6 @@ void GLCanvas3D::_update_volumes_hover_state()
|
||||
return;
|
||||
}
|
||||
|
||||
#if !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
bool selection_modifiers_only = m_selection.is_empty() || m_selection.is_any_modifier();
|
||||
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
bool hover_modifiers_only = true;
|
||||
for (int i : m_hover_volume_idxs) {
|
||||
if (!m_volumes.volumes[i]->is_modifier) {
|
||||
@ -6478,14 +6714,8 @@ void GLCanvas3D::_update_volumes_hover_state()
|
||||
if (volume.hover != GLVolume::HS_None)
|
||||
continue;
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
bool deselect = volume.selected && ((shift_pressed && m_rectangle_selection.is_empty()) || (alt_pressed && !m_rectangle_selection.is_empty()));
|
||||
bool select = !volume.selected && (m_rectangle_selection.is_empty() || (shift_pressed && !m_rectangle_selection.is_empty()));
|
||||
#else
|
||||
bool deselect = volume.selected && ((ctrl_pressed && !shift_pressed) || alt_pressed);
|
||||
// (volume->is_modifier && !selection_modifiers_only && !is_ctrl_pressed) -> allows hovering on selected modifiers belonging to selection of type Instance
|
||||
bool select = (!volume.selected || (volume.is_modifier && !selection_modifiers_only && !ctrl_pressed)) && !alt_pressed;
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
if (select || deselect) {
|
||||
bool as_volume =
|
||||
@ -7420,42 +7650,38 @@ void GLCanvas3D::_update_selection_from_hover()
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (!m_rectangle_selection.is_empty()) {
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (state == GLSelectionRectangle::EState::Select) {
|
||||
bool contains_all = true;
|
||||
for (int i : m_hover_volume_idxs) {
|
||||
if (!m_selection.contains_volume((unsigned int)i)) {
|
||||
contains_all = false;
|
||||
break;
|
||||
if (state == GLSelectionRectangle::EState::Select) {
|
||||
bool contains_all = true;
|
||||
for (int i : m_hover_volume_idxs) {
|
||||
if (!m_selection.contains_volume((unsigned int)i)) {
|
||||
contains_all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the selection is going to be modified (Add)
|
||||
if (!contains_all) {
|
||||
wxGetApp().plater()->take_snapshot(_L("Selection-Add from rectangle"), UndoRedo::SnapshotType::Selection);
|
||||
selection_changed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool contains_any = false;
|
||||
for (int i : m_hover_volume_idxs) {
|
||||
if (m_selection.contains_volume((unsigned int)i)) {
|
||||
contains_any = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the selection is going to be modified (Add)
|
||||
if (!contains_all) {
|
||||
wxGetApp().plater()->take_snapshot(_L("Selection-Add from rectangle"), UndoRedo::SnapshotType::Selection);
|
||||
selection_changed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool contains_any = false;
|
||||
for (int i : m_hover_volume_idxs) {
|
||||
if (m_selection.contains_volume((unsigned int)i)) {
|
||||
contains_any = true;
|
||||
break;
|
||||
// the selection is going to be modified (Remove)
|
||||
if (contains_any) {
|
||||
wxGetApp().plater()->take_snapshot(_L("Selection-Remove from rectangle"), UndoRedo::SnapshotType::Selection);
|
||||
selection_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// the selection is going to be modified (Remove)
|
||||
if (contains_any) {
|
||||
wxGetApp().plater()->take_snapshot(_L("Selection-Remove from rectangle"), UndoRedo::SnapshotType::Selection);
|
||||
selection_changed = true;
|
||||
}
|
||||
}
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
}
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
if (!selection_changed)
|
||||
return;
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GCodeViewer.hpp"
|
||||
#include "Camera.hpp"
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include "SceneRaycaster.hpp"
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
|
||||
@ -479,6 +482,9 @@ public:
|
||||
private:
|
||||
wxGLCanvas* m_canvas;
|
||||
wxGLContext* m_context;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
SceneRaycaster m_scene_raycaster;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
Bed3D &m_bed;
|
||||
#if ENABLE_RETINA_GL
|
||||
std::unique_ptr<RetinaHelper> m_retina_helper;
|
||||
@ -533,10 +539,6 @@ private:
|
||||
|
||||
bool m_reload_delayed;
|
||||
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
bool m_show_picking_texture;
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
|
||||
RenderStats m_render_stats;
|
||||
|
||||
int m_imgui_undo_redo_hovered_pos{ -1 };
|
||||
@ -656,6 +658,26 @@ public:
|
||||
bool init();
|
||||
void post_event(wxEvent &&event);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::shared_ptr<SceneRaycasterItem> add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo) {
|
||||
return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo);
|
||||
}
|
||||
void remove_raycasters_for_picking(SceneRaycaster::EType type, int id) {
|
||||
m_scene_raycaster.remove_raycasters(type, id);
|
||||
}
|
||||
void remove_raycasters_for_picking(SceneRaycaster::EType type) {
|
||||
m_scene_raycaster.remove_raycasters(type);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters_for_picking(SceneRaycaster::EType type) {
|
||||
return m_scene_raycaster.get_raycasters(type);
|
||||
}
|
||||
|
||||
void set_raycaster_gizmos_on_top(bool value) {
|
||||
m_scene_raycaster.set_gizmos_on_top(value);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void set_as_dirty();
|
||||
void requires_check_outside_state() { m_requires_check_outside_state = true; }
|
||||
|
||||
@ -975,7 +997,11 @@ private:
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
void _check_and_update_toolbar_icon_scale();
|
||||
void _render_overlays();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void _render_volumes_for_picking(const Camera& camera) const;
|
||||
#else
|
||||
void _render_volumes_for_picking() const;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void _render_current_gizmo() const;
|
||||
void _render_gizmos_overlay();
|
||||
void _render_main_toolbar();
|
||||
|
@ -29,19 +29,25 @@ namespace GUI {
|
||||
m_end_corner = mouse_position;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::vector<unsigned int> GLSelectionRectangle::contains(const std::vector<Vec3d>& points) const
|
||||
#else
|
||||
std::vector<unsigned int> GLSelectionRectangle::stop_dragging(const GLCanvas3D& canvas, const std::vector<Vec3d>& points)
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
std::vector<unsigned int> out;
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
if (!is_dragging())
|
||||
return out;
|
||||
|
||||
m_state = EState::Off;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||
Matrix4d projection= camera.get_projection_matrix().matrix();
|
||||
Vec4i viewport(camera.get_viewport().data());
|
||||
const Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||
const Matrix4d projection= camera.get_projection_matrix().matrix();
|
||||
const Vec4i viewport(camera.get_viewport().data());
|
||||
|
||||
// Convert our std::vector to Eigen dynamic matrix.
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign> pts(points.size(), 3);
|
||||
@ -53,11 +59,15 @@ namespace GUI {
|
||||
igl::project(pts, modelview, projection, viewport, projections);
|
||||
|
||||
// bounding box created from the rectangle corners - will take care of order of the corners
|
||||
BoundingBox rectangle(Points{ Point(m_start_corner.cast<coord_t>()), Point(m_end_corner.cast<coord_t>()) });
|
||||
const BoundingBox rectangle(Points{ Point(m_start_corner.cast<coord_t>()), Point(m_end_corner.cast<coord_t>()) });
|
||||
|
||||
// Iterate over all points and determine whether they're in the rectangle.
|
||||
for (int i = 0; i<projections.rows(); ++i)
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (rectangle.contains(Point(projections(i, 0), viewport[3] - projections(i, 1))))
|
||||
#else
|
||||
if (rectangle.contains(Point(projections(i, 0), canvas.get_canvas_size().get_height() - projections(i, 1))))
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
out.push_back(i);
|
||||
|
||||
return out;
|
||||
|
@ -26,9 +26,15 @@ public:
|
||||
// To be called on mouse move.
|
||||
void dragging(const Vec2d& mouse_position);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// Given a vector of points in world coordinates, the function returns indices of those
|
||||
// that are in the rectangle.
|
||||
std::vector<unsigned int> contains(const std::vector<Vec3d>& points) const;
|
||||
#else
|
||||
// Given a vector of points in world coordinates, the function returns indices of those
|
||||
// that are in the rectangle. It then disables the rectangle.
|
||||
std::vector<unsigned int> stop_dragging(const GLCanvas3D& canvas, const std::vector<Vec3d>& points);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// Disables the rectangle.
|
||||
void stop_dragging();
|
||||
@ -36,9 +42,7 @@ public:
|
||||
void render(const GLCanvas3D& canvas);
|
||||
|
||||
bool is_dragging() const { return m_state != EState::Off; }
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
bool is_empty() const { return m_state == EState::Off || m_start_corner.isApprox(m_end_corner); }
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
||||
EState get_state() const { return m_state; }
|
||||
|
||||
|
@ -63,7 +63,7 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig
|
||||
m_canvas->set_context(wxGetApp().init_glcontext(*m_canvas_widget));
|
||||
|
||||
m_canvas->allow_multisample(OpenGLManager::can_multisample());
|
||||
// XXX: If have OpenGL
|
||||
|
||||
m_canvas->enable_picking(true);
|
||||
m_canvas->enable_moving(true);
|
||||
// XXX: more config from 3D.pm
|
||||
|
@ -18,19 +18,30 @@ const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
|
||||
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
|
||||
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel GLGizmoBase::Grabber::s_cube;
|
||||
PickingModel GLGizmoBase::Grabber::s_cone;
|
||||
#else
|
||||
GLModel GLGizmoBase::Grabber::s_cube;
|
||||
GLModel GLGizmoBase::Grabber::s_cone;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
GLGizmoBase::Grabber::~Grabber()
|
||||
{
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (s_cube.model.is_initialized())
|
||||
s_cube.model.reset();
|
||||
|
||||
if (s_cone.model.is_initialized())
|
||||
s_cone.model.reset();
|
||||
#else
|
||||
if (s_cube.is_initialized())
|
||||
s_cube.reset();
|
||||
|
||||
if (s_cone.is_initialized())
|
||||
s_cone.reset();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
float GLGizmoBase::Grabber::get_half_size(float size) const
|
||||
{
|
||||
@ -42,7 +53,26 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
|
||||
return get_half_size(size) * DraggingScaleFactor;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoBase::Grabber::register_raycasters_for_picking(int id)
|
||||
{
|
||||
picking_id = id;
|
||||
// registration will happen on next call to render()
|
||||
}
|
||||
|
||||
void GLGizmoBase::Grabber::unregister_raycasters_for_picking()
|
||||
{
|
||||
wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, picking_id);
|
||||
picking_id = -1;
|
||||
raycasters = { nullptr };
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color)
|
||||
#else
|
||||
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking)
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
@ -50,106 +80,148 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
|
||||
return;
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
if (!s_cube.is_initialized()) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (!s_cube.model.is_initialized()) {
|
||||
#else
|
||||
if (!m_cube.is_initialized()) {
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
if (!s_cube.is_initialized()) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
// This cannot be done in constructor, OpenGL is not yet
|
||||
// initialized at that point (on Linux at least).
|
||||
indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
|
||||
its_translate(its, -0.5f * Vec3f::Ones());
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
s_cube.model.init_from(its);
|
||||
s_cube.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
#else
|
||||
s_cube.init_from(its);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
m_cube.init_from(its);
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#else
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
s_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
|
||||
#else
|
||||
m_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (!s_cone.model.is_initialized()) {
|
||||
indexed_triangle_set its = its_make_cone(0.375, 1.5, double(PI) / 18.0);
|
||||
s_cone.model.init_from(its);
|
||||
s_cone.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
}
|
||||
#else
|
||||
if (!s_cone.is_initialized())
|
||||
s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0));
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
|
||||
#else
|
||||
const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size));
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
s_cube.model.set_color(render_color);
|
||||
s_cone.model.set_color(render_color);
|
||||
#else
|
||||
s_cube.set_color(render_color);
|
||||
s_cone.set_color(render_color);
|
||||
#else
|
||||
m_cube.set_color(render_color);
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
|
||||
const Matrix3d view_matrix_no_offset = view_matrix.matrix().block(0, 0, 3, 3);
|
||||
std::vector<Transform3d> elements_matrices(GRABBER_ELEMENTS_MAX_COUNT, Transform3d::Identity());
|
||||
elements_matrices[0] = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
|
||||
Transform3d view_model_matrix = view_matrix * elements_matrices[0];
|
||||
#else
|
||||
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones());
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
|
||||
const Transform3d view_model_matrix = view_matrix * model_matrix;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
Matrix3d view_normal_matrix = view_matrix_no_offset * elements_matrices[0].matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
#else
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
#else
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
s_cube.set_color(-1, render_color);
|
||||
s_cone.set_color(-1, render_color);
|
||||
#else
|
||||
m_cube.set_color(-1, render_color);
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(center.x(), center.y(), center.z()));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
|
||||
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size));
|
||||
#else
|
||||
glsafe(::glScaled(fullsize, fullsize, fullsize));
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
s_cube.model.render();
|
||||
|
||||
auto render_extension = [&view_matrix, &view_matrix_no_offset, shader](const Transform3d& matrix) {
|
||||
const Transform3d view_model_matrix = view_matrix * matrix;
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix_no_offset * matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
s_cone.model.render();
|
||||
};
|
||||
#else
|
||||
s_cube.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[1] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0));
|
||||
render_extension(elements_matrices[1]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0)));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[2] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0));
|
||||
render_extension(elements_matrices[2]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0)));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[3] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0));
|
||||
render_extension(elements_matrices[3]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0)));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[4] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0));
|
||||
render_extension(elements_matrices[4]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0)));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[5] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitZ());
|
||||
render_extension(elements_matrices[5]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitZ()));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) {
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
elements_matrices[6] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0));
|
||||
render_extension(elements_matrices[6]);
|
||||
#else
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0)));
|
||||
s_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
#else
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
|
||||
@ -194,26 +266,41 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#else
|
||||
m_cube.render();
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (raycasters[0] == nullptr) {
|
||||
GLCanvas3D& canvas = *wxGetApp().plater()->canvas3D();
|
||||
raycasters[0] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cube.mesh_raycaster, elements_matrices[0]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0)
|
||||
raycasters[1] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[1]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0)
|
||||
raycasters[2] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[2]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0)
|
||||
raycasters[3] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[3]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0)
|
||||
raycasters[4] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[4]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0)
|
||||
raycasters[5] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[5]);
|
||||
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0)
|
||||
raycasters[6] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[6]);
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < GRABBER_ELEMENTS_MAX_COUNT; ++i) {
|
||||
if (raycasters[i] != nullptr)
|
||||
raycasters[i]->set_transform(elements_matrices[i]);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: m_parent(parent)
|
||||
, m_group_id(-1)
|
||||
, m_state(Off)
|
||||
, m_shortcut_key(0)
|
||||
, m_icon_filename(icon_filename)
|
||||
, m_sprite_id(sprite_id)
|
||||
, m_hover_id(-1)
|
||||
, m_dragging(false)
|
||||
, m_imgui(wxGetApp().imgui())
|
||||
, m_first_input_window_render(true)
|
||||
, m_dirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -237,6 +324,21 @@ bool GLGizmoBase::update_items_state()
|
||||
return res;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoBase::register_grabbers_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_grabbers.size(); ++i) {
|
||||
m_grabbers[i].register_raycasters_for_picking((m_group_id >= 0) ? m_group_id : i);
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoBase::unregister_grabbers_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_grabbers.size(); ++i) {
|
||||
m_grabbers[i].unregister_raycasters_for_picking();
|
||||
}
|
||||
}
|
||||
#else
|
||||
ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
|
||||
{
|
||||
id = BASE_ID - id;
|
||||
@ -245,6 +347,7 @@ ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
|
||||
|
||||
return picking_decode(id);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
|
||||
{
|
||||
@ -265,6 +368,7 @@ void GLGizmoBase::render_grabbers(float size) const
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -285,6 +389,7 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
|
||||
}
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
// help function to process grabbers
|
||||
// call start_dragging, stop_dragging, on_dragging
|
||||
|
@ -6,6 +6,10 @@
|
||||
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
#include "slic3r/GUI/SceneRaycaster.hpp"
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#include <cereal/archives/binary.hpp>
|
||||
|
||||
@ -37,8 +41,8 @@ public:
|
||||
// Starting value for ids to avoid clashing with ids used by GLVolumes
|
||||
// (254 is choosen to leave some space for forward compatibility)
|
||||
static const unsigned int BASE_ID = 255 * 255 * 254;
|
||||
static const unsigned int GRABBER_ELEMENTS_MAX_COUNT = 7;
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
enum class EGrabberExtension
|
||||
{
|
||||
None = 0,
|
||||
@ -49,7 +53,6 @@ public:
|
||||
PosZ = 1 << 4,
|
||||
NegZ = 1 << 5,
|
||||
};
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
protected:
|
||||
struct Grabber
|
||||
@ -66,30 +69,45 @@ protected:
|
||||
Transform3d matrix{ Transform3d::Identity() };
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
ColorRGBA color{ ColorRGBA::WHITE() };
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
EGrabberExtension extensions{ EGrabberExtension::None };
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// the picking id shared by all the elements
|
||||
int picking_id{ -1 };
|
||||
std::array<std::shared_ptr<SceneRaycasterItem>, GRABBER_ELEMENTS_MAX_COUNT> raycasters = { nullptr };
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
Grabber() = default;
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
~Grabber();
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void render(bool hover, float size) { render(size, hover ? complementary(color) : color); }
|
||||
#else
|
||||
void render(bool hover, float size) { render(size, hover ? complementary(color) : color, false); }
|
||||
void render_for_picking(float size) { render(size, color, true); }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
float get_half_size(float size) const;
|
||||
float get_dragging_half_size(float size) const;
|
||||
|
||||
private:
|
||||
void render(float size, const ColorRGBA& render_color, bool picking);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void register_raycasters_for_picking(int id);
|
||||
void unregister_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
private:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void render(float size, const ColorRGBA& render_color);
|
||||
#else
|
||||
void render(float size, const ColorRGBA& render_color, bool picking);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
static PickingModel s_cube;
|
||||
static PickingModel s_cone;
|
||||
#else
|
||||
static GLModel s_cube;
|
||||
static GLModel s_cone;
|
||||
#else
|
||||
GLModel m_cube;
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
};
|
||||
|
||||
public:
|
||||
@ -112,17 +130,19 @@ public:
|
||||
|
||||
protected:
|
||||
GLCanvas3D& m_parent;
|
||||
int m_group_id; // TODO: remove only for rotate
|
||||
EState m_state;
|
||||
int m_shortcut_key;
|
||||
|
||||
int m_group_id{ -1 }; // TODO: remove only for rotate
|
||||
EState m_state{ Off };
|
||||
int m_shortcut_key{ 0 };
|
||||
std::string m_icon_filename;
|
||||
unsigned int m_sprite_id;
|
||||
int m_hover_id;
|
||||
bool m_dragging;
|
||||
int m_hover_id{ -1 };
|
||||
bool m_dragging{ false };
|
||||
mutable std::vector<Grabber> m_grabbers;
|
||||
ImGuiWrapper* m_imgui;
|
||||
bool m_first_input_window_render;
|
||||
CommonGizmosDataPool* m_c;
|
||||
bool m_first_input_window_render{ true };
|
||||
CommonGizmosDataPool* m_c{ nullptr };
|
||||
|
||||
public:
|
||||
GLGizmoBase(GLCanvas3D& parent,
|
||||
const std::string& icon_filename,
|
||||
@ -163,7 +183,9 @@ public:
|
||||
bool update_items_state();
|
||||
|
||||
void render() { on_render(); }
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void render_for_picking() { on_render_for_picking(); }
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
void render_input_window(float x, float y, float bottom_limit);
|
||||
|
||||
/// <summary>
|
||||
@ -184,6 +206,12 @@ public:
|
||||
/// <param name="mouse_event">Keep information about mouse click</param>
|
||||
/// <returns>Return True when use the information and don't want to propagate it otherwise False.</returns>
|
||||
virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; }
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void register_raycasters_for_picking() { register_grabbers_for_picking(); on_register_raycasters_for_picking(); }
|
||||
void unregister_raycasters_for_picking() { unregister_grabbers_for_picking(); on_unregister_raycasters_for_picking(); }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
protected:
|
||||
virtual bool on_init() = 0;
|
||||
virtual void on_load(cereal::BinaryInputArchive& ar) {}
|
||||
@ -203,16 +231,27 @@ protected:
|
||||
virtual void on_dragging(const UpdateData& data) {}
|
||||
|
||||
virtual void on_render() = 0;
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
virtual void on_render_for_picking() = 0;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit) {}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void register_grabbers_for_picking();
|
||||
void unregister_grabbers_for_picking();
|
||||
virtual void on_register_raycasters_for_picking() {}
|
||||
virtual void on_unregister_raycasters_for_picking() {}
|
||||
#else
|
||||
// Returns the picking color for the given id, based on the BASE_ID constant
|
||||
// No check is made for clashing with other picking color (i.e. GLVolumes)
|
||||
ColorRGBA picking_color_component(unsigned int id) const;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void render_grabbers(const BoundingBoxf3& box) const;
|
||||
void render_grabbers(float size) const;
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
std::string format(float value, unsigned int decimals) const;
|
||||
|
||||
@ -235,7 +274,7 @@ protected:
|
||||
private:
|
||||
// Flag for dirty visible state of Gizmo
|
||||
// When True then need new rendering
|
||||
bool m_dirty;
|
||||
bool m_dirty{ false };
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
@ -269,11 +269,24 @@ void GLGizmoCut::on_render()
|
||||
#endif // !ENABLE_GL_CORE_PROFILE
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoCut::on_register_raycasters_for_picking()
|
||||
{
|
||||
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
|
||||
m_parent.set_raycaster_gizmos_on_top(true);
|
||||
}
|
||||
|
||||
void GLGizmoCut::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.set_raycaster_gizmos_on_top(false);
|
||||
}
|
||||
#else
|
||||
void GLGizmoCut::on_render_for_picking()
|
||||
{
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
|
@ -68,7 +68,12 @@ protected:
|
||||
virtual void on_start_dragging() override;
|
||||
virtual void on_dragging(const UpdateData& data) override;
|
||||
virtual void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
virtual void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
private:
|
||||
|
@ -133,8 +133,13 @@ void GLGizmoFlatten::on_render()
|
||||
update_planes();
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_planes[i].vbo.model.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR);
|
||||
m_planes[i].vbo.model.render();
|
||||
#else
|
||||
m_planes[i].vbo.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR);
|
||||
m_planes[i].vbo.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data()));
|
||||
if (m_planes[i].vbo.has_VBOs())
|
||||
@ -154,6 +159,29 @@ void GLGizmoFlatten::on_render()
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoFlatten::on_register_raycasters_for_picking()
|
||||
{
|
||||
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
|
||||
m_parent.set_raycaster_gizmos_on_top(true);
|
||||
|
||||
if (!m_planes.empty()) {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Transform3d matrix = Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) *
|
||||
selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
||||
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_planes[i].vbo.mesh_raycaster, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoFlatten::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
|
||||
m_parent.set_raycaster_gizmos_on_top(false);
|
||||
}
|
||||
#else
|
||||
void GLGizmoFlatten::on_render_for_picking()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
@ -204,12 +232,16 @@ void GLGizmoFlatten::on_render_for_picking()
|
||||
shader->stop_using();
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
|
||||
{
|
||||
if (model_object != m_old_model_object) {
|
||||
m_planes.clear();
|
||||
m_planes_valid = false;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,6 +258,9 @@ void GLGizmoFlatten::update_planes()
|
||||
}
|
||||
ch = ch.convex_hull_3d();
|
||||
m_planes.clear();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Transform3d inst_matrix = mo->instances.front()->get_matrix_no_offset();
|
||||
#else
|
||||
@ -422,6 +457,19 @@ void GLGizmoFlatten::update_planes()
|
||||
// the vertices in order, so triangulation is trivial.
|
||||
for (auto& plane : m_planes) {
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(plane.vertices.size());
|
||||
its.indices.reserve(plane.vertices.size() / 3);
|
||||
for (size_t i = 0; i < plane.vertices.size(); ++i) {
|
||||
its.vertices.emplace_back((Vec3f)plane.vertices[i].cast<float>());
|
||||
}
|
||||
for (size_t i = 1; i < plane.vertices.size() - 1; ++i) {
|
||||
its.indices.emplace_back(0, i, i + 1); // triangle fan
|
||||
}
|
||||
plane.vbo.model.init_from(its);
|
||||
plane.vbo.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
#else
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3 };
|
||||
init_data.reserve_vertices(plane.vertices.size());
|
||||
@ -432,6 +480,7 @@ void GLGizmoFlatten::update_planes()
|
||||
init_data.add_index((unsigned int)i);
|
||||
}
|
||||
plane.vbo.init_from(std::move(init_data));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
plane.vbo.reserve(plane.vertices.size());
|
||||
for (const auto& vert : plane.vertices)
|
||||
@ -446,6 +495,9 @@ void GLGizmoFlatten::update_planes()
|
||||
plane.vertices.shrink_to_fit();
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
m_planes_valid = true;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "GLGizmoBase.hpp"
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -26,12 +29,19 @@ private:
|
||||
struct PlaneData {
|
||||
std::vector<Vec3d> vertices; // should be in fact local in update_planes()
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel vbo;
|
||||
#else
|
||||
GLModel vbo;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
GLIndexedVertexArray vbo;
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
Vec3d normal;
|
||||
float area;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
int picking_id{ -1 };
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
};
|
||||
|
||||
// This holds information to decide whether recalculation is necessary:
|
||||
@ -67,7 +77,12 @@ protected:
|
||||
std::string on_get_name() const override;
|
||||
bool on_is_activable() const override;
|
||||
void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void on_set_state() override;
|
||||
CommonGizmosDataID on_get_requirements() const override;
|
||||
};
|
||||
|
@ -55,6 +55,12 @@ void GLGizmoHollow::data_changed()
|
||||
}
|
||||
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
|
||||
m_holes_in_drilled_mesh = mo->sla_drain_holes;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_raycasters.empty())
|
||||
on_register_raycasters_for_picking();
|
||||
else
|
||||
update_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,8 +68,16 @@ void GLGizmoHollow::data_changed()
|
||||
|
||||
void GLGizmoHollow::on_render()
|
||||
{
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (!m_cylinder.model.is_initialized()) {
|
||||
indexed_triangle_set its = its_make_cylinder(1.0, 1.0);
|
||||
m_cylinder.model.init_from(its);
|
||||
m_cylinder.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
}
|
||||
#else
|
||||
if (!m_cylinder.is_initialized())
|
||||
m_cylinder.init_from(its_make_cylinder(1.0, 1.0));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info();
|
||||
@ -80,7 +94,11 @@ void GLGizmoHollow::on_render()
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
if (selection.is_from_single_instance())
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
render_points(selection);
|
||||
#else
|
||||
render_points(selection, false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_selection_rectangle.render(m_parent);
|
||||
m_c->object_clipper()->render_cut();
|
||||
@ -89,22 +107,49 @@ void GLGizmoHollow::on_render()
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoHollow::on_register_raycasters_for_picking()
|
||||
{
|
||||
assert(m_raycasters.empty());
|
||||
set_sla_auxiliary_volumes_picking_state(false);
|
||||
|
||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||
if (info != nullptr && !info->model_object()->sla_drain_holes.empty()) {
|
||||
const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes;
|
||||
for (int i = 0; i < (int)drain_holes.size(); ++i) {
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cylinder.mesh_raycaster, Transform3d::Identity()));
|
||||
}
|
||||
update_raycasters_for_picking_transform();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoHollow::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
|
||||
m_raycasters.clear();
|
||||
set_sla_auxiliary_volumes_picking_state(true);
|
||||
}
|
||||
#else
|
||||
void GLGizmoHollow::on_render_for_picking()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
//#if ENABLE_RENDER_PICKING_PASS
|
||||
// m_z_shift = selection.get_first_volume()->get_sla_shift_z();
|
||||
//#endif
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
render_points(selection, true);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoHollow::render_points(const Selection& selection)
|
||||
#else
|
||||
void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
#else
|
||||
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
@ -118,7 +163,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
const GLVolume* vol = selection.get_first_volume();
|
||||
Geometry::Transformation trafo = vol->get_instance_transformation() * vol->get_volume_transformation();
|
||||
const Transform3d trafo = vol->world_matrix();
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
@ -126,13 +171,9 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
#else
|
||||
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const Transform3d instance_matrix = Geometry::translation_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix();
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
const Transform3d& projection_matrix = camera.get_projection_matrix();
|
||||
|
||||
shader->set_uniform("projection_matrix", projection_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
#else
|
||||
const Transform3d& instance_scaling_matrix_inverse = trafo.get_matrix(true, true, false, true).inverse();
|
||||
const Transform3d& instance_matrix = trafo.get_matrix();
|
||||
@ -150,13 +191,22 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
const sla::DrainHole& drain_hole = drain_holes[i];
|
||||
const bool point_selected = m_selected[i];
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const bool clipped = is_mesh_point_clipped(drain_hole.pos.cast<double>());
|
||||
m_raycasters[i]->set_active(!clipped);
|
||||
if (clipped)
|
||||
continue;
|
||||
#else
|
||||
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
|
||||
continue;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// First decide about the color of the point.
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
if (picking)
|
||||
render_color = picking_color_component(i);
|
||||
else {
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
if (size_t(m_hover_id) == i)
|
||||
render_color = ColorRGBA::CYAN();
|
||||
else if (m_c->hollowed_mesh() &&
|
||||
@ -164,14 +214,20 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
m_c->hollowed_mesh()->get_drainholes()[i].failed) {
|
||||
render_color = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
}
|
||||
else // neither hover nor picking
|
||||
else
|
||||
render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_cylinder.model.set_color(render_color);
|
||||
#else
|
||||
m_cylinder.set_color(render_color);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
// 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;
|
||||
const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
#else
|
||||
const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color);
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
@ -188,8 +244,8 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d model_matrix = instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
const Transform3d model_matrix = trafo * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
@ -198,7 +254,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_cylinder.model.render();
|
||||
#else
|
||||
m_cylinder.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
@ -317,7 +377,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
||||
if (m_selection_empty) {
|
||||
std::pair<Vec3f, Vec3f> pos_and_normal;
|
||||
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add drainage hole")));
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add drainage hole"));
|
||||
|
||||
mo->sla_drain_holes.emplace_back(pos_and_normal.first,
|
||||
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height);
|
||||
@ -325,6 +385,10 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
||||
assert(m_selected.size() == mo->sla_drain_holes.size());
|
||||
m_parent.set_as_dirty();
|
||||
m_wait_for_up_event = true;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -349,7 +413,12 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
||||
|
||||
// Now ask the rectangle which of the points are inside.
|
||||
std::vector<Vec3f> points_inside;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::vector<unsigned int> points_idxs = m_selection_rectangle.contains(points);
|
||||
m_selection_rectangle.stop_dragging();
|
||||
#else
|
||||
std::vector<unsigned int> points_idxs = m_selection_rectangle.stop_dragging(m_parent, points);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
for (size_t idx : points_idxs)
|
||||
points_inside.push_back(points[idx].cast<float>());
|
||||
|
||||
@ -443,6 +512,10 @@ void GLGizmoHollow::delete_selected_points()
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
select_point(NoPoints);
|
||||
}
|
||||
|
||||
@ -518,6 +591,49 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
|
||||
});
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoHollow::set_sla_auxiliary_volumes_picking_state(bool state)
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||
if (raycasters != nullptr) {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList ids = selection.get_volume_idxs();
|
||||
for (unsigned int id : ids) {
|
||||
const GLVolume* v = selection.get_volume(id);
|
||||
if (v->is_sla_pad() || v->is_sla_support()) {
|
||||
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
||||
if (it != raycasters->end())
|
||||
(*it)->set_active(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoHollow::update_raycasters_for_picking_transform()
|
||||
{
|
||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||
if (info != nullptr) {
|
||||
const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes;
|
||||
if (!drain_holes.empty()) {
|
||||
assert(!m_raycasters.empty());
|
||||
|
||||
const GLVolume* vol = m_parent.get_selection().get_first_volume();
|
||||
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_scaling_factor_matrix().inverse();
|
||||
|
||||
for (size_t i = 0; i < drain_holes.size(); ++i) {
|
||||
const sla::DrainHole& drain_hole = drain_holes[i];
|
||||
const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
const Transform3d matrix = vol->world_matrix() * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
m_raycasters[i]->set_transform(matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>>
|
||||
GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
||||
|
@ -28,8 +28,7 @@ private:
|
||||
|
||||
public:
|
||||
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
virtual ~GLGizmoHollow() = default;
|
||||
void data_changed() override;
|
||||
void data_changed() override;
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
void delete_selected_points();
|
||||
bool is_selection_rectangle_dragging() const {
|
||||
@ -43,18 +42,37 @@ public:
|
||||
/// <param name="mouse_event">Keep information about mouse click</param>
|
||||
/// <returns>Return True when use the information otherwise False.</returns>
|
||||
bool on_mouse(const wxMouseEvent &mouse_event) override;
|
||||
private:
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
private:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void render_points(const Selection& selection);
|
||||
#else
|
||||
void render_points(const Selection& selection, bool picking = false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void hollow_mesh(bool postpone_error_messages = false);
|
||||
bool unsaved_changes() const;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void set_sla_auxiliary_volumes_picking_state(bool state);
|
||||
void update_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
ObjectID m_old_mo_id = -1;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel m_cylinder;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_raycasters;
|
||||
#else
|
||||
GLModel m_cylinder;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||
float m_new_hole_height = 6.f;
|
||||
|
@ -61,15 +61,11 @@ bool GLGizmoMove3D::on_init()
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
m_grabbers.push_back(Grabber());
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
m_grabbers.back().extensions = GLGizmoBase::EGrabberExtension::PosZ;
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
}
|
||||
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
m_grabbers[0].angles = { 0.0, 0.5 * double(PI), 0.0 };
|
||||
m_grabbers[1].angles = { -0.5 * double(PI), 0.0, 0.0 };
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_M;
|
||||
|
||||
@ -149,11 +145,6 @@ void GLGizmoMove3D::on_dragging(const UpdateData& data)
|
||||
|
||||
void GLGizmoMove3D::on_render()
|
||||
{
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
if (!m_cone.is_initialized())
|
||||
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
@ -300,24 +291,8 @@ void GLGizmoMove3D::on_render()
|
||||
// draw grabbers
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
render_grabbers(m_bounding_box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if (m_grabbers[i].enabled)
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
render_grabber_extension((Axis)i, base_matrix, m_bounding_box, false);
|
||||
#else
|
||||
render_grabber_extension((Axis)i, m_bounding_box, false);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#else
|
||||
render_grabbers(box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if (m_grabbers[i].enabled)
|
||||
render_grabber_extension((Axis)i, box, false);
|
||||
}
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
else {
|
||||
@ -376,17 +351,6 @@ void GLGizmoMove3D::on_render()
|
||||
m_grabbers[m_hover_id].render(true, mean_size);
|
||||
shader->stop_using();
|
||||
}
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
render_grabber_extension((Axis)m_hover_id, base_matrix, m_bounding_box, false);
|
||||
#else
|
||||
render_grabber_extension((Axis)m_hover_id, m_bounding_box, false);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#else
|
||||
render_grabber_extension((Axis)m_hover_id, box, false);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
@ -396,6 +360,18 @@ void GLGizmoMove3D::on_render()
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoMove3D::on_register_raycasters_for_picking()
|
||||
{
|
||||
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
|
||||
m_parent.set_raycaster_gizmos_on_top(true);
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.set_raycaster_gizmos_on_top(false);
|
||||
}
|
||||
#else
|
||||
void GLGizmoMove3D::on_render_for_picking()
|
||||
{
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
@ -412,29 +388,15 @@ void GLGizmoMove3D::on_render_for_picking()
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
render_grabbers_for_picking(m_bounding_box);
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(X, base_matrix, m_bounding_box, true);
|
||||
render_grabber_extension(Y, base_matrix, m_bounding_box, true);
|
||||
render_grabber_extension(Z, base_matrix, m_bounding_box, true);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#else
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(X, m_bounding_box, true);
|
||||
render_grabber_extension(Y, m_bounding_box, true);
|
||||
render_grabber_extension(Z, m_bounding_box, true);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#else
|
||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||
render_grabbers_for_picking(box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(X, box, true);
|
||||
render_grabber_extension(Y, box, true);
|
||||
render_grabber_extension(Z, box, true);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
||||
{
|
||||
@ -462,70 +424,6 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
||||
return projection;
|
||||
}
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_WORLD_COORDINATE && ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void GLGizmoMove3D::render_grabber_extension(Axis axis, const Transform3d& base_matrix, const BoundingBoxf3& box, bool picking)
|
||||
#else
|
||||
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking)
|
||||
#endif // ENABLE_WORLD_COORDINATE && ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
{
|
||||
const Vec3d box_size = box.size();
|
||||
const float mean_size = float((box_size.x() + box_size.y() + box_size.z()) / 3.0);
|
||||
const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
|
||||
#else
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color);
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
Transform3d model_matrix = Geometry::assemble_transform(m_grabbers[axis].center);
|
||||
if (axis == X)
|
||||
model_matrix = model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
|
||||
else if (axis == Y)
|
||||
model_matrix = model_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX());
|
||||
model_matrix = model_matrix * Geometry::assemble_transform(2.0 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
#else
|
||||
m_cone.set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color);
|
||||
if (!picking) {
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
}
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z()));
|
||||
if (axis == X)
|
||||
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
|
||||
else if (axis == Y)
|
||||
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
|
||||
|
||||
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
|
||||
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
m_cone.render();
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
if (! picking)
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
shader->stop_using();
|
||||
}
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
Transform3d GLGizmoMove3D::local_transform(const Selection& selection) const
|
||||
|
@ -25,9 +25,6 @@ class GLGizmoMove3D : public GLGizmoBase
|
||||
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
||||
Vec3d m_starting_box_bottom_center{ Vec3d::Zero() };
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
GLModel m_cone;
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
struct GrabberConnection
|
||||
{
|
||||
@ -65,7 +62,12 @@ protected:
|
||||
void on_stop_dragging() override;
|
||||
void on_dragging(const UpdateData& data) override;
|
||||
void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
private:
|
||||
double calc_projection(const UpdateData& data) const;
|
||||
@ -77,17 +79,9 @@ private:
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void calc_selection_box_and_center();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_WORLD_COORDINATE && ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void render_grabber_extension(Axis axis, const Transform3d& base_matrix, const BoundingBoxf3& box, bool picking);
|
||||
#else
|
||||
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking);
|
||||
#endif // ENABLE_WORLD_COORDINATE && ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -138,7 +138,10 @@ private:
|
||||
ObjectID m_old_mo_id;
|
||||
size_t m_old_volumes_size = 0;
|
||||
void on_render() override {}
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void on_render_for_picking() override {}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
public:
|
||||
GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
~GLGizmoPainterBase() override;
|
||||
|
@ -94,9 +94,7 @@ void GLGizmoRotate::disable_grabber() { m_grabbers[0].enabled = false; }
|
||||
bool GLGizmoRotate::on_init()
|
||||
{
|
||||
m_grabbers.push_back(Grabber());
|
||||
#if ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
m_grabbers.back().extensions = (GLGizmoBase::EGrabberExtension)(int(GLGizmoBase::EGrabberExtension::PosY) | int(GLGizmoBase::EGrabberExtension::NegY));
|
||||
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -152,11 +150,6 @@ void GLGizmoRotate::on_render()
|
||||
if (!m_grabbers.front().enabled)
|
||||
return;
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
if (!m_cone.is_initialized())
|
||||
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0));
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
@ -249,14 +242,8 @@ void GLGizmoRotate::on_render()
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
render_grabber(m_bounding_box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(m_bounding_box, false);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#else
|
||||
render_grabber(box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(box, false);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -264,6 +251,7 @@ void GLGizmoRotate::on_render()
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoRotate::on_render_for_picking()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
@ -279,21 +267,16 @@ void GLGizmoRotate::on_render_for_picking()
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
render_grabbers_for_picking(m_bounding_box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(m_bounding_box, true);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#else
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
render_grabbers_for_picking(box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
render_grabber_extension(box, true);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||
@ -662,81 +645,6 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box)
|
||||
render_grabbers(box);
|
||||
}
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking)
|
||||
{
|
||||
const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
|
||||
const double size = m_dragging ? double(m_grabbers.front().get_dragging_half_size(mean_size)) : double(m_grabbers.front().get_half_size(mean_size));
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers.front().color) : m_grabbers.front().color);
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
#else
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
m_cone.set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers.front().color) : m_grabbers.front().color);
|
||||
if (!picking) {
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
}
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
const Vec3d& center = m_grabbers.front().center;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
Transform3d model_matrix = m_grabbers.front().matrix * Geometry::assemble_transform(center, Vec3d(0.5 * PI, 0.0, m_angle)) *
|
||||
Geometry::assemble_transform(2.0 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
#else
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(center.x(), center.y(), center.z()));
|
||||
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
|
||||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
|
||||
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cone.render();
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
model_matrix = m_grabbers.front().matrix * Geometry::assemble_transform(center, Vec3d(-0.5 * PI, 0.0, m_angle)) *
|
||||
Geometry::assemble_transform(2.0 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
#else
|
||||
glsafe(::glPopMatrix());
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(center.x(), center.y(), center.z()));
|
||||
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
|
||||
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
|
||||
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
|
||||
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cone.render();
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
if (! picking)
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
shader->stop_using();
|
||||
}
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
|
||||
{
|
||||
@ -974,6 +882,25 @@ void GLGizmoRotate3D::on_render()
|
||||
m_gizmos[Z].render();
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoRotate3D::on_register_raycasters_for_picking()
|
||||
{
|
||||
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
|
||||
m_parent.set_raycaster_gizmos_on_top(true);
|
||||
for (GLGizmoRotate& g : m_gizmos) {
|
||||
g.register_raycasters_for_picking();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
for (GLGizmoRotate& g : m_gizmos) {
|
||||
g.unregister_raycasters_for_picking();
|
||||
}
|
||||
m_parent.set_raycaster_gizmos_on_top(false);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
|
||||
State & state,
|
||||
const Alignment &alignment)
|
||||
|
@ -6,6 +6,7 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
class Selection;
|
||||
|
||||
class GLGizmoRotate : public GLGizmoBase
|
||||
{
|
||||
static const float Offset;
|
||||
@ -39,9 +40,6 @@ private:
|
||||
Transform3d m_orient_matrix{ Transform3d::Identity() };
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
GLModel m_cone;
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
GLModel m_circle;
|
||||
GLModel m_scale;
|
||||
@ -87,13 +85,16 @@ public:
|
||||
/// <returns>Return True when use the information otherwise False.</returns>
|
||||
bool on_mouse(const wxMouseEvent &mouse_event) override;
|
||||
void dragging(const UpdateData &data);
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
std::string on_get_name() const override { return ""; }
|
||||
void on_start_dragging() override;
|
||||
void on_dragging(const UpdateData &data) override;
|
||||
void on_render() override;
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void on_render_for_picking() override;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
private:
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -111,9 +112,6 @@ private:
|
||||
void render_angle() const;
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void render_grabber(const BoundingBoxf3& box);
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
void render_grabber_extension(const BoundingBoxf3& box, bool picking);
|
||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
Transform3d local_transform(const Selection& selection) const;
|
||||
@ -181,11 +179,16 @@ protected:
|
||||
void on_dragging(const UpdateData &data) override;
|
||||
|
||||
void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
void on_render_for_picking() override {
|
||||
for (GLGizmoRotate& g : m_gizmos) {
|
||||
g.render_for_picking();
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
|
@ -643,6 +643,18 @@ void GLGizmoScale3D::on_render()
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoScale3D::on_register_raycasters_for_picking()
|
||||
{
|
||||
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
|
||||
m_parent.set_raycaster_gizmos_on_top(true);
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.set_raycaster_gizmos_on_top(false);
|
||||
}
|
||||
#else
|
||||
void GLGizmoScale3D::on_render_for_picking()
|
||||
{
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
@ -664,6 +676,7 @@ void GLGizmoScale3D::on_render_for_picking()
|
||||
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color)
|
||||
|
@ -93,7 +93,12 @@ protected:
|
||||
virtual void on_stop_dragging() override;
|
||||
virtual void on_dragging(const UpdateData& data) override;
|
||||
virtual void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
virtual void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
private:
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
@ -38,7 +38,9 @@ protected:
|
||||
// must implement
|
||||
virtual bool on_init() override { return true;};
|
||||
virtual void on_render() override;
|
||||
virtual void on_render_for_picking() override{};
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
virtual void on_render_for_picking() override{};
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
CommonGizmosDataID on_get_requirements() const override;
|
||||
|
||||
|
@ -22,6 +22,10 @@
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
static const double CONE_RADIUS = 0.25;
|
||||
static const double CONE_HEIGHT = 0.75;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@ -47,9 +51,11 @@ bool GLGizmoSlaSupports::on_init()
|
||||
m_desc["clipping_of_view"] = _L("Clipping of view")+ ": ";
|
||||
m_desc["reset_direction"] = _L("Reset direction");
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24));
|
||||
m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.));
|
||||
m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.));
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -73,16 +79,36 @@ void GLGizmoSlaSupports::data_changed()
|
||||
if (mo->sla_points_status == sla::PointsStatus::Generating)
|
||||
get_data_from_backend();
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_raycasters.empty())
|
||||
on_register_raycasters_for_picking();
|
||||
else
|
||||
update_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::on_render()
|
||||
{
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (!m_sphere.model.is_initialized()) {
|
||||
indexed_triangle_set its = its_make_sphere(1.0, double(PI) / 12.0);
|
||||
m_sphere.model.init_from(its);
|
||||
m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
}
|
||||
if (!m_cone.model.is_initialized()) {
|
||||
indexed_triangle_set its = its_make_cone(1.0, 1.0, double(PI) / 12.0);
|
||||
m_cone.model.init_from(its);
|
||||
m_cone.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
}
|
||||
#else
|
||||
if (!m_cone.is_initialized())
|
||||
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0));
|
||||
if (!m_sphere.is_initialized())
|
||||
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
if (!m_cylinder.is_initialized())
|
||||
m_cylinder.init_from(its_make_cylinder(1.0, 1.0, double(PI) / 12.0));
|
||||
|
||||
@ -101,7 +127,11 @@ void GLGizmoSlaSupports::on_render()
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
if (selection.is_from_single_instance())
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
render_points(selection);
|
||||
#else
|
||||
render_points(selection, false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_selection_rectangle.render(m_parent);
|
||||
m_c->object_clipper()->render_cut();
|
||||
@ -110,15 +140,41 @@ void GLGizmoSlaSupports::on_render()
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoSlaSupports::on_register_raycasters_for_picking()
|
||||
{
|
||||
assert(m_raycasters.empty());
|
||||
set_sla_auxiliary_volumes_picking_state(false);
|
||||
|
||||
if (m_editing_mode && !m_editing_cache.empty()) {
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_sphere.mesh_raycaster, Transform3d::Identity()),
|
||||
m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
||||
}
|
||||
update_raycasters_for_picking_transform();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
|
||||
m_raycasters.clear();
|
||||
set_sla_auxiliary_volumes_picking_state(true);
|
||||
}
|
||||
#else
|
||||
void GLGizmoSlaSupports::on_render_for_picking()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
//glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
render_points(selection, true);
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoSlaSupports::render_points(const Selection& selection)
|
||||
#else
|
||||
void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
|
||||
|
||||
@ -130,7 +186,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
return;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
#else
|
||||
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
@ -147,19 +207,16 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
const GLVolume* vol = selection.get_first_volume();
|
||||
Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix());
|
||||
const Geometry::Transformation transformation(vol->world_matrix());
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Transform3d instance_scaling_matrix_inverse = transformation.get_scaling_factor_matrix().inverse();
|
||||
#else
|
||||
const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * transformation.get_matrix();
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
const Transform3d& projection_matrix = camera.get_projection_matrix();
|
||||
|
||||
shader->set_uniform("projection_matrix", projection_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
#else
|
||||
const Transform3d& instance_matrix = transformation.get_matrix();
|
||||
const float z_shift = m_c->selection_info()->get_sla_shift();
|
||||
@ -173,13 +230,25 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i];
|
||||
const bool point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const bool clipped = is_mesh_point_clipped(support_point.pos.cast<double>());
|
||||
if (!m_raycasters.empty()) {
|
||||
m_raycasters[i].first->set_active(!clipped);
|
||||
m_raycasters[i].second->set_active(!clipped);
|
||||
}
|
||||
if (clipped)
|
||||
continue;
|
||||
#else
|
||||
if (is_mesh_point_clipped(support_point.pos.cast<double>()))
|
||||
continue;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// First decide about the color of the point.
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
if (picking)
|
||||
render_color = picking_color_component(i);
|
||||
else {
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
if (size_t(m_hover_id) == i && m_editing_mode) // ignore hover state unless editing mode is active
|
||||
render_color = { 0.f, 1.f, 1.f, 1.f };
|
||||
else { // neigher hover nor picking
|
||||
@ -196,12 +265,21 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
else
|
||||
render_color = { 0.5f, 0.5f, 0.5f, 1.f };
|
||||
}
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_cone.model.set_color(render_color);
|
||||
m_sphere.model.set_color(render_color);
|
||||
#else
|
||||
m_cone.set_color(render_color);
|
||||
m_sphere.set_color(render_color);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
if (!picking)
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
#else
|
||||
m_cone.set_color(-1, render_color);
|
||||
m_sphere.set_color(-1, render_color);
|
||||
@ -211,7 +289,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d support_matrix = Geometry::assemble_transform(support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
const Transform3d support_matrix = Geometry::translation_transform(support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
#else
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(support_point.pos.x(), support_point.pos.y(), support_point.pos.z()));
|
||||
@ -231,12 +309,19 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
const double cone_radius = 0.25; // mm
|
||||
const double cone_height = 0.75;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d model_matrix = instance_matrix * support_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
const Transform3d model_matrix = vol->world_matrix() * support_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
Geometry::assemble_transform((CONE_HEIGHT + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(),
|
||||
Vec3d(PI, 0.0, 0.0), Vec3d(CONE_RADIUS, CONE_RADIUS, CONE_HEIGHT));
|
||||
#else
|
||||
Geometry::assemble_transform((cone_height + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(),
|
||||
Vec3d(PI, 0.0, 0.0), Vec3d(cone_radius, cone_radius, cone_height));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
@ -248,7 +333,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
glsafe(::glRotated(180., 1., 0., 0.));
|
||||
glsafe(::glScaled(cone_radius, cone_radius, cone_height));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_cone.model.render();
|
||||
#else
|
||||
m_cone.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -256,9 +345,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
const double radius = (double)support_point.head_front_radius * RenderPointScale;
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d model_matrix = instance_matrix * support_matrix *
|
||||
Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), radius * Vec3d::Ones());
|
||||
|
||||
const Transform3d model_matrix = vol->world_matrix() * support_matrix * Geometry::scale_transform(radius);
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
@ -266,7 +353,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glScaled(radius, radius, radius));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_sphere.model.render();
|
||||
#else
|
||||
m_sphere.render();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -280,7 +371,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
}
|
||||
|
||||
// Now render the drain holes:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (has_holes) {
|
||||
#else
|
||||
if (has_holes && ! picking) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
render_color = { 0.7f, 0.7f, 0.7f, 0.7f };
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cylinder.set_color(render_color);
|
||||
@ -294,7 +389,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
continue;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
#else
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glPushMatrix());
|
||||
@ -310,9 +405,8 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d model_matrix = instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
|
||||
const Transform3d model_matrix = vol->world_matrix() * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
@ -450,6 +544,10 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
|
||||
m_parent.set_as_dirty();
|
||||
m_wait_for_up_event = true;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -474,7 +572,12 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
|
||||
// Now ask the rectangle which of the points are inside.
|
||||
std::vector<Vec3f> points_inside;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::vector<unsigned int> points_idxs = m_selection_rectangle.contains(points);
|
||||
m_selection_rectangle.stop_dragging();
|
||||
#else
|
||||
std::vector<unsigned int> points_idxs = m_selection_rectangle.stop_dragging(m_parent, points);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
for (size_t idx : points_idxs)
|
||||
points_inside.push_back(points[idx].cast<float>());
|
||||
|
||||
@ -604,6 +707,11 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
select_point(NoPoints);
|
||||
}
|
||||
|
||||
@ -1281,6 +1389,9 @@ void GLGizmoSlaSupports::switch_to_editing_mode()
|
||||
for (const sla::SupportPoint& sp : m_normal_cache)
|
||||
m_editing_cache.emplace_back(sp);
|
||||
select_point(NoPoints);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_c->instances_hider()->show_supports(false);
|
||||
m_parent.set_as_dirty();
|
||||
@ -1294,6 +1405,9 @@ void GLGizmoSlaSupports::disable_editing_mode()
|
||||
wxGetApp().plater()->leave_gizmos_stack();
|
||||
m_c->instances_hider()->show_supports(true);
|
||||
m_parent.set_as_dirty();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
wxGetApp().plater()->get_notification_manager()->close_notification_of_type(NotificationType::QuitSLAManualMode);
|
||||
}
|
||||
@ -1312,6 +1426,54 @@ bool GLGizmoSlaSupports::unsaved_changes() const
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoSlaSupports::set_sla_auxiliary_volumes_picking_state(bool state)
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||
if (raycasters != nullptr) {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList ids = selection.get_volume_idxs();
|
||||
for (unsigned int id : ids) {
|
||||
const GLVolume* v = selection.get_volume(id);
|
||||
if (v->is_sla_pad() || v->is_sla_support()) {
|
||||
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
||||
if (it != raycasters->end())
|
||||
(*it)->set_active(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::update_raycasters_for_picking_transform()
|
||||
{
|
||||
if (!m_editing_cache.empty()) {
|
||||
assert(!m_raycasters.empty());
|
||||
|
||||
const GLVolume* vol = m_parent.get_selection().get_first_volume();
|
||||
const Geometry::Transformation transformation(vol->world_matrix());
|
||||
const Transform3d instance_scaling_matrix_inverse = transformation.get_scaling_factor_matrix().inverse();
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
const Transform3d support_matrix = Geometry::translation_transform(m_editing_cache[i].support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
|
||||
if (m_editing_cache[i].normal == Vec3f::Zero())
|
||||
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
const Transform3d cone_matrix = vol->world_matrix() * support_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::assemble_transform((CONE_HEIGHT + m_editing_cache[i].support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(),
|
||||
Vec3d(PI, 0.0, 0.0), Vec3d(CONE_RADIUS, CONE_RADIUS, CONE_HEIGHT));
|
||||
m_raycasters[i].second->set_transform(cone_matrix);
|
||||
|
||||
const double radius = (double)m_editing_cache[i].support_point.head_front_radius * RenderPointScale;
|
||||
const Transform3d sphere_matrix = vol->world_matrix() * support_matrix * Geometry::scale_transform(radius);
|
||||
m_raycasters[i].first->set_transform(sphere_matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
SlaGizmoHelpDialog::SlaGizmoHelpDialog()
|
||||
: wxDialog(nullptr, wxID_ANY, _L("SLA gizmo keyboard shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
{
|
||||
|
@ -77,13 +77,27 @@ public:
|
||||
/// <param name="mouse_event">Keep information about mouse click</param>
|
||||
/// <returns>Return True when use the information otherwise False.</returns>
|
||||
bool on_mouse(const wxMouseEvent &mouse_event) override;
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
void on_render() override;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
virtual void on_register_raycasters_for_picking() override;
|
||||
virtual void on_unregister_raycasters_for_picking() override;
|
||||
#else
|
||||
void on_render_for_picking() override;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void render_points(const Selection& selection);
|
||||
#else
|
||||
void render_points(const Selection& selection, bool picking = false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
bool unsaved_changes() const;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void set_sla_auxiliary_volumes_picking_state(bool state);
|
||||
void update_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
bool m_lock_unique_islands = false;
|
||||
bool m_editing_mode = false; // Is editing mode active?
|
||||
@ -96,9 +110,15 @@ private:
|
||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||
ObjectID m_old_mo_id;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel m_sphere;
|
||||
PickingModel m_cone;
|
||||
std::vector<std::pair<std::shared_ptr<SceneRaycasterItem>, std::shared_ptr<SceneRaycasterItem>>> m_raycasters;
|
||||
#else
|
||||
GLModel m_cone;
|
||||
GLModel m_cylinder;
|
||||
GLModel m_sphere;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
GLModel m_cylinder;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
|
@ -351,7 +351,11 @@ void Raycaster::on_update()
|
||||
if (meshes != m_old_meshes) {
|
||||
m_raycasters.clear();
|
||||
for (const TriangleMesh* mesh : meshes)
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
m_raycasters.emplace_back(new MeshRaycaster(std::make_shared<const TriangleMesh>(*mesh)));
|
||||
#else
|
||||
m_raycasters.emplace_back(new MeshRaycaster(*mesh));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
m_old_meshes = meshes;
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ enum class CommonGizmosDataID {
|
||||
// by GLGizmoManager, the gizmos keep a pointer to it.
|
||||
class CommonGizmosDataPool {
|
||||
public:
|
||||
CommonGizmosDataPool(GLCanvas3D* canvas);
|
||||
explicit CommonGizmosDataPool(GLCanvas3D* canvas);
|
||||
|
||||
// Update all resources and release what is not used.
|
||||
// Accepts a bitmask of currently required resources.
|
||||
|
@ -331,6 +331,7 @@ void GLGizmosManager::render_painter_gizmo()
|
||||
gizmo->render_painter_gizmo();
|
||||
}
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void GLGizmosManager::render_current_gizmo_for_picking_pass() const
|
||||
{
|
||||
if (! m_enabled || m_current == Undefined)
|
||||
@ -339,6 +340,7 @@ void GLGizmosManager::render_current_gizmo_for_picking_pass() const
|
||||
|
||||
m_gizmos[m_current]->render_for_picking();
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmosManager::render_overlay()
|
||||
{
|
||||
@ -1117,6 +1119,10 @@ bool GLGizmosManager::activate_gizmo(EType type)
|
||||
if (old_gizmo.get_state() != GLGizmoBase::Off)
|
||||
return false; // gizmo refused to be turned off, do nothing.
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
old_gizmo.unregister_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
if (!m_serializing && old_gizmo.wants_enter_leave_snapshots())
|
||||
Plater::TakeSnapshot
|
||||
snapshot(wxGetApp().plater(),
|
||||
@ -1146,6 +1152,10 @@ bool GLGizmosManager::activate_gizmo(EType type)
|
||||
return false; // gizmo refused to be turned on.
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
new_gizmo.register_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// sucessful activation of gizmo
|
||||
return true;
|
||||
}
|
||||
|
@ -213,7 +213,9 @@ public:
|
||||
bool is_hiding_instances() const;
|
||||
|
||||
void render_current_gizmo() const;
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
void render_current_gizmo_for_picking_pass() const;
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
void render_painter_gizmo();
|
||||
|
||||
void render_overlay();
|
||||
|
@ -172,10 +172,6 @@ void KBShortcutsDialog::fill_shortcuts()
|
||||
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
|
||||
#endif // __APPLE__
|
||||
#endif // _WIN32
|
||||
#if ENABLE_RENDER_PICKING_PASS
|
||||
// Don't localize debugging texts.
|
||||
{ "P", "Toggle picking pass texture rendering on/off" },
|
||||
#endif // ENABLE_RENDER_PICKING_PASS
|
||||
};
|
||||
|
||||
m_full_shortcuts.push_back({ { _L("Plater"), "" }, plater_shortcuts });
|
||||
|
@ -234,8 +234,13 @@ Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const
|
||||
return m_normals[facet_idx];
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction)
|
||||
#else
|
||||
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction) const
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
{
|
||||
Matrix4d modelview = camera.get_view_matrix().matrix();
|
||||
Matrix4d projection= camera.get_projection_matrix().matrix();
|
||||
@ -243,9 +248,9 @@ void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3
|
||||
|
||||
Vec3d pt1;
|
||||
Vec3d pt2;
|
||||
igl::unproject(Vec3d(mouse_pos(0), viewport[3] - mouse_pos(1), 0.),
|
||||
igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), 0.),
|
||||
modelview, projection, viewport, pt1);
|
||||
igl::unproject(Vec3d(mouse_pos(0), viewport[3] - mouse_pos(1), 1.),
|
||||
igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), 1.),
|
||||
modelview, projection, viewport, pt2);
|
||||
|
||||
Transform3d inv = trafo.inverse();
|
||||
@ -350,6 +355,40 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo
|
||||
return out;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
bool MeshRaycaster::closest_hit(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane, size_t* facet_idx) const
|
||||
{
|
||||
Vec3d point;
|
||||
Vec3d direction;
|
||||
line_from_mouse_pos(mouse_pos, trafo, camera, point, direction);
|
||||
|
||||
const std::vector<sla::IndexedMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction.normalized());
|
||||
|
||||
if (hits.empty())
|
||||
return false; // no intersection found
|
||||
|
||||
size_t hit_id = 0;
|
||||
if (clipping_plane != nullptr) {
|
||||
while (hit_id < hits.size() && clipping_plane->is_point_clipped(trafo * hits[hit_id].position())) {
|
||||
++hit_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_id == hits.size())
|
||||
return false; // all points are obscured or cut by the clipping plane.
|
||||
|
||||
const sla::IndexedMesh::hit_result& hit = hits[hit_id];
|
||||
|
||||
position = hit.position().cast<float>();
|
||||
normal = hit.normal().cast<float>();
|
||||
|
||||
if (facet_idx != nullptr)
|
||||
*facet_idx = hit.face();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
Vec3f MeshRaycaster::get_closest_point(const Vec3f& point, Vec3f* normal) const
|
||||
{
|
||||
|
@ -14,6 +14,9 @@
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
#include <cfloat>
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
#include <memory>
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -57,6 +60,10 @@ public:
|
||||
void set_offset(double offset) { m_data[3] = offset; }
|
||||
double get_offset() const { return m_data[3]; }
|
||||
Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); }
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void invert_normal() { m_data[0] *= -1.0; m_data[1] *= -1.0; m_data[2] *= -1.0; }
|
||||
ClippingPlane inverted_normal() const { return ClippingPlane(-get_normal(), get_offset()); }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
bool is_active() const { return m_data[3] != DBL_MAX; }
|
||||
static ClippingPlane ClipsNothing() { return ClippingPlane(Vec3d(0., 0., 1.), DBL_MAX); }
|
||||
const std::array<double, 4>& get_data() const { return m_data; }
|
||||
@ -123,6 +130,18 @@ private:
|
||||
// whether certain points are visible or obscured by the mesh etc.
|
||||
class MeshRaycaster {
|
||||
public:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
explicit MeshRaycaster(std::shared_ptr<const TriangleMesh> mesh)
|
||||
: m_mesh(mesh)
|
||||
, m_emesh(*mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length
|
||||
, m_normals(its_face_normals(mesh->its))
|
||||
{
|
||||
assert(m_mesh != nullptr);
|
||||
}
|
||||
|
||||
static void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction);
|
||||
#else
|
||||
// The class references extern TriangleMesh, which must stay alive
|
||||
// during MeshRaycaster existence.
|
||||
MeshRaycaster(const TriangleMesh& mesh)
|
||||
@ -132,7 +151,8 @@ public:
|
||||
}
|
||||
|
||||
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3d& point, Vec3d& direction) const;
|
||||
Vec3d& point, Vec3d& direction) const;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// Given a mouse position, this returns true in case it is on the mesh.
|
||||
bool unproject_on_mesh(
|
||||
@ -155,10 +175,24 @@ public:
|
||||
const ClippingPlane* clipping_plane = nullptr // clipping plane (if active)
|
||||
) const;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
// Returns true if the ray, built from mouse position and camera direction, intersects the mesh.
|
||||
// In this case, position and normal contain the position and normal, in model coordinates, of the intersection closest to the camera,
|
||||
// depending on the position/orientation of the clipping_plane, if specified
|
||||
bool closest_hit(
|
||||
const Vec2d& mouse_pos,
|
||||
const Transform3d& trafo, // how to get the mesh into world coords
|
||||
const Camera& camera, // current camera position
|
||||
Vec3f& position, // where to save the positibon of the hit (mesh coords)
|
||||
Vec3f& normal, // normal of the triangle that was hit
|
||||
const ClippingPlane* clipping_plane = nullptr, // clipping plane (if active)
|
||||
size_t* facet_idx = nullptr // index of the facet hit
|
||||
) const;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
// Given a point in world coords, the method returns closest point on the mesh.
|
||||
// The output is in mesh coords.
|
||||
// normal* can be used to also get normal of the respective triangle.
|
||||
|
||||
Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const;
|
||||
|
||||
// Given a point in mesh coords, the method returns the closest facet from mesh.
|
||||
@ -167,11 +201,26 @@ public:
|
||||
Vec3f get_triangle_normal(size_t facet_idx) const;
|
||||
|
||||
private:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
std::shared_ptr<const TriangleMesh> m_mesh;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
sla::IndexedMesh m_emesh;
|
||||
std::vector<stl_normal> m_normals;
|
||||
};
|
||||
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
struct PickingModel
|
||||
{
|
||||
GLModel model;
|
||||
std::unique_ptr<MeshRaycaster> mesh_raycaster;
|
||||
|
||||
void reset() {
|
||||
model.reset();
|
||||
mesh_raycaster.reset();
|
||||
}
|
||||
};
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
209
src/slic3r/GUI/SceneRaycaster.cpp
Normal file
209
src/slic3r/GUI/SceneRaycaster.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "SceneRaycaster.hpp"
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
SceneRaycaster::SceneRaycaster() {
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
// hit point
|
||||
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 16.0));
|
||||
m_sphere.set_color(ColorRGBA::YELLOW());
|
||||
|
||||
// hit normal
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
|
||||
init_data.color = ColorRGBA::YELLOW();
|
||||
init_data.reserve_vertices(2);
|
||||
init_data.reserve_indices(2);
|
||||
|
||||
// vertices
|
||||
init_data.add_vertex((Vec3f)Vec3f::Zero());
|
||||
init_data.add_vertex((Vec3f)Vec3f::UnitZ());
|
||||
|
||||
// indices
|
||||
init_data.add_line(0, 1);
|
||||
|
||||
m_line.init_from(std::move(init_data));
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
|
||||
std::shared_ptr<SceneRaycasterItem> SceneRaycaster::add_raycaster(EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo)
|
||||
{
|
||||
switch (type) {
|
||||
case EType::Bed: { return m_bed.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo)); }
|
||||
case EType::Volume: { return m_volumes.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo)); }
|
||||
case EType::Gizmo: { return m_gizmos.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo)); }
|
||||
default: { assert(false); return nullptr; }
|
||||
};
|
||||
}
|
||||
|
||||
void SceneRaycaster::remove_raycasters(EType type, int id)
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
|
||||
auto it = raycasters->begin();
|
||||
while (it != raycasters->end()) {
|
||||
if ((*it)->get_id() == encode_id(type, id))
|
||||
it = raycasters->erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneRaycaster::remove_raycasters(EType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EType::Bed: { m_bed.clear(); break; }
|
||||
case EType::Volume: { m_volumes.clear(); break; }
|
||||
case EType::Gizmo: { m_gizmos.clear(); break; }
|
||||
default: { break; }
|
||||
};
|
||||
}
|
||||
|
||||
void SceneRaycaster::remove_raycaster(std::shared_ptr<SceneRaycasterItem> item)
|
||||
{
|
||||
for (auto it = m_bed.begin(); it != m_bed.end(); ++it) {
|
||||
if (*it == item) {
|
||||
m_bed.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto it = m_volumes.begin(); it != m_volumes.end(); ++it) {
|
||||
if (*it == item) {
|
||||
m_volumes.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto it = m_gizmos.begin(); it != m_gizmos.end(); ++it) {
|
||||
if (*it == item) {
|
||||
m_gizmos.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane)
|
||||
{
|
||||
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||
auto is_closest = [&closest_hit_squared_distance](const Camera& camera, const Vec3f& hit) {
|
||||
const double hit_squared_distance = (camera.get_position() - hit.cast<double>()).squaredNorm();
|
||||
const bool ret = hit_squared_distance < closest_hit_squared_distance;
|
||||
if (ret)
|
||||
closest_hit_squared_distance = hit_squared_distance;
|
||||
return ret;
|
||||
};
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
m_last_hit.reset();
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
HitResult ret;
|
||||
|
||||
auto test_raycasters = [this, is_closest, clipping_plane](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) {
|
||||
const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
|
||||
HitResult current_hit = { type };
|
||||
for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
|
||||
if (!item->is_active())
|
||||
continue;
|
||||
|
||||
current_hit.raycaster_id = item->get_id();
|
||||
const Transform3d& trafo = item->get_transform();
|
||||
if (item->get_raycaster()->closest_hit(mouse_pos, trafo, camera, current_hit.position, current_hit.normal, clip_plane)) {
|
||||
current_hit.position = (trafo * current_hit.position.cast<double>()).cast<float>();
|
||||
if (is_closest(camera, current_hit.position)) {
|
||||
const Matrix3d normal_matrix = (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
current_hit.normal = (normal_matrix * current_hit.normal.cast<double>()).normalized().cast<float>();
|
||||
ret = current_hit;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!m_gizmos.empty())
|
||||
test_raycasters(EType::Gizmo, mouse_pos, camera, ret);
|
||||
|
||||
if (!m_gizmos_on_top || !ret.is_valid()) {
|
||||
if (camera.is_looking_downward() && !m_bed.empty())
|
||||
test_raycasters(EType::Bed, mouse_pos, camera, ret);
|
||||
if (!m_volumes.empty())
|
||||
test_raycasters(EType::Volume, mouse_pos, camera, ret);
|
||||
}
|
||||
|
||||
if (ret.is_valid())
|
||||
ret.raycaster_id = decode_id(ret.type, ret.raycaster_id);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
m_last_hit = ret;
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
void SceneRaycaster::render_hit(const Camera& camera)
|
||||
{
|
||||
if (!m_last_hit.has_value() || !(*m_last_hit).is_valid())
|
||||
return;
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
shader->start_using();
|
||||
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
const Transform3d sphere_view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform((*m_last_hit).position.cast<double>()) *
|
||||
Geometry::scale_transform(4.0 * camera.get_inv_zoom());
|
||||
shader->set_uniform("view_model_matrix", sphere_view_model_matrix);
|
||||
m_sphere.render();
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(Vec3d::UnitZ(), (*m_last_hit).normal.cast<double>()).toRotationMatrix();
|
||||
|
||||
const Transform3d line_view_model_matrix = sphere_view_model_matrix * m * Geometry::scale_transform(10.0);
|
||||
shader->set_uniform("view_model_matrix", line_view_model_matrix);
|
||||
m_line.render();
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* SceneRaycaster::get_raycasters(EType type)
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* ret = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case EType::Bed: { ret = &m_bed; break; }
|
||||
case EType::Volume: { ret = &m_volumes; break; }
|
||||
case EType::Gizmo: { ret = &m_gizmos; break; }
|
||||
default: { break; }
|
||||
}
|
||||
assert(ret != nullptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SceneRaycaster::base_id(EType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EType::Bed: { return int(EIdBase::Bed); }
|
||||
case EType::Volume: { return int(EIdBase::Volume); }
|
||||
case EType::Gizmo: { return int(EIdBase::Gizmo); }
|
||||
default: { break; }
|
||||
};
|
||||
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SceneRaycaster::encode_id(EType type, int id) { return base_id(type) + id; }
|
||||
int SceneRaycaster::decode_id(EType type, int id) { return id - base_id(type); }
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
113
src/slic3r/GUI/SceneRaycaster.hpp
Normal file
113
src/slic3r/GUI/SceneRaycaster.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef slic3r_SceneRaycaster_hpp_
|
||||
#define slic3r_SceneRaycaster_hpp_
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
|
||||
#include "MeshUtils.hpp"
|
||||
#include "GLModel.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
struct Camera;
|
||||
|
||||
class SceneRaycasterItem
|
||||
{
|
||||
int m_id{ -1 };
|
||||
bool m_active{ true };
|
||||
const MeshRaycaster* m_raycaster;
|
||||
Transform3d m_trafo;
|
||||
|
||||
public:
|
||||
SceneRaycasterItem(int id, const MeshRaycaster& raycaster, const Transform3d& trafo)
|
||||
: m_id(id), m_raycaster(&raycaster), m_trafo(trafo)
|
||||
{}
|
||||
|
||||
int get_id() const { return m_id; }
|
||||
bool is_active() const { return m_active; }
|
||||
void set_active(bool active) { m_active = active; }
|
||||
const MeshRaycaster* get_raycaster() const { return m_raycaster; }
|
||||
const Transform3d& get_transform() const { return m_trafo; }
|
||||
void set_transform(const Transform3d& trafo) { m_trafo = trafo; }
|
||||
};
|
||||
|
||||
class SceneRaycaster
|
||||
{
|
||||
public:
|
||||
enum class EType
|
||||
{
|
||||
None,
|
||||
Bed,
|
||||
Volume,
|
||||
Gizmo
|
||||
};
|
||||
|
||||
enum class EIdBase
|
||||
{
|
||||
Bed = 0,
|
||||
Volume = 1000,
|
||||
Gizmo = 1000000
|
||||
};
|
||||
|
||||
struct HitResult
|
||||
{
|
||||
EType type{ EType::None };
|
||||
int raycaster_id{ -1 };
|
||||
Vec3f position{ Vec3f::Zero() };
|
||||
Vec3f normal{ Vec3f::Zero() };
|
||||
|
||||
bool is_valid() const { return raycaster_id != -1; }
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_bed;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volumes;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_gizmos;
|
||||
|
||||
// When set to true, if checking gizmos returns a valid hit,
|
||||
// the search is not performed on other types
|
||||
bool m_gizmos_on_top{ false };
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
GLModel m_sphere;
|
||||
GLModel m_line;
|
||||
std::optional<HitResult> m_last_hit;
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
public:
|
||||
SceneRaycaster();
|
||||
|
||||
std::shared_ptr<SceneRaycasterItem> add_raycaster(EType type, int picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo);
|
||||
void remove_raycasters(EType type, int id);
|
||||
void remove_raycasters(EType type);
|
||||
void remove_raycaster(std::shared_ptr<SceneRaycasterItem> item);
|
||||
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type);
|
||||
|
||||
void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; }
|
||||
|
||||
HitResult hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane = nullptr);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
void render_hit(const Camera& camera);
|
||||
|
||||
size_t beds_count() const { return m_bed.size(); }
|
||||
size_t volumes_count() const { return m_volumes.size(); }
|
||||
size_t gizmos_count() const { return m_gizmos.size(); }
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
private:
|
||||
static int encode_id(EType type, int id);
|
||||
static int decode_id(EType type, int id);
|
||||
static int base_id(EType type);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
#endif // slic3r_SceneRaycaster_hpp_
|
@ -20,6 +20,7 @@ SCENARIO("Color encoding/decoding cycle", "[Color]") {
|
||||
}
|
||||
}
|
||||
|
||||
#if !ENABLE_RAYCAST_PICKING
|
||||
SCENARIO("Color picking encoding/decoding cycle", "[Color]") {
|
||||
GIVEN("Picking color") {
|
||||
const ColorRGB src_rgb(static_cast<unsigned char>(255), static_cast<unsigned char>(127), static_cast<unsigned char>(63));
|
||||
@ -33,5 +34,6 @@ SCENARIO("Color picking encoding/decoding cycle", "[Color]") {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user