SLA gizmo now respects the clipping plane when rendering points and raycasting mouse onto mesh

This commit is contained in:
Lukas Matena 2019-03-20 08:48:42 +01:00
parent fd1f9d65fb
commit bc9164e40c
4 changed files with 74 additions and 27 deletions

View File

@ -2582,27 +2582,7 @@ void GLCanvas3D::render()
if (early_bed_render)
_render_bed(theta);
////////////////////////
//Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> stashed_projection_matrix;
//::glGetDoublev(GL_PROJECTION_MATRIX, stashed_projection_matrix.data());
const Size& cnv_size = get_canvas_size();
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) {
std::pair<float, float> clipping_limits = m_gizmos.get_sla_clipping_plane();
set_ortho_projection((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height(), clipping_limits.first, clipping_limits.second);
}
////////////////////
_render_objects();
//////////////////////////////////
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) {
//::glMatrixMode(GL_PROJECTION);
//::glLoadIdentity();
//::glMultMatrixd(stashed_projection_matrix.data());
//::glMatrixMode(GL_MODELVIEW);
_resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
}
//////////////////////////////////
_render_sla_slices();
_render_selection();
@ -4720,6 +4700,28 @@ void GLCanvas3D::set_ortho_projection(float w, float h, float near, float far) c
}
void GLCanvas3D::set_sla_clipping(bool enable) const
{
if (m_gizmos.get_current_type() != Gizmos::SlaSupports)
return;
if (enable) {
::glMatrixMode(GL_PROJECTION);
::glPushMatrix();
::glMatrixMode(GL_MODELVIEW);
const Size& cnv_size = get_canvas_size();
std::pair<float, float> clipping_limits = m_gizmos.get_sla_clipping_plane();
set_ortho_projection((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height(), clipping_limits.first, clipping_limits.second);
}
else {
::glMatrixMode(GL_PROJECTION);
::glPopMatrix();
::glMatrixMode(GL_MODELVIEW);
::glClear(GL_DEPTH_BUFFER_BIT);
}
}
void GLCanvas3D::_render_objects() const
{
if (m_volumes.empty())
@ -4728,6 +4730,8 @@ void GLCanvas3D::_render_objects() const
::glEnable(GL_LIGHTING);
::glEnable(GL_DEPTH_TEST);
set_sla_clipping(true);
if (m_use_VBOs)
{
if (m_picking_enabled)
@ -4789,6 +4793,8 @@ void GLCanvas3D::_render_objects() const
}
}
set_sla_clipping(false);
::glDisable(GL_LIGHTING);
}
@ -4831,6 +4837,8 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const
if (!fake_colors)
::glEnable(GL_LIGHTING);
set_sla_clipping(true);
// do not cull backfaces to show broken geometry, if any
::glDisable(GL_CULL_FACE);
@ -4869,6 +4877,8 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const
::glEnable(GL_CULL_FACE);
set_sla_clipping(false);
if (!fake_colors)
::glDisable(GL_LIGHTING);
}

View File

@ -778,6 +778,9 @@ private:
// Sets current projection matrix to ortho, accounting for current camera zoom.
void set_ortho_projection(float w, float h, float near, float far) const;
// Set/unset near clipping plane according to SLA gizmo requirements.
void set_sla_clipping(bool enable) const;
void _start_timer();
void _stop_timer();

View File

@ -157,6 +157,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
// we'll recover current look direction from the modelview matrix (in world coords):
Eigen::Matrix<double, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
::glPushMatrix();
::glTranslated(0.0, 0.0, z_shift);
::glMultMatrixd(instance_matrix.data());
@ -167,6 +172,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point;
const bool& point_selected = m_editing_mode_cache[i].selected;
if (is_point_clipped(support_point.pos.cast<double>(), direction_to_camera, z_shift))
continue;
// First decide about the color of the point.
if (picking) {
std::array<float, 3> color = picking_color_component(i);
@ -285,6 +293,8 @@ void GLGizmoSlaSupports::update_mesh()
m_AABB.init(m_V, m_F);
}
// Unprojects the mouse position on the mesh and return the hit point and normal of the facet.
// The function throws if no intersection if found.
std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
{
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
@ -303,12 +313,15 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
igl::Hit hit;
std::vector<igl::Hit> hits;
const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z();
// we'll recover current look direction from the modelview matrix (in world coords):
Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
point1(2) -= z_offset;
point2(2) -= z_offset;
@ -317,17 +330,37 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
point1 = inv * point1;
point2 = inv * point2;
if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hit))
if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hits))
throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
int fid = hit.id; // facet id
Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit
Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0)));
Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0)));
std::sort(hits.begin(), hits.end(), [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
// Now let's iterate through the points and find the first that is not clipped:
unsigned int i=0;
Vec3f bc;
Vec3f a;
Vec3f b;
Vec3f result;
for (i=0; i<hits.size(); ++i) {
igl::Hit& hit = hits[i];
int fid = hit.id; // facet id
bc = Vec3f(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit
a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0)));
b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0)));
result = bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2));
if (m_clipping_plane_distance == 0.f || !is_point_clipped(result.cast<double>(), direction_to_camera, z_offset))
break;
}
if (i==hits.size() || (hits.size()-i) % 2 != 0) {
// All hits are either clipped, or there is an odd number of unclipped
// hits - meaning the nearest must be from inside the mesh.
throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
}
// Calculate and return both the point and the facet normal.
return std::make_pair(
bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)),
result,
a.cross(b)
);
}

View File

@ -86,6 +86,7 @@ private:
int m_canvas_height;
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
bool is_point_clipped(const Vec3d& point, const Vec3d& direction_to_camera, float z_shift) const;
// Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc: