mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 14:51:06 +00:00
* Add Missing Includes Across src/slic3r/GUI Every GUI source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, plus one hand edit making CalibrationPanel.hpp self-contained. * Drop the OS-Specific Includes Added Outside Their Platform Guards GLib, GTK, D-Bus and POSIX headers are only used inside platform #if blocks, which already include them. Added unconditionally at the top of the file they broke the Windows build. * Add the clang-tidy Configuration That Generated These Includes Only misc-include-cleaner's missing-include check, with the headers it must never suggest: per-platform, internal and OS-specific ones that would break other platforms or are not meant to be included directly. * Match Windows Paths in the clang-tidy Ignore List Header paths use backslashes on Windows, so every / in a pattern is now [/\\]. The Windows SDK headers are ignored alongside the other OS-specific ones, and the list is one pattern per line. Suggested by @raistlin7447 from a Windows clang-cl run.
142 lines
5.1 KiB
C++
142 lines
5.1 KiB
C++
#include "CameraUtils.hpp"
|
|
#include <Eigen/Core>
|
|
#include <cstddef>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <igl/project.h> // projecting points
|
|
#include <igl/unproject.h>
|
|
#include "libslic3r/Point.hpp"
|
|
#include "slic3r/GUI/Camera.hpp"
|
|
#include <vector>
|
|
#include "libslic3r/Polygon.hpp"
|
|
#include "libslic3r/TriangleMesh.hpp"
|
|
#include <limits>
|
|
|
|
#include "slic3r/GUI/3DScene.hpp" // GLVolume
|
|
#include "libslic3r/Geometry/ConvexHull.hpp"
|
|
|
|
using namespace Slic3r;
|
|
using namespace GUI;
|
|
|
|
Points CameraUtils::project(const Camera & camera,
|
|
const std::vector<Vec3d> &points)
|
|
{
|
|
Vec4i32 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);
|
|
for (size_t i = 0; i < points.size(); ++i)
|
|
pts.block<1, 3>(i, 0) = points[i];
|
|
|
|
// Get the projections.
|
|
Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::DontAlign> projections;
|
|
igl::project(pts, camera.get_view_matrix().matrix(),
|
|
camera.get_projection_matrix().matrix(), viewport, projections);
|
|
|
|
Points result;
|
|
result.reserve(points.size());
|
|
int window_height = viewport[3];
|
|
|
|
// convert to points --> loss precision
|
|
for (int i = 0; i < projections.rows(); ++i) {
|
|
double x = projections(i, 0);
|
|
double y = projections(i, 1);
|
|
// opposit direction o Y
|
|
result.emplace_back(x, window_height - y);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Slic3r::Point CameraUtils::project(const Camera &camera, const Vec3d &point)
|
|
{
|
|
// IMPROVE: do it faster when you need it (inspire in project multi point)
|
|
return project(camera, std::vector{point}).front();
|
|
}
|
|
|
|
Slic3r::Polygon CameraUtils::create_hull2d(const Camera & camera,
|
|
const GLVolume &volume)
|
|
{
|
|
std::vector<Vec3d> vertices;
|
|
const TriangleMesh *hull = volume.convex_hull();
|
|
if (hull != nullptr) {
|
|
const indexed_triangle_set &its = hull->its;
|
|
vertices.reserve(its.vertices.size());
|
|
// cast vector
|
|
for (const Vec3f &vertex : its.vertices)
|
|
vertices.emplace_back(vertex.cast<double>());
|
|
} else {
|
|
// Negative volume doesn't have convex hull so use bounding box
|
|
auto bb = volume.bounding_box();
|
|
Vec3d &min = bb.min;
|
|
Vec3d &max = bb.max;
|
|
vertices = {min,
|
|
Vec3d(min.x(), min.y(), max.z()),
|
|
Vec3d(min.x(), max.y(), min.z()),
|
|
Vec3d(min.x(), max.y(), max.z()),
|
|
Vec3d(max.x(), min.y(), min.z()),
|
|
Vec3d(max.x(), min.y(), max.z()),
|
|
Vec3d(max.x(), max.y(), min.z()),
|
|
max};
|
|
}
|
|
|
|
const Transform3d &trafoMat =
|
|
volume.get_instance_transformation().get_matrix() *
|
|
volume.get_volume_transformation().get_matrix();
|
|
for (Vec3d &vertex : vertices)
|
|
vertex = trafoMat * vertex.cast<double>();
|
|
|
|
Points vertices_2d = project(camera, vertices);
|
|
return Geometry::convex_hull(vertices_2d);
|
|
}
|
|
|
|
void CameraUtils::ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction) {
|
|
switch (camera.get_type()) {
|
|
case Camera::EType::Ortho: return ray_from_ortho_screen_pos(camera, position, point, direction);
|
|
case Camera::EType::Perspective: return ray_from_persp_screen_pos(camera, position, point, direction);
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
Vec3d CameraUtils::screen_point(const Camera &camera, const Vec2d &position)
|
|
{
|
|
double height = camera.get_viewport().data()[3];
|
|
// Y coordinate has opposit direction
|
|
return Vec3d(position.x(), height - position.y(), 0.);
|
|
}
|
|
|
|
void CameraUtils::ray_from_ortho_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
|
{
|
|
assert(camera.get_type() == Camera::EType::Ortho);
|
|
Matrix4d modelview = camera.get_view_matrix().matrix();
|
|
Matrix4d projection = camera.get_projection_matrix().matrix();
|
|
Vec4i32 viewport(camera.get_viewport().data());
|
|
igl::unproject(screen_point(camera,position), modelview, projection, viewport, point);
|
|
direction = camera.get_dir_forward();
|
|
}
|
|
void CameraUtils::ray_from_persp_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
|
|
{
|
|
assert(camera.get_type() == Camera::EType::Perspective);
|
|
Matrix4d modelview = camera.get_view_matrix().matrix();
|
|
Matrix4d projection = camera.get_projection_matrix().matrix();
|
|
Vec4i32 viewport(camera.get_viewport().data());
|
|
igl::unproject(screen_point(camera, position), modelview, projection, viewport, point);
|
|
direction = point - camera.get_position();
|
|
}
|
|
|
|
Vec2d CameraUtils::get_z0_position(const Camera &camera, const Vec2d & coor)
|
|
{
|
|
Vec3d p0, dir;
|
|
ray_from_screen_pos(camera, coor, p0, dir);
|
|
|
|
// is approx zero
|
|
if ((fabs(dir.z()) - 1e-4) < 0)
|
|
return Vec2d(std::numeric_limits<double>::max(),
|
|
std::numeric_limits<double>::max());
|
|
|
|
// find position of ray cross plane(z = 0)
|
|
double t = p0.z() / dir.z();
|
|
Vec3d p = p0 - t * dir;
|
|
return Vec2d(p.x(), p.y());
|
|
}
|