ENH:enhance render performance
jira: none Change-Id: I23ba97d0a00752a131b719436bd062cd0b79e9d2
This commit is contained in:
parent
072f4ed43e
commit
4bf4e1bb91
|
@ -10970,7 +10970,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||||
|
|
||||||
// Basic info
|
// Basic info
|
||||||
Text("Dear ImGui %s", GetVersion());
|
Text("Dear ImGui %s", GetVersion());
|
||||||
Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
//Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||||
Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
|
Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
|
||||||
Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
|
Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
|
||||||
Text("%d active allocations", io.MetricsActiveAllocations);
|
Text("%d active allocations", io.MetricsActiveAllocations);
|
||||||
|
|
|
@ -172,6 +172,8 @@ void AppConfig::set_defaults()
|
||||||
|
|
||||||
if (get("zoom_to_mouse").empty())
|
if (get("zoom_to_mouse").empty())
|
||||||
set_bool("zoom_to_mouse", false);
|
set_bool("zoom_to_mouse", false);
|
||||||
|
if (get("enable_lod").empty())
|
||||||
|
set_bool("enable_lod", true);
|
||||||
if (get("user_bed_type").empty())
|
if (get("user_bed_type").empty())
|
||||||
set_bool("user_bed_type", true);
|
set_bool("user_bed_type", true);
|
||||||
if (get("grabber_size_factor").empty())
|
if (get("grabber_size_factor").empty())
|
||||||
|
@ -306,7 +308,7 @@ void AppConfig::set_defaults()
|
||||||
if (get("mouse_wheel").empty()) {
|
if (get("mouse_wheel").empty()) {
|
||||||
set("mouse_wheel", "0");
|
set("mouse_wheel", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get("max_recent_count").empty()) {
|
if (get("max_recent_count").empty()) {
|
||||||
set("max_recent_count", "18");
|
set("max_recent_count", "18");
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,8 @@ set(lisbslic3r_sources
|
||||||
Fill/FillRectilinear.hpp
|
Fill/FillRectilinear.hpp
|
||||||
Flow.cpp
|
Flow.cpp
|
||||||
Flow.hpp
|
Flow.hpp
|
||||||
|
Frustum.cpp
|
||||||
|
Frustum.hpp
|
||||||
FlushVolCalc.cpp
|
FlushVolCalc.cpp
|
||||||
FlushVolCalc.hpp
|
FlushVolCalc.hpp
|
||||||
format.hpp
|
format.hpp
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "Frustum.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
namespace Slic3r {
|
||||||
|
Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const BoundingBoxf3 &box) const
|
||||||
|
{
|
||||||
|
Vec3f center = ((box.min + box.max) * 0.5f).cast<float>();
|
||||||
|
Vec3f extent = ((box.max - box.min) * 0.5f).cast<float>();
|
||||||
|
float d = distance(center);
|
||||||
|
float r = fabsf(extent.x() * normal_.x()) + fabsf(extent.y() * normal_.y()) + fabsf(extent.z() * normal_.z());
|
||||||
|
if (d == r) {
|
||||||
|
return Plane::Intersects_Tangent;
|
||||||
|
} else if (std::abs(d) < r) {
|
||||||
|
return Plane::Intersects_Cross;
|
||||||
|
}
|
||||||
|
return (d > 0.0f) ? Plane::Intersects_Front : Plane::Intersects_Back;
|
||||||
|
}
|
||||||
|
Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const Vec3f &p0) const
|
||||||
|
{
|
||||||
|
float d = distance(p0);
|
||||||
|
if (d == 0) {
|
||||||
|
return Plane::Intersects_Tangent;
|
||||||
|
}
|
||||||
|
return (d > 0.0f) ? Plane::Intersects_Front : Plane::Intersects_Back;
|
||||||
|
}
|
||||||
|
Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const Vec3f &p0, const Vec3f &p1) const
|
||||||
|
{
|
||||||
|
Plane::PlaneIntersects state0 = intersects(p0);
|
||||||
|
Plane::PlaneIntersects state1 = intersects(p1);
|
||||||
|
if (state0 == state1) {
|
||||||
|
return state0;
|
||||||
|
}
|
||||||
|
if (state0 == Plane::Intersects_Tangent || state1 == Plane::Intersects_Tangent) {
|
||||||
|
return Plane::Intersects_Tangent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plane::Intersects_Cross;
|
||||||
|
}
|
||||||
|
Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const
|
||||||
|
{
|
||||||
|
Plane::PlaneIntersects state0 = intersects(p0, p1);
|
||||||
|
Plane::PlaneIntersects state1 = intersects(p0, p2);
|
||||||
|
Plane::PlaneIntersects state2 = intersects(p1, p2);
|
||||||
|
|
||||||
|
if (state0 == state1 && state0 == state2) {
|
||||||
|
return state0; }
|
||||||
|
|
||||||
|
if (state0 == Plane::Intersects_Cross || state1 == Plane::Intersects_Cross || state2 == Plane::Intersects_Cross) {
|
||||||
|
return Plane::Intersects_Cross;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plane::Intersects_Tangent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::intersects(const BoundingBoxf3 &box) const {
|
||||||
|
for (auto &plane : planes) {
|
||||||
|
if (plane.intersects(box) == Plane::Intersects_Back) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check box intersects
|
||||||
|
if (!bbox.intersects(box)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::intersects(const Vec3f &p0) const {
|
||||||
|
for (auto &plane : planes) {
|
||||||
|
if (plane.intersects(p0) == Plane::Intersects_Back) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::intersects(const Vec3f &p0, const Vec3f &p1) const
|
||||||
|
{
|
||||||
|
for (auto &plane : planes) {
|
||||||
|
if (plane.intersects(p0, p1) == Plane::Intersects_Back) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const
|
||||||
|
{
|
||||||
|
for (auto &plane : planes) {
|
||||||
|
if (plane.intersects(p0, p1, p2) == Plane::Intersects_Back) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef slic3r_Frustum_hpp_
|
||||||
|
#define slic3r_Frustum_hpp_
|
||||||
|
|
||||||
|
#include "Point.hpp"
|
||||||
|
#include "BoundingBox.hpp"
|
||||||
|
namespace Slic3r {
|
||||||
|
class Frustum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Frustum()=default;
|
||||||
|
~Frustum() = default;
|
||||||
|
|
||||||
|
class Plane {
|
||||||
|
public:
|
||||||
|
enum PlaneIntersects { Intersects_Cross = 0, Intersects_Tangent = 1, Intersects_Front = 2, Intersects_Back = 3 };
|
||||||
|
void set(const Vec3f &n, const Vec3f &pt)
|
||||||
|
{
|
||||||
|
normal_ = n.normalized();
|
||||||
|
center_ = pt;
|
||||||
|
d_ = -normal_.dot(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
float distance(const Vec3f &pt) const { return normal_.dot(pt) + d_; }
|
||||||
|
|
||||||
|
inline const Vec3f &getNormal() const { return normal_; }
|
||||||
|
|
||||||
|
Plane::PlaneIntersects intersects(const BoundingBoxf3 &box) const;
|
||||||
|
//// check intersect with point (world space)
|
||||||
|
Plane::PlaneIntersects intersects(const Vec3f &p0) const;
|
||||||
|
// check intersect with line segment (world space)
|
||||||
|
Plane::PlaneIntersects intersects(const Vec3f &p0, const Vec3f &p1) const;
|
||||||
|
// check intersect with triangle (world space)
|
||||||
|
Plane::PlaneIntersects intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const;
|
||||||
|
private:
|
||||||
|
Vec3f normal_;
|
||||||
|
Vec3f center_;
|
||||||
|
float d_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool intersects(const BoundingBoxf3 &box) const;
|
||||||
|
// check intersect with point (world space)
|
||||||
|
bool intersects(const Vec3f &p0) const;
|
||||||
|
// check intersect with line segment (world space)
|
||||||
|
bool intersects(const Vec3f &p0, const Vec3f &p1) const;
|
||||||
|
// check intersect with triangle (world space)
|
||||||
|
bool intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const;
|
||||||
|
|
||||||
|
Plane planes[6];
|
||||||
|
/* corners[0]: nearTopLeft;
|
||||||
|
* corners[1]: nearTopRight;
|
||||||
|
* corners[2]: nearBottomLeft;
|
||||||
|
* corners[3]: nearBottomRight;
|
||||||
|
* corners[4]: farTopLeft;
|
||||||
|
* corners[5]: farTopRight;
|
||||||
|
* corners[6]: farBottomLeft;
|
||||||
|
* corners[7]: farBottomRight;
|
||||||
|
*/
|
||||||
|
Vec3f corners[8];
|
||||||
|
|
||||||
|
BoundingBoxf3 bbox;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FrustumClipMask {
|
||||||
|
POSITIVE_X = 1 << 0,
|
||||||
|
NEGATIVE_X = 1 << 1,
|
||||||
|
POSITIVE_Y = 1 << 2,
|
||||||
|
NEGATIVE_Y = 1 << 3,
|
||||||
|
POSITIVE_Z = 1 << 4,
|
||||||
|
NEGATIVE_Z = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const int FrustumClipMaskArray[6] = {
|
||||||
|
FrustumClipMask::POSITIVE_X, FrustumClipMask::NEGATIVE_X, FrustumClipMask::POSITIVE_Y, FrustumClipMask::NEGATIVE_Y, FrustumClipMask::POSITIVE_Z, FrustumClipMask::NEGATIVE_Z,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Vec4f FrustumClipPlane[6] = {{-1, 0, 0, 1}, {1, 0, 0, 1}, {0, -1, 0, 1}, {0, 1, 0, 1}, {0, 0, -1, 1}, {0, 0, 1, 1}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,6 +10,7 @@
|
||||||
#include "GLShader.hpp"
|
#include "GLShader.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "GUI_Colors.hpp"
|
#include "GUI_Colors.hpp"
|
||||||
|
//#include "Camera.hpp"
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "BitmapCache.hpp"
|
#include "BitmapCache.hpp"
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
#include "libslic3r/Tesselate.hpp"
|
#include "libslic3r/Tesselate.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
#include "libslic3r/QuadricEdgeCollapse.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -415,6 +417,45 @@ std::array<std::array<float, 4>, 5> GLVolume::MODEL_COLOR = { {
|
||||||
{ 1.0f, 1.0f, 0.0f, 1.f }
|
{ 1.0f, 1.0f, 0.0f, 1.f }
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
float GLVolume::LOD_HIGH_ZOOM = 3.5f;
|
||||||
|
float GLVolume::LOD_MIDDLE_ZOOM = 2.8f;
|
||||||
|
float GLVolume::LOD_SMALL_ZOOM = 1.4f;
|
||||||
|
float GLVolume::LAST_CAMERA_ZOOM_VALUE = 0.0f;
|
||||||
|
const float ZOOM_THRESHOLD = 0.3f;
|
||||||
|
const unsigned char LOD_UPDATE_FREQUENCY = 20;
|
||||||
|
const Vec2i LOD_SCREEN_MIN = Vec2i(45, 35);
|
||||||
|
const Vec2i LOD_SCREEN_MAX = Vec2i(70, 55);
|
||||||
|
|
||||||
|
Vec2f calc_pt_in_screen(const Vec3d &pt, const Transform3d &world_tran, const Matrix4d &view_proj_mat, int window_width, int window_height)
|
||||||
|
{
|
||||||
|
auto tran = (view_proj_mat * world_tran);
|
||||||
|
Vec4d temp_center(pt.x(), pt.y(), pt.z(), 1.0);
|
||||||
|
Vec4d temp_ndc = tran * temp_center;
|
||||||
|
Vec3d screen_box_center = Vec3d(temp_ndc.x(), temp_ndc.y(), temp_ndc.z()) / temp_ndc.w();
|
||||||
|
|
||||||
|
float x = 0.5f * (1 + screen_box_center(0)) * window_width;
|
||||||
|
float y = 0.5f * (1 - screen_box_center(1)) * window_height;
|
||||||
|
return Vec2f(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOD_LEVEL calc_volume_box_in_screen_bigger_than_threshold(
|
||||||
|
const BoundingBoxf3 &v_box, const Transform3d &world_tran, const Matrix4d &view_proj_mat,
|
||||||
|
int window_width, int window_height)
|
||||||
|
{
|
||||||
|
auto s_min = calc_pt_in_screen(v_box.min, world_tran, view_proj_mat, window_width, window_height);
|
||||||
|
auto s_max = calc_pt_in_screen(v_box.max, world_tran, view_proj_mat, window_width, window_height);
|
||||||
|
auto size_x = abs(s_max.x() - s_min.x());
|
||||||
|
auto size_y = abs(s_max.y() - s_min.y());
|
||||||
|
if (size_x >= LOD_SCREEN_MAX.x() || size_y >= LOD_SCREEN_MAX.y()) {
|
||||||
|
return LOD_LEVEL::HIGH;
|
||||||
|
}
|
||||||
|
if (size_x <= LOD_SCREEN_MIN.x() && size_y <= LOD_SCREEN_MIN.y()) {
|
||||||
|
return LOD_LEVEL::SMALL;
|
||||||
|
} else {
|
||||||
|
return LOD_LEVEL::MIDDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLVolume::update_render_colors()
|
void GLVolume::update_render_colors()
|
||||||
{
|
{
|
||||||
GLVolume::DISABLED_COLOR = GLColor(RenderColor::colors[RenderCol_Model_Disable]);
|
GLVolume::DISABLED_COLOR = GLColor(RenderColor::colors[RenderCol_Model_Disable]);
|
||||||
|
@ -463,6 +504,8 @@ GLVolume::GLVolume(float r, float g, float b, float a, bool create_index_data)
|
||||||
, force_sinking_contours(false)
|
, force_sinking_contours(false)
|
||||||
, tverts_range(0, size_t(-1))
|
, tverts_range(0, size_t(-1))
|
||||||
, qverts_range(0, size_t(-1))
|
, qverts_range(0, size_t(-1))
|
||||||
|
, tverts_range_lod(0, size_t(-1))
|
||||||
|
, qverts_range_lod(0, size_t(-1))
|
||||||
{
|
{
|
||||||
color = { r, g, b, a };
|
color = { r, g, b, a };
|
||||||
set_render_color(color);
|
set_render_color(color);
|
||||||
|
@ -580,6 +623,91 @@ std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume)
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLVolume::simplify_mesh(const TriangleMesh &mesh, GLIndexedVertexArray &va, LOD_LEVEL lod) const
|
||||||
|
{
|
||||||
|
return simplify_mesh(mesh.its,va,lod);
|
||||||
|
}
|
||||||
|
#define SUPER_LARGE_FACES 500000
|
||||||
|
#define LARGE_FACES 100000
|
||||||
|
bool GLVolume::simplify_mesh(const indexed_triangle_set &_its, GLIndexedVertexArray &va, LOD_LEVEL lod) const
|
||||||
|
{
|
||||||
|
if (_its.indices.size() == 0 || _its.vertices.size() == 0) { return false; }
|
||||||
|
bool enable_lod = GUI::wxGetApp().app_config->get("enable_lod") == "true";
|
||||||
|
if (!enable_lod) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto its = std::make_unique<indexed_triangle_set>(_its);
|
||||||
|
auto m_state = std::make_unique<State>();
|
||||||
|
if (lod == LOD_LEVEL::MIDDLE) {
|
||||||
|
m_state->config.max_error = 0.5f;
|
||||||
|
if (_its.indices.size() > SUPER_LARGE_FACES) {
|
||||||
|
m_state->config.max_error = 0.4f;
|
||||||
|
} else if (_its.indices.size() > LARGE_FACES) {
|
||||||
|
m_state->config.max_error = 0.3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lod == LOD_LEVEL::SMALL) {
|
||||||
|
m_state->config.max_error = 0.1f;
|
||||||
|
if (_its.indices.size() > SUPER_LARGE_FACES) {
|
||||||
|
m_state->config.max_error = 0.08f;
|
||||||
|
} else if (_its.indices.size() > LARGE_FACES) {
|
||||||
|
m_state->config.max_error = 0.05f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//std::mutex m_state_mutex;
|
||||||
|
std::thread m_worker = std::thread(
|
||||||
|
[&va](std::unique_ptr<indexed_triangle_set> its, std::unique_ptr<State> state) {
|
||||||
|
// Checks that the UI thread did not request cancellation, throws if so.
|
||||||
|
std::function<void(void)> throw_on_cancel = []() {
|
||||||
|
};
|
||||||
|
std::function<void(int)> statusfn = [&state](int percent) {
|
||||||
|
state->progress = percent;
|
||||||
|
};
|
||||||
|
// Initialize.
|
||||||
|
uint32_t triangle_count = 0;
|
||||||
|
float max_error = std::numeric_limits<float>::max();
|
||||||
|
{
|
||||||
|
if (state->config.use_count)
|
||||||
|
triangle_count = state->config.wanted_count;
|
||||||
|
if (!state->config.use_count)
|
||||||
|
max_error = state->config.max_error;
|
||||||
|
state->progress = 0;
|
||||||
|
state->result.reset();
|
||||||
|
state->status = State::Status::running;
|
||||||
|
}
|
||||||
|
TriangleMesh origin_mesh(*its);
|
||||||
|
try { // Start the actual calculation.
|
||||||
|
its_quadric_edge_collapse(*its, triangle_count, &max_error, throw_on_cancel, statusfn);
|
||||||
|
} catch (std::exception&) {
|
||||||
|
state->status = State::idle;
|
||||||
|
}
|
||||||
|
if (state->status == State::Status::running) {
|
||||||
|
// We were not cancelled, the result is valid.
|
||||||
|
state->status = State::Status::idle;
|
||||||
|
state->result = std::move(its);
|
||||||
|
}
|
||||||
|
if (state->result) {
|
||||||
|
TriangleMesh mesh(*state->result);
|
||||||
|
float eps = 1.0f;
|
||||||
|
Vec3f origin_min = origin_mesh.stats().min - Vec3f(eps, eps, eps);
|
||||||
|
Vec3f origin_max = origin_mesh.stats().max + Vec3f(eps, eps, eps);
|
||||||
|
if (origin_min.x() < mesh.stats().min.x() && origin_min.y() < mesh.stats().min.y() && origin_min.z() < mesh.stats().min.z()&&
|
||||||
|
origin_max.x() > mesh.stats().max.x() && origin_max.y() > mesh.stats().max.y() && origin_max.z() > mesh.stats().max.z()) {
|
||||||
|
va.load_mesh(mesh);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state->status = State::cancelling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
std::move(its),std::move(m_state));
|
||||||
|
if (m_worker.joinable()) {
|
||||||
|
m_worker.detach();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Transform3d GLVolume::world_matrix() const
|
Transform3d GLVolume::world_matrix() const
|
||||||
{
|
{
|
||||||
Transform3d m = m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix();
|
Transform3d m = m_instance_transformation.get_matrix() * m_volume_transformation.get_matrix();
|
||||||
|
@ -687,7 +815,11 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
glsafe(::glCullFace(GL_BACK));
|
glsafe(::glCullFace(GL_BACK));
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
|
auto camera = GUI::wxGetApp().plater()->get_camera();
|
||||||
|
auto zoom = camera.get_zoom();
|
||||||
|
Transform3d vier_mat = camera.get_view_matrix();
|
||||||
|
Matrix4d vier_proj_mat = camera.get_projection_matrix().matrix() * vier_mat.matrix();
|
||||||
|
const std::array<int, 4> &viewport = camera.get_viewport();
|
||||||
// BBS: add logic for mmu segmentation rendering
|
// BBS: add logic for mmu segmentation rendering
|
||||||
auto render_body = [&]() {
|
auto render_body = [&]() {
|
||||||
bool color_volume = false;
|
bool color_volume = false;
|
||||||
|
@ -716,7 +848,6 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]);
|
mmuseg_ivas[idx].load_its_flat_shading(its_per_color[idx]);
|
||||||
mmuseg_ivas[idx].finalize_geometry(true);
|
mmuseg_ivas[idx].finalize_geometry(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mmuseg_ts = mv->mmu_segmentation_facets.timestamp();
|
mmuseg_ts = mv->mmu_segmentation_facets.timestamp();
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, new mmuseg_ts %3%, new color size %4%")
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, new mmuseg_ts %3%, new color size %4%")
|
||||||
%this %this->name %mmuseg_ts %mmuseg_ivas.size();
|
%this %this->name %mmuseg_ts %mmuseg_ivas.size();
|
||||||
|
@ -734,8 +865,8 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
}
|
}
|
||||||
glsafe(::glMultMatrixd(world_matrix().data()));
|
glsafe(::glMultMatrixd(world_matrix().data()));
|
||||||
for (int idx = 0; idx < mmuseg_ivas.size(); idx++) {
|
for (int idx = 0; idx < mmuseg_ivas.size(); idx++) {
|
||||||
GLIndexedVertexArray& iva = mmuseg_ivas[idx];
|
GLIndexedVertexArray* iva = &mmuseg_ivas[idx];
|
||||||
if (iva.triangle_indices_size == 0 && iva.quad_indices_size == 0)
|
if (iva->triangle_indices_size == 0 && iva->quad_indices_size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (shader) {
|
if (shader) {
|
||||||
|
@ -763,7 +894,7 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iva.render(this->tverts_range, this->qverts_range);
|
iva->render(this->tverts_range, this->qverts_range);
|
||||||
/*if (force_native_color && (render_color[3] < 1.0)) {
|
/*if (force_native_color && (render_color[3] < 1.0)) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}")
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}")
|
||||||
%this %this->name %this->tverts_range.first %this->tverts_range.second
|
%this %this->name %this->tverts_range.first %this->tverts_range.second
|
||||||
|
@ -773,7 +904,32 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
glsafe(::glMultMatrixd(world_matrix().data()));
|
glsafe(::glMultMatrixd(world_matrix().data()));
|
||||||
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
auto render_which = [this](std::shared_ptr<GLIndexedVertexArray> cur) {
|
||||||
|
if (cur->vertices_and_normals_interleaved_VBO_id > 0) {
|
||||||
|
cur->render(tverts_range_lod, qverts_range_lod);
|
||||||
|
} else {// if (cur->vertices_and_normals_interleaved_VBO_id == 0)
|
||||||
|
if (cur->triangle_indices.size() > 0) {
|
||||||
|
cur->finalize_geometry(true);
|
||||||
|
cur->render(tverts_range_lod, qverts_range_lod);
|
||||||
|
} else {
|
||||||
|
indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Transform3d world_tran = world_matrix();
|
||||||
|
m_lod_update_index++;
|
||||||
|
if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY){
|
||||||
|
m_lod_update_index = 0;
|
||||||
|
LAST_CAMERA_ZOOM_VALUE = zoom;
|
||||||
|
m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(bounding_box(), world_tran, vier_proj_mat, viewport[2], viewport[3]);
|
||||||
|
}
|
||||||
|
if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small) {
|
||||||
|
render_which(indexed_vertex_array_small);
|
||||||
|
} else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle) {
|
||||||
|
render_which(indexed_vertex_array_middle);
|
||||||
|
} else {
|
||||||
|
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -887,9 +1043,22 @@ void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color)
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
|
|
||||||
Transform3d matrix = world_matrix();
|
Transform3d matrix = world_matrix();
|
||||||
|
Transform3d world_tran = matrix;
|
||||||
matrix.scale(scale);
|
matrix.scale(scale);
|
||||||
glsafe(::glMultMatrixd(matrix.data()));
|
glsafe(::glMultMatrixd(matrix.data()));
|
||||||
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
m_lod_update_index++;
|
||||||
|
if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY) {
|
||||||
|
m_lod_update_index = 0;
|
||||||
|
LAST_CAMERA_ZOOM_VALUE = zoom;
|
||||||
|
m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(bounding_box(), world_tran, vier_proj_mat, viewport[2], viewport[3]);
|
||||||
|
}
|
||||||
|
if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small && indexed_vertex_array_small->vertices_and_normals_interleaved_VBO_id > 0) {
|
||||||
|
this->indexed_vertex_array_small->render(this->tverts_range_lod, this->qverts_range_lod);
|
||||||
|
} else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle && indexed_vertex_array_middle->vertices_and_normals_interleaved_VBO_id > 0) {
|
||||||
|
this->indexed_vertex_array_middle->render(this->tverts_range_lod, this->qverts_range_lod);
|
||||||
|
} else {
|
||||||
|
this->indexed_vertex_array->render(this->tverts_range, this->qverts_range);
|
||||||
|
}
|
||||||
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name();
|
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name();
|
||||||
shader->set_uniform("is_outline", false);
|
shader->set_uniform("is_outline", false);
|
||||||
|
|
||||||
|
@ -998,6 +1167,14 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj
|
||||||
glFrontFace(GL_CCW);
|
glFrontFace(GL_CCW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLVolume::set_bounding_boxes_as_dirty()
|
||||||
|
{
|
||||||
|
m_lod_update_index = LOD_UPDATE_FREQUENCY;
|
||||||
|
m_transformed_bounding_box.reset();
|
||||||
|
m_transformed_convex_hull_bounding_box.reset();
|
||||||
|
m_transformed_non_sinking_bounding_box.reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); }
|
bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); }
|
||||||
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposPad); }
|
bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposPad); }
|
||||||
|
|
||||||
|
@ -1112,6 +1289,8 @@ int GLVolumeCollection::load_object_volume(
|
||||||
else {
|
else {
|
||||||
GLVolume* first_volume = *(volume_set.begin());
|
GLVolume* first_volume = *(volume_set.begin());
|
||||||
new_volume->indexed_vertex_array = first_volume->indexed_vertex_array;
|
new_volume->indexed_vertex_array = first_volume->indexed_vertex_array;
|
||||||
|
new_volume->indexed_vertex_array_middle = first_volume->indexed_vertex_array_middle;
|
||||||
|
new_volume->indexed_vertex_array_small = first_volume->indexed_vertex_array_small;
|
||||||
need_create_mesh = false;
|
need_create_mesh = false;
|
||||||
}
|
}
|
||||||
volume_set.emplace(new_volume);
|
volume_set.emplace(new_volume);
|
||||||
|
@ -1127,6 +1306,10 @@ int GLVolumeCollection::load_object_volume(
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
v.indexed_vertex_array->load_mesh(mesh, true);
|
v.indexed_vertex_array->load_mesh(mesh, true);
|
||||||
#else
|
#else
|
||||||
|
if (v.indexed_vertex_array_middle == nullptr) { v.indexed_vertex_array_middle = std::make_shared<GLIndexedVertexArray>(); }
|
||||||
|
v.simplify_mesh(mesh, *v.indexed_vertex_array_middle, LOD_LEVEL::MIDDLE); // include finalize_geometry
|
||||||
|
if (v.indexed_vertex_array_small == nullptr) { v.indexed_vertex_array_small = std::make_shared<GLIndexedVertexArray>(); }
|
||||||
|
v.simplify_mesh(mesh, *v.indexed_vertex_array_small, LOD_LEVEL::SMALL);
|
||||||
v.indexed_vertex_array->load_mesh(mesh);
|
v.indexed_vertex_array->load_mesh(mesh);
|
||||||
#endif // ENABLE_SMOOTH_NORMALS
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
v.indexed_vertex_array->finalize_geometry(opengl_initialized);
|
v.indexed_vertex_array->finalize_geometry(opengl_initialized);
|
||||||
|
@ -1369,7 +1552,12 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||||
if (disable_cullface)
|
if (disable_cullface)
|
||||||
glsafe(::glDisable(GL_CULL_FACE));
|
glsafe(::glDisable(GL_CULL_FACE));
|
||||||
|
|
||||||
|
auto camera = GUI::wxGetApp().plater()->get_camera();
|
||||||
for (GLVolumeWithIdAndZ& volume : to_render) {
|
for (GLVolumeWithIdAndZ& volume : to_render) {
|
||||||
|
auto world_box = volume.first->transformed_bounding_box();
|
||||||
|
if (!camera.getFrustum().intersects(world_box)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
|
#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
|
||||||
if (type == ERenderType::Transparent) {
|
if (type == ERenderType::Transparent) {
|
||||||
volume.first->force_transparent = true;
|
volume.first->force_transparent = true;
|
||||||
|
|
|
@ -256,8 +256,20 @@ public:
|
||||||
private:
|
private:
|
||||||
BoundingBox m_bounding_box;
|
BoundingBox m_bounding_box;
|
||||||
};
|
};
|
||||||
|
enum LOD_LEVEL {
|
||||||
|
HIGH, // Origin data
|
||||||
|
MIDDLE,
|
||||||
|
SMALL,
|
||||||
|
};
|
||||||
|
|
||||||
class GLVolume {
|
class GLVolume {
|
||||||
|
static float LOD_HIGH_ZOOM;
|
||||||
|
static float LOD_MIDDLE_ZOOM;
|
||||||
|
static float LOD_SMALL_ZOOM;
|
||||||
|
static float LAST_CAMERA_ZOOM_VALUE;
|
||||||
|
mutable LOD_LEVEL m_cur_lod_level = LOD_LEVEL::HIGH;
|
||||||
|
mutable unsigned char m_lod_update_index = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
bool is_text_shape{false};
|
bool is_text_shape{false};
|
||||||
|
@ -292,6 +304,9 @@ public:
|
||||||
virtual ~GLVolume() = default;
|
virtual ~GLVolume() = default;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
|
bool simplify_mesh(const TriangleMesh &mesh, GLIndexedVertexArray &va, LOD_LEVEL lod) const;
|
||||||
|
bool simplify_mesh(const indexed_triangle_set &_its, GLIndexedVertexArray &va, LOD_LEVEL lod) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Geometry::Transformation m_instance_transformation;
|
Geometry::Transformation m_instance_transformation;
|
||||||
Geometry::Transformation m_volume_transformation;
|
Geometry::Transformation m_volume_transformation;
|
||||||
|
@ -327,6 +342,30 @@ protected:
|
||||||
|
|
||||||
SinkingContours m_sinking_contours;
|
SinkingContours m_sinking_contours;
|
||||||
|
|
||||||
|
// guards m_state
|
||||||
|
struct Configuration
|
||||||
|
{
|
||||||
|
bool use_count = false;//diff with glgizmoSimplify
|
||||||
|
float decimate_ratio = 50.f; // in percent
|
||||||
|
uint32_t wanted_count = 0; // initialize by percents
|
||||||
|
float max_error = 1.; // maximal quadric error
|
||||||
|
|
||||||
|
bool operator==(const Configuration &rhs)
|
||||||
|
{
|
||||||
|
return (use_count == rhs.use_count && decimate_ratio == rhs.decimate_ratio && wanted_count == rhs.wanted_count && max_error == rhs.max_error);
|
||||||
|
}
|
||||||
|
bool operator!=(const Configuration &rhs) { return !(*this == rhs); }
|
||||||
|
};
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
enum Status { idle, running, cancelling };
|
||||||
|
|
||||||
|
Status status = idle;
|
||||||
|
int progress = 0; // percent of done work
|
||||||
|
Configuration config; // Configuration we started with.
|
||||||
|
const ModelVolume * mv = nullptr;
|
||||||
|
std::unique_ptr<indexed_triangle_set> result;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
// Color of the triangles / quads held by this volume.
|
// Color of the triangles / quads held by this volume.
|
||||||
std::array<float, 4> color;
|
std::array<float, 4> color;
|
||||||
|
@ -400,7 +439,9 @@ public:
|
||||||
EHoverState hover;
|
EHoverState hover;
|
||||||
|
|
||||||
// Interleaved triangles & normals with indexed triangles & quads.
|
// Interleaved triangles & normals with indexed triangles & quads.
|
||||||
std::shared_ptr<GLIndexedVertexArray> indexed_vertex_array;
|
std::shared_ptr<GLIndexedVertexArray> indexed_vertex_array;
|
||||||
|
std::shared_ptr<GLIndexedVertexArray> indexed_vertex_array_middle;
|
||||||
|
std::shared_ptr<GLIndexedVertexArray> indexed_vertex_array_small;
|
||||||
const TriangleMesh * ori_mesh{nullptr};
|
const TriangleMesh * ori_mesh{nullptr};
|
||||||
// BBS
|
// BBS
|
||||||
mutable std::vector<GLIndexedVertexArray> mmuseg_ivas;
|
mutable std::vector<GLIndexedVertexArray> mmuseg_ivas;
|
||||||
|
@ -409,7 +450,8 @@ public:
|
||||||
// Ranges of triangle and quad indices to be rendered.
|
// Ranges of triangle and quad indices to be rendered.
|
||||||
std::pair<size_t, size_t> tverts_range;
|
std::pair<size_t, size_t> tverts_range;
|
||||||
std::pair<size_t, size_t> qverts_range;
|
std::pair<size_t, size_t> qverts_range;
|
||||||
|
std::pair<size_t, size_t> tverts_range_lod;
|
||||||
|
std::pair<size_t, size_t> qverts_range_lod;
|
||||||
// If the qverts or tverts contain thick extrusions, then offsets keeps pointers of the starts
|
// If the qverts or tverts contain thick extrusions, then offsets keeps pointers of the starts
|
||||||
// of the extrusions per layer.
|
// of the extrusions per layer.
|
||||||
std::vector<coordf_t> print_zs;
|
std::vector<coordf_t> print_zs;
|
||||||
|
@ -533,11 +575,7 @@ public:
|
||||||
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array->finalize_geometry(opengl_initialized); }
|
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array->finalize_geometry(opengl_initialized); }
|
||||||
void release_geometry() { this->indexed_vertex_array->release_geometry(); }
|
void release_geometry() { this->indexed_vertex_array->release_geometry(); }
|
||||||
|
|
||||||
void set_bounding_boxes_as_dirty() {
|
void set_bounding_boxes_as_dirty();
|
||||||
m_transformed_bounding_box.reset();
|
|
||||||
m_transformed_convex_hull_bounding_box.reset();
|
|
||||||
m_transformed_non_sinking_bounding_box.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_sla_support() const;
|
bool is_sla_support() const;
|
||||||
bool is_sla_pad() const;
|
bool is_sla_pad() const;
|
||||||
|
@ -573,6 +611,7 @@ typedef std::vector<GLVolume*> GLVolumePtrs;
|
||||||
typedef std::pair<GLVolume*, std::pair<unsigned int, double>> GLVolumeWithIdAndZ;
|
typedef std::pair<GLVolume*, std::pair<unsigned int, double>> GLVolumeWithIdAndZ;
|
||||||
typedef std::vector<GLVolumeWithIdAndZ> GLVolumeWithIdAndZList;
|
typedef std::vector<GLVolumeWithIdAndZ> GLVolumeWithIdAndZList;
|
||||||
|
|
||||||
|
|
||||||
class GLVolumeCollection
|
class GLVolumeCollection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -56,7 +56,7 @@ void Camera::select_next_type()
|
||||||
void Camera::translate(const Vec3d& displacement) {
|
void Camera::translate(const Vec3d& displacement) {
|
||||||
if (!displacement.isApprox(Vec3d::Zero())) {
|
if (!displacement.isApprox(Vec3d::Zero())) {
|
||||||
m_view_matrix.translate(-displacement);
|
m_view_matrix.translate(-displacement);
|
||||||
update_target();
|
update_target();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,104 @@ void Camera::select_view(const std::string& direction)
|
||||||
look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ());
|
look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//how to use
|
||||||
|
//BoundingBox bbox = mesh.aabb.transform(transform);
|
||||||
|
//return camera_->getFrustum().intersects(bbox);
|
||||||
|
void Camera::update_frustum()
|
||||||
|
{
|
||||||
|
auto eye_ = get_position().cast<float>();
|
||||||
|
auto center_ = get_target().cast<float>();
|
||||||
|
auto up_ = get_dir_up().cast<float>();
|
||||||
|
float near_ = m_frustrum_zs.first;
|
||||||
|
float far_ = m_frustrum_zs.second;
|
||||||
|
float aspect_ = m_viewport[2] / (double)m_viewport[3];
|
||||||
|
float fov_ = (float) Geometry::deg2rad(get_fov());
|
||||||
|
float eps = 0.01;
|
||||||
|
if (m_last_eye.isApprox(eye_) && m_last_center.isApprox(center_) && m_last_up.isApprox(up_) &&
|
||||||
|
abs(m_last_near - near_) > eps && abs(m_last_far - far_) > eps &&
|
||||||
|
abs(m_last_aspect - aspect_) > eps && abs(m_last_fov - fov_) > eps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_last_eye = eye_;
|
||||||
|
m_last_center = center_;
|
||||||
|
m_last_up = up_;
|
||||||
|
m_last_near = near_;
|
||||||
|
m_last_far = far_;
|
||||||
|
m_last_aspect = aspect_;
|
||||||
|
m_last_fov = fov_;
|
||||||
|
Vec3f forward((center_ - eye_).normalized());
|
||||||
|
Vec3f side((forward.cross(up_)).normalized());
|
||||||
|
Vec3f up((side.cross(forward)).normalized());
|
||||||
|
|
||||||
|
float nearHeightHalf = near_ * std::tan(fov_ / 2.f);
|
||||||
|
float farHeightHalf = far_ * std::tan(fov_ / 2.f);
|
||||||
|
float nearWidthHalf = nearHeightHalf * aspect_;
|
||||||
|
float farWidthHalf = farHeightHalf * aspect_;
|
||||||
|
|
||||||
|
// near plane
|
||||||
|
Vec3f nearCenter = eye_ + forward * near_;
|
||||||
|
Vec3f nearNormal = forward;
|
||||||
|
m_frustum.planes[0].set(nearNormal, nearCenter);
|
||||||
|
|
||||||
|
// far plane
|
||||||
|
Vec3f farCenter = eye_ + forward * far_;
|
||||||
|
Vec3f farNormal = -forward;
|
||||||
|
m_frustum.planes[1].set(farNormal, farCenter);
|
||||||
|
|
||||||
|
// top plane
|
||||||
|
Vec3f topCenter = nearCenter + up * nearHeightHalf;
|
||||||
|
Vec3f topNormal = (topCenter - eye_).normalized().cross(side);
|
||||||
|
m_frustum.planes[2].set(topNormal, topCenter);
|
||||||
|
|
||||||
|
// bottom plane
|
||||||
|
Vec3f bottomCenter = nearCenter - up * nearHeightHalf;
|
||||||
|
Vec3f bottomNormal = side.cross((bottomCenter - eye_).normalized());
|
||||||
|
m_frustum.planes[3].set(bottomNormal, bottomCenter);
|
||||||
|
|
||||||
|
// left plane
|
||||||
|
Vec3f leftCenter = nearCenter - side * nearWidthHalf;
|
||||||
|
Vec3f leftNormal = (leftCenter - eye_).normalized().cross(up);
|
||||||
|
m_frustum.planes[4].set(leftNormal, leftCenter);
|
||||||
|
|
||||||
|
// right plane
|
||||||
|
Vec3f rightCenter = nearCenter + side * nearWidthHalf;
|
||||||
|
Vec3f rightNormal = up.cross((rightCenter - eye_).normalized());
|
||||||
|
m_frustum.planes[5].set(rightNormal, rightCenter);
|
||||||
|
|
||||||
|
//// 8 corners
|
||||||
|
Vec3f nearTopLeft = nearCenter + up * nearHeightHalf - side * nearWidthHalf;
|
||||||
|
Vec3f nearTopRight = nearCenter + up * nearHeightHalf + side * nearWidthHalf;
|
||||||
|
Vec3f nearBottomLeft = nearCenter - up * nearHeightHalf - side * nearWidthHalf;
|
||||||
|
Vec3f nearBottomRight = nearCenter - up * nearHeightHalf + side * nearWidthHalf;
|
||||||
|
|
||||||
|
Vec3f farTopLeft = farCenter + up * farHeightHalf - side * farWidthHalf;
|
||||||
|
Vec3f farTopRight = farCenter + up * farHeightHalf + side * farWidthHalf;
|
||||||
|
Vec3f farBottomLeft = farCenter - up * farHeightHalf - side * farWidthHalf;
|
||||||
|
Vec3f farBottomRight = farCenter - up * farHeightHalf + side * farWidthHalf;
|
||||||
|
|
||||||
|
m_frustum.corners[0] = nearTopLeft;
|
||||||
|
m_frustum.corners[1] = nearTopRight;
|
||||||
|
m_frustum.corners[2] = nearBottomLeft;
|
||||||
|
m_frustum.corners[3] = nearBottomRight;
|
||||||
|
m_frustum.corners[4] = farTopLeft;
|
||||||
|
m_frustum.corners[5] = farTopRight;
|
||||||
|
m_frustum.corners[6] = farBottomLeft;
|
||||||
|
m_frustum.corners[7] = farBottomRight;
|
||||||
|
// bounding box
|
||||||
|
auto double_min = std::numeric_limits<double>::min();
|
||||||
|
auto double_max = std::numeric_limits<double>::max();
|
||||||
|
m_frustum.bbox.min = Vec3d(double_max, double_max, double_max);
|
||||||
|
m_frustum.bbox.max = Vec3d(double_min, double_min, double_min);
|
||||||
|
for (auto &corner : m_frustum.corners) {
|
||||||
|
m_frustum.bbox.min[0] = std::min((float)m_frustum.bbox.min.x(), corner.x());
|
||||||
|
m_frustum.bbox.min[1] = std::min((float)m_frustum.bbox.min.y(), corner.y());
|
||||||
|
m_frustum.bbox.min[2] = std::min((float)m_frustum.bbox.min.z(), corner.z());
|
||||||
|
|
||||||
|
m_frustum.bbox.max[0] = std::max((float)m_frustum.bbox.max.x(), corner.x());
|
||||||
|
m_frustum.bbox.max[1] = std::max((float)m_frustum.bbox.max.y(), corner.y());
|
||||||
|
m_frustum.bbox.max[2] = std::max((float)m_frustum.bbox.max.z(), corner.z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double Camera::get_fov() const
|
double Camera::get_fov() const
|
||||||
{
|
{
|
||||||
|
@ -220,7 +318,7 @@ void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_CAMERA_STATISTICS
|
#if ENABLE_CAMERA_STATISTICS
|
||||||
void Camera::debug_render() const
|
void Camera::debug_render()
|
||||||
{
|
{
|
||||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
imgui.begin(std::string("Camera statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
imgui.begin(std::string("Camera statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
@ -520,7 +618,7 @@ void Camera::set_distance(double distance)
|
||||||
if (m_distance != distance) {
|
if (m_distance != distance) {
|
||||||
m_view_matrix.translate((distance - m_distance) * get_dir_forward());
|
m_view_matrix.translate((distance - m_distance) * get_dir_forward());
|
||||||
m_distance = distance;
|
m_distance = distance;
|
||||||
|
|
||||||
update_target();
|
update_target();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,7 +724,7 @@ void Camera::update_target() {
|
||||||
Vec3d temptarget = get_position() + m_distance * get_dir_forward();
|
Vec3d temptarget = get_position() + m_distance * get_dir_forward();
|
||||||
if (!(temptarget-m_target).isApprox(Vec3d::Zero())){
|
if (!(temptarget-m_target).isApprox(Vec3d::Zero())){
|
||||||
m_target = temptarget;
|
m_target = temptarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define slic3r_Camera_hpp_
|
#define slic3r_Camera_hpp_
|
||||||
|
|
||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
|
#include "libslic3r/Frustum.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
@ -55,6 +56,9 @@ private:
|
||||||
std::pair<double, double> m_frustrum_zs;
|
std::pair<double, double> m_frustrum_zs;
|
||||||
|
|
||||||
BoundingBoxf3 m_scene_box;
|
BoundingBoxf3 m_scene_box;
|
||||||
|
Frustum m_frustum;
|
||||||
|
Vec3f m_last_eye, m_last_center, m_last_up;
|
||||||
|
float m_last_near, m_last_far, m_last_aspect, m_last_fov;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Camera() { set_default_orientation(); }
|
Camera() { set_default_orientation(); }
|
||||||
|
@ -69,7 +73,7 @@ public:
|
||||||
void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; }
|
void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; }
|
||||||
|
|
||||||
void translate(const Vec3d& displacement);
|
void translate(const Vec3d& displacement);
|
||||||
const Vec3d& get_target() {
|
const Vec3d& get_target() {
|
||||||
update_target();
|
update_target();
|
||||||
return m_target; }
|
return m_target; }
|
||||||
void set_target(const Vec3d& target);
|
void set_target(const Vec3d& target);
|
||||||
|
@ -100,9 +104,9 @@ public:
|
||||||
Vec3d get_dir_up() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(1); }
|
Vec3d get_dir_up() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(1); }
|
||||||
Vec3d get_dir_forward() const { return -m_view_matrix.matrix().block(0, 0, 3, 3).row(2); }
|
Vec3d get_dir_forward() const { return -m_view_matrix.matrix().block(0, 0, 3, 3).row(2); }
|
||||||
|
|
||||||
|
|
||||||
Vec3d get_position() const { return m_view_matrix.matrix().inverse().block(0, 3, 3, 1); }
|
Vec3d get_position() const { return m_view_matrix.matrix().inverse().block(0, 3, 3, 1); }
|
||||||
|
const Frustum & getFrustum() const { return m_frustum; }
|
||||||
|
void update_frustum();
|
||||||
double get_near_z() const { return m_frustrum_zs.first; }
|
double get_near_z() const { return m_frustrum_zs.first; }
|
||||||
double get_far_z() const { return m_frustrum_zs.second; }
|
double get_far_z() const { return m_frustrum_zs.second; }
|
||||||
const std::pair<double, double>& get_z_range() const { return m_frustrum_zs; }
|
const std::pair<double, double>& get_z_range() const { return m_frustrum_zs; }
|
||||||
|
@ -119,7 +123,7 @@ public:
|
||||||
void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
||||||
|
|
||||||
#if ENABLE_CAMERA_STATISTICS
|
#if ENABLE_CAMERA_STATISTICS
|
||||||
void debug_render() const;
|
void debug_render();
|
||||||
#endif // ENABLE_CAMERA_STATISTICS
|
#endif // ENABLE_CAMERA_STATISTICS
|
||||||
|
|
||||||
// translate the camera in world space
|
// translate the camera in world space
|
||||||
|
|
|
@ -1991,7 +1991,7 @@ void GLCanvas3D::render(bool only_init)
|
||||||
#if ENABLE_SHOW_CAMERA_TARGET
|
#if ENABLE_SHOW_CAMERA_TARGET
|
||||||
_render_camera_target();
|
_render_camera_target();
|
||||||
#endif // ENABLE_SHOW_CAMERA_TARGET
|
#endif // ENABLE_SHOW_CAMERA_TARGET
|
||||||
|
camera.update_frustum();
|
||||||
if (m_picking_enabled && m_rectangle_selection.is_dragging())
|
if (m_picking_enabled && m_rectangle_selection.is_dragging())
|
||||||
m_rectangle_selection.render(*this);
|
m_rectangle_selection.render(*this);
|
||||||
|
|
||||||
|
|
|
@ -805,6 +805,28 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (param == "enable_lod") {
|
||||||
|
if (wxGetApp().plater()->is_project_dirty()) {
|
||||||
|
auto result = MessageDialog(static_cast<wxWindow *>(this), _L("The current project has unsaved changes, save it before continuing?"),
|
||||||
|
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Save"), wxYES_NO | wxYES_DEFAULT | wxCENTRE)
|
||||||
|
.ShowModal();
|
||||||
|
if (result == wxID_YES) {
|
||||||
|
wxGetApp().plater()->save_project();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageDialog msg_wingow(nullptr, _L("Please note that the model show will undergo certain changes at small pixels case.\nEnabled LOD requires application restart.") + "\n" + _L("Do you want to continue?"), _L("Enable LOD"),
|
||||||
|
wxYES| wxYES_DEFAULT | wxCANCEL | wxCENTRE);
|
||||||
|
if (msg_wingow.ShowModal() == wxID_YES) {
|
||||||
|
Close();
|
||||||
|
GetParent()->RemoveChild(this);
|
||||||
|
wxGetApp().recreate_GUI(_L("Enable LOD"));
|
||||||
|
} else {
|
||||||
|
checkbox->SetValue(!checkbox->GetValue());
|
||||||
|
app_config->set_bool(param, checkbox->GetValue());
|
||||||
|
app_config->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.Skip();
|
e.Skip();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1107,6 +1129,9 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||||
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page,
|
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page,
|
||||||
_L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50,
|
_L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50,
|
||||||
"zoom_to_mouse");
|
"zoom_to_mouse");
|
||||||
|
auto enable_lod_settings = create_item_checkbox(_L("Improve rendering performance by lod"), page,
|
||||||
|
_L("Improved rendering performance under the scene of multiple plates and many models."), 50,
|
||||||
|
"enable_lod");
|
||||||
float range_min = 1.0, range_max = 2.5;
|
float range_min = 1.0, range_max = 2.5;
|
||||||
auto item_grabber_size_settings = create_item_range_input(_L("Grabber scale"), page,
|
auto item_grabber_size_settings = create_item_range_input(_L("Grabber scale"), page,
|
||||||
_L("Set grabber size for move,rotate,scale tool.") + _L("Value range") + ":[" + std::to_string(range_min) + "," +
|
_L("Set grabber size for move,rotate,scale tool.") + _L("Value range") + ":[" + std::to_string(range_min) + "," +
|
||||||
|
@ -1188,6 +1213,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||||
sizer_page->Add(item_multi_machine, 0, wxTOP, FromDIP(3));
|
sizer_page->Add(item_multi_machine, 0, wxTOP, FromDIP(3));
|
||||||
sizer_page->Add(_3d_settings, 0, wxTOP | wxEXPAND, FromDIP(20));
|
sizer_page->Add(_3d_settings, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||||
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
|
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
|
||||||
|
sizer_page->Add(enable_lod_settings, 0, wxTOP, FromDIP(3));
|
||||||
sizer_page->Add(item_grabber_size_settings, 0, wxTOP, FromDIP(3));
|
sizer_page->Add(item_grabber_size_settings, 0, wxTOP, FromDIP(3));
|
||||||
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
|
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||||
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
|
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
void OnPaint(wxPaintEvent &evt);
|
void OnPaint(wxPaintEvent &evt);
|
||||||
virtual ~ProgressDialog();
|
virtual ~ProgressDialog();
|
||||||
|
|
||||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO)override;
|
||||||
bool Create(const wxString &title, const wxString &message, int maximum = 100, wxWindow *parent = NULL, int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE);
|
bool Create(const wxString &title, const wxString &message, int maximum = 100, wxWindow *parent = NULL, int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE);
|
||||||
|
|
||||||
virtual bool Update(int value, const wxString &newmsg = wxEmptyString, bool *skip = NULL);
|
virtual bool Update(int value, const wxString &newmsg = wxEmptyString, bool *skip = NULL);
|
||||||
|
|
Loading…
Reference in New Issue