mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-15 10:47:50 -06:00
Fixed automatic update of perspective camera
This commit is contained in:
parent
77df54947b
commit
8078e00c13
2 changed files with 76 additions and 68 deletions
|
@ -22,10 +22,10 @@ namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
const double Camera::DefaultDistance = 1000.0;
|
const double Camera::DefaultDistance = 1000.0;
|
||||||
double Camera::FrustrumMinZSize = 50.0;
|
double Camera::FrustrumMinZRange = 50.0;
|
||||||
|
double Camera::FrustrumMinNearZ = 100.0;
|
||||||
double Camera::FrustrumZMargin = 10.0;
|
double Camera::FrustrumZMargin = 10.0;
|
||||||
double Camera::FovMinDeg = 0.5;
|
double Camera::MaxFovDeg = 60.0;
|
||||||
double Camera::FovMaxDeg = 75.0;
|
|
||||||
|
|
||||||
Camera::Camera()
|
Camera::Camera()
|
||||||
: phi(45.0f)
|
: phi(45.0f)
|
||||||
|
@ -186,7 +186,8 @@ void Camera::apply_view_matrix() const
|
||||||
|
|
||||||
void Camera::apply_projection(const BoundingBoxf3& box) const
|
void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
m_distance = DefaultDistance;
|
set_distance(DefaultDistance);
|
||||||
|
|
||||||
double w = 0.0;
|
double w = 0.0;
|
||||||
double h = 0.0;
|
double h = 0.0;
|
||||||
|
|
||||||
|
@ -194,15 +195,14 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
||||||
|
|
||||||
w = (double)m_viewport[2];
|
w = 0.5 * (double)m_viewport[2];
|
||||||
h = (double)m_viewport[3];
|
h = 0.5 * (double)m_viewport[3];
|
||||||
|
|
||||||
double two_zoom = 2.0 * m_zoom;
|
if (m_zoom != 0.0)
|
||||||
if (two_zoom != 0.0)
|
|
||||||
{
|
{
|
||||||
double inv_two_zoom = 1.0 / two_zoom;
|
double inv_zoom = 1.0 / m_zoom;
|
||||||
w *= inv_two_zoom;
|
w *= inv_zoom;
|
||||||
h *= inv_two_zoom;
|
h *= inv_zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
|
@ -226,21 +226,16 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
|
|
||||||
if (m_type == Perspective)
|
if (m_type == Perspective)
|
||||||
{
|
{
|
||||||
double fov_rad = 2.0 * std::atan(h / m_frustrum_zs.first);
|
double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first));
|
||||||
double fov_deg = Geometry::rad2deg(fov_rad);
|
|
||||||
|
|
||||||
// adjust camera distance to keep fov in a limited range
|
// adjust camera distance to keep fov in a limited range
|
||||||
if (fov_deg > FovMaxDeg + 0.001)
|
if (fov_deg > MaxFovDeg)
|
||||||
{
|
{
|
||||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMaxDeg));
|
double delta_z = h / ::tan(0.5 * Geometry::deg2rad(MaxFovDeg)) - m_frustrum_zs.first;
|
||||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
if (delta_z > 0.001)
|
||||||
apply_view_matrix();
|
set_distance(m_distance + delta_z);
|
||||||
}
|
else
|
||||||
else if (fov_deg < FovMinDeg - 0.001)
|
break;
|
||||||
{
|
|
||||||
double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMinDeg));
|
|
||||||
m_distance += (new_near_z - m_frustrum_zs.first);
|
|
||||||
apply_view_matrix();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -328,42 +323,50 @@ void Camera::debug_render() const
|
||||||
|
|
||||||
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
std::pair<double, double> ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
std::pair<double, double> ret;
|
||||||
|
|
||||||
Vec3d bb_min = box.min;
|
while (true)
|
||||||
Vec3d bb_max = box.max;
|
|
||||||
|
|
||||||
// box vertices in world space
|
|
||||||
std::vector<Vec3d> vertices;
|
|
||||||
vertices.reserve(8);
|
|
||||||
vertices.push_back(bb_min);
|
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
|
||||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
|
||||||
vertices.push_back(bb_max);
|
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
|
||||||
|
|
||||||
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
|
||||||
for (const Vec3d& v : vertices)
|
|
||||||
{
|
{
|
||||||
double z = -(m_view_matrix * v)(2);
|
ret = std::make_pair(DBL_MAX, -DBL_MAX);
|
||||||
ret.first = std::min(ret.first, z);
|
|
||||||
ret.second = std::max(ret.second, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply margin
|
// box vertices in world space
|
||||||
ret.first -= FrustrumZMargin;
|
std::vector<Vec3d> vertices;
|
||||||
ret.second += FrustrumZMargin;
|
vertices.reserve(8);
|
||||||
|
vertices.push_back(box.min);
|
||||||
|
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||||
|
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||||
|
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||||
|
vertices.push_back(box.max);
|
||||||
|
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||||
|
|
||||||
// ensure min size
|
// set the Z range in eye coordinates (negative Zs are in front of the camera)
|
||||||
if (ret.second - ret.first < FrustrumMinZSize)
|
for (const Vec3d& v : vertices)
|
||||||
{
|
{
|
||||||
double mid_z = 0.5 * (ret.first + ret.second);
|
double z = -(m_view_matrix * v)(2);
|
||||||
double half_size = 0.5 * FrustrumMinZSize;
|
ret.first = std::min(ret.first, z);
|
||||||
ret.first = mid_z - half_size;
|
ret.second = std::max(ret.second, z);
|
||||||
ret.second = mid_z + half_size;
|
}
|
||||||
|
|
||||||
|
// apply margin
|
||||||
|
ret.first -= FrustrumZMargin;
|
||||||
|
ret.second += FrustrumZMargin;
|
||||||
|
|
||||||
|
// ensure min size
|
||||||
|
if (ret.second - ret.first < FrustrumMinZRange)
|
||||||
|
{
|
||||||
|
double mid_z = 0.5 * (ret.first + ret.second);
|
||||||
|
double half_size = 0.5 * FrustrumMinZRange;
|
||||||
|
ret.first = mid_z - half_size;
|
||||||
|
ret.second = mid_z + half_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret.first >= FrustrumMinNearZ)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ensure min Near Z
|
||||||
|
set_distance(m_distance + FrustrumMinNearZ - ret.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -385,21 +388,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
Vec3d up = get_dir_up();
|
Vec3d up = get_dir_up();
|
||||||
Vec3d forward = get_dir_forward();
|
Vec3d forward = get_dir_forward();
|
||||||
|
|
||||||
Vec3d bb_min = box.min;
|
|
||||||
Vec3d bb_max = box.max;
|
|
||||||
Vec3d bb_center = box.center();
|
Vec3d bb_center = box.center();
|
||||||
|
|
||||||
// box vertices in world space
|
// box vertices in world space
|
||||||
std::vector<Vec3d> vertices;
|
std::vector<Vec3d> vertices;
|
||||||
vertices.reserve(8);
|
vertices.reserve(8);
|
||||||
vertices.push_back(bb_min);
|
vertices.push_back(box.min);
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2));
|
vertices.emplace_back(box.max(0), box.min(1), box.min(2));
|
||||||
vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2));
|
vertices.emplace_back(box.max(0), box.max(1), box.min(2));
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2));
|
vertices.emplace_back(box.min(0), box.max(1), box.min(2));
|
||||||
vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2));
|
vertices.emplace_back(box.min(0), box.min(1), box.max(2));
|
||||||
vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2));
|
vertices.emplace_back(box.max(0), box.min(1), box.max(2));
|
||||||
vertices.push_back(bb_max);
|
vertices.push_back(box.max);
|
||||||
vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2));
|
vertices.emplace_back(box.min(0), box.max(1), box.max(2));
|
||||||
|
|
||||||
double max_x = 0.0;
|
double max_x = 0.0;
|
||||||
double max_y = 0.0;
|
double max_y = 0.0;
|
||||||
|
@ -430,6 +431,12 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::set_distance(double distance) const
|
||||||
|
{
|
||||||
|
m_distance = distance;
|
||||||
|
apply_view_matrix();
|
||||||
|
}
|
||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ namespace GUI {
|
||||||
struct Camera
|
struct Camera
|
||||||
{
|
{
|
||||||
static const double DefaultDistance;
|
static const double DefaultDistance;
|
||||||
static double FrustrumMinZSize;
|
static double FrustrumMinZRange;
|
||||||
|
static double FrustrumMinNearZ;
|
||||||
static double FrustrumZMargin;
|
static double FrustrumZMargin;
|
||||||
static double FovMinDeg;
|
static double MaxFovDeg;
|
||||||
static double FovMaxDeg;
|
|
||||||
|
|
||||||
enum EType : unsigned char
|
enum EType : unsigned char
|
||||||
{
|
{
|
||||||
|
@ -101,6 +101,7 @@ private:
|
||||||
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
||||||
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
||||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
||||||
|
void set_distance(double distance) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue