diff options
author | Enrico Turri <enricoturri@seznam.cz> | 2019-06-14 11:38:09 +0300 |
---|---|---|
committer | Enrico Turri <enricoturri@seznam.cz> | 2019-06-14 11:38:09 +0300 |
commit | 1a91add2e60f3a4d22cdd6c8a10e57dc8095e0a2 (patch) | |
tree | 711eca9fdaeb3e304ba91667f00eaad21bab61a3 /src/slic3r/GUI/Camera.cpp | |
parent | a99466ef1df99d52277a5f78a4fbb5481d2dd584 (diff) |
Tighter camera frustrum to reduce z-fighting
Diffstat (limited to 'src/slic3r/GUI/Camera.cpp')
-rw-r--r-- | src/slic3r/GUI/Camera.cpp | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 5aa881e3e..1fc2f6be3 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -23,6 +23,8 @@ namespace Slic3r { namespace GUI { const float Camera::DefaultDistance = 1000.0f; +double Camera::FrustrumMinZSize = 50.0; +double Camera::FrustrumZMargin = 10.0; Camera::Camera() : type(Ortho) @@ -127,6 +129,8 @@ void Camera::apply_view_matrix() const void Camera::apply_projection(const BoundingBoxf3& box) const { + m_frustrum_zs = calc_tight_frustrum_zs_around(box); + switch (type) { case Ortho: @@ -141,10 +145,7 @@ void Camera::apply_projection(const BoundingBoxf3& box) const h2 *= inv_two_zoom; } - // FIXME: calculate a tighter value for depth will improve z-fighting - // Set at least some minimum depth in case the bounding box is empty to avoid an OpenGL driver error. - double depth = std::max(1.0, 5.0 * box.max_size()); - apply_ortho_projection(-w2, w2, -h2, h2, (double)distance - depth, (double)distance + depth); + apply_ortho_projection(-w2, w2, -h2, h2, m_frustrum_zs.first, m_frustrum_zs.second); break; } // case Perspective: @@ -166,6 +167,8 @@ void Camera::debug_render() const Vec3f forward = get_dir_forward().cast<float>(); Vec3f right = get_dir_right().cast<float>(); Vec3f up = get_dir_up().cast<float>(); + float nearZ = (float)m_frustrum_zs.first; + float farZ = (float)m_frustrum_zs.second; ImGui::InputText("Type", const_cast<char*>(type.data()), type.length(), ImGuiInputTextFlags_ReadOnly); ImGui::Separator(); @@ -175,6 +178,9 @@ void Camera::debug_render() const ImGui::InputFloat3("Forward", forward.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat3("Right", right.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat3("Up", up.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); + ImGui::Separator(); + ImGui::InputFloat("Near Z", &nearZ, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly); + ImGui::InputFloat("Far Z", &farZ, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly); imgui.end(); } #endif // ENABLE_CAMERA_STATISTICS @@ -190,6 +196,47 @@ void Camera::apply_ortho_projection(double x_min, double x_max, double y_min, do glsafe(::glMatrixMode(GL_MODELVIEW)); } +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); + + Vec3d bb_min = box.min; + Vec3d bb_max = box.max; + + // bbox 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 (only negative Zs are in front of the camera) + for (const Vec3d& v : vertices) + { + // ensure non-negative values + double z = std::max(-(m_view_matrix * v)(2), 0.0); + ret.first = std::min(ret.first, z); + ret.second = std::max(ret.second, z); + } + + // apply margin + ret.first -= FrustrumZMargin; + ret.second += FrustrumZMargin; + + // ensure min size + if (ret.second - ret.first < FrustrumMinZSize) + ret.second = ret.first + FrustrumMinZSize; + + assert(ret.first > 0.0); + + return ret; +} + } // GUI } // Slic3r |