mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-28 09:07:52 +08:00
Tech ENABLE_GCODE_VIEWER -> Bed axes rendered using the new OpenGL model class
This commit is contained in:
parent
3475604362
commit
8d5cea82f4
@ -5,15 +5,24 @@
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "3DScene.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include <boost/log/trivial.hpp>
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
static const float GROUND_Z = -0.02f;
|
||||
|
||||
@ -119,13 +128,25 @@ const float* GeometryBuffer::get_vertices_data() const
|
||||
return (m_vertices.size() > 0) ? (const float*)m_vertices.data() : nullptr;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
|
||||
const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
||||
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
|
||||
const float Bed3D::Axes::DefaultTipLength = 5.0f;
|
||||
#else
|
||||
const double Bed3D::Axes::Radius = 0.5;
|
||||
const double Bed3D::Axes::ArrowBaseRadius = 2.5 * Bed3D::Axes::Radius;
|
||||
const double Bed3D::Axes::ArrowLength = 5.0;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void Bed3D::Axes::set_stem_length(float length)
|
||||
{
|
||||
m_stem_length = length;
|
||||
m_arrow.reset();
|
||||
}
|
||||
#else
|
||||
Bed3D::Axes::Axes()
|
||||
: origin(Vec3d::Zero())
|
||||
, length(25.0 * Vec3d::Ones())
|
||||
{
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
@ -137,9 +158,46 @@ Bed3D::Axes::~Axes()
|
||||
if (m_quadric != nullptr)
|
||||
::gluDeleteQuadric(m_quadric);
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
void Bed3D::Axes::render() const
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
auto render_axis = [this](const Transform3f& transform, GLint color_id, const std::array<float, 4>& color) {
|
||||
if (color_id >= 0)
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color.data()));
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixf(transform.data()));
|
||||
m_arrow.render();
|
||||
glsafe(::glPopMatrix());
|
||||
};
|
||||
|
||||
m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
|
||||
if (!m_shader.init("gouraud_light.vs", "gouraud_light.fs"))
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to initialize gouraud_light shader: please, check that the files gouraud_light.vs and gouraud_light.fs are available";
|
||||
|
||||
if (!m_shader.is_initialized())
|
||||
return;
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
m_shader.start_using();
|
||||
GLint color_id = ::glGetUniformLocation(m_shader.get_shader_program_id(), "uniform_color");
|
||||
|
||||
// x axis
|
||||
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0f }).cast<float>(), color_id, { 0.75f, 0.0f, 0.0f, 1.0f });
|
||||
|
||||
// y axis
|
||||
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0f }).cast<float>(), color_id, { 0.0f, 0.75f, 0.0f, 1.0f });
|
||||
|
||||
// z axis
|
||||
render_axis(Geometry::assemble_transform(m_origin).cast<float>(), color_id, { 0.0f, 0.0f, 0.75f, 1.0f });
|
||||
|
||||
m_shader.stop_using();
|
||||
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
#else
|
||||
if (m_quadric == nullptr)
|
||||
return;
|
||||
|
||||
@ -171,8 +229,10 @@ void Bed3D::Axes::render() const
|
||||
|
||||
glsafe(::glDisable(GL_LIGHTING));
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
void Bed3D::Axes::render_axis(double length) const
|
||||
{
|
||||
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
|
||||
@ -185,6 +245,7 @@ void Bed3D::Axes::render_axis(double length) const
|
||||
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
|
||||
::gluDisk(m_quadric, 0.0, ArrowBaseRadius, 32, 1);
|
||||
}
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
Bed3D::Bed3D()
|
||||
: m_type(Custom)
|
||||
@ -242,8 +303,13 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c
|
||||
m_model.reset();
|
||||
|
||||
// Set the origin and size for rendering the coordinate system axes.
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_axes.set_origin({ 0.0, 0.0, static_cast<double>(GROUND_Z) });
|
||||
m_axes.set_stem_length(0.1f * static_cast<float>(m_bounding_box.max_size()));
|
||||
#else
|
||||
m_axes.origin = Vec3d(0.0, 0.0, (double)GROUND_Z);
|
||||
m_axes.length = 0.1 * m_bounding_box.max_size() * Vec3d::Ones();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// Let the calee to update the UI.
|
||||
return true;
|
||||
@ -290,7 +356,11 @@ void Bed3D::calc_bounding_boxes() const
|
||||
m_extended_bounding_box = m_bounding_box;
|
||||
|
||||
// extend to contain axes
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_extended_bounding_box.merge(m_axes.get_total_length() * Vec3d::Ones());
|
||||
#else
|
||||
m_extended_bounding_box.merge(m_axes.length + Axes::ArrowLength * Vec3d::Ones());
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// extend to contain model, if any
|
||||
if (!m_model.get_filename().empty())
|
||||
|
@ -4,11 +4,16 @@
|
||||
#include "GLTexture.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "GLShader.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "GLModel.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
class GLUquadric;
|
||||
typedef class GLUquadric GLUquadricObj;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@ -45,22 +50,50 @@ public:
|
||||
|
||||
class Bed3D
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
class Axes
|
||||
{
|
||||
static const float DefaultStemRadius;
|
||||
static const float DefaultStemLength;
|
||||
static const float DefaultTipRadius;
|
||||
static const float DefaultTipLength;
|
||||
#else
|
||||
struct Axes
|
||||
{
|
||||
static const double Radius;
|
||||
static const double ArrowBaseRadius;
|
||||
static const double ArrowLength;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
Vec3d m_origin{ Vec3d::Zero() };
|
||||
float m_stem_length{ DefaultStemLength };
|
||||
mutable GL_Model m_arrow;
|
||||
mutable Shader m_shader;
|
||||
|
||||
public:
|
||||
#else
|
||||
Vec3d origin;
|
||||
Vec3d length;
|
||||
GLUquadricObj* m_quadric;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
Axes();
|
||||
~Axes();
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void set_origin(const Vec3d& origin) { m_origin = origin; }
|
||||
void set_stem_length(float length);
|
||||
float get_total_length() const { return m_stem_length + DefaultTipLength; }
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
void render() const;
|
||||
|
||||
#if !ENABLE_GCODE_VIEWER
|
||||
private:
|
||||
void render_axis(double length) const;
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -147,7 +147,7 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con
|
||||
|
||||
void GCodeViewer::SequentialView::Marker::init()
|
||||
{
|
||||
m_model.init_from(stilized_arrow(16, 0.5f, 1.0f, 0.25f, 2.0f));
|
||||
m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f));
|
||||
init_shader();
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ void GCodeViewer::render() const
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
render_toolpaths();
|
||||
m_sequential_view.marker.set_world_transform(Geometry::assemble_transform(m_sequential_view.current_position.cast<double>() + 0.5 * Vec3d::UnitZ(), { 0.0, 0.0, 0.0 }, { 4.0, 4.0, 4.0 }, { 1.0, 1.0, 1.0 }).cast<float>());
|
||||
m_sequential_view.marker.set_world_transform(Geometry::assemble_transform(m_sequential_view.current_position.cast<double>() + (0.5 + 12.0) * Vec3d::UnitZ(), { M_PI, 0.0, 0.0 }).cast<float>());
|
||||
m_sequential_view.marker.render();
|
||||
render_shells();
|
||||
render_legend();
|
||||
@ -437,6 +437,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
||||
::memcpy(static_cast<void*>(&vertices_data[i * 3]), static_cast<const void*>(move.position.data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
m_bounding_box.merge(m_bounding_box.max + m_sequential_view.marker.get_bounding_box().max[2] * Vec3d::UnitZ());
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
m_statistics.vertices_size = SLIC3R_STDVEC_MEMSIZE(vertices_data, float);
|
||||
m_statistics.vertices_gpu_size = vertices_data.size() * sizeof(float);
|
||||
|
@ -162,6 +162,8 @@ class GCodeViewer
|
||||
public:
|
||||
void init();
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
|
||||
|
||||
void set_world_transform(const Transform3f& transform) { m_world_transform = transform; }
|
||||
void set_color(const std::array<float, 4>& color) { m_color = color; }
|
||||
|
||||
|
@ -9,12 +9,14 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
bool GL_Model::init_from(const GLModelInitializationData& data)
|
||||
void GL_Model::init_from(const GLModelInitializationData& data)
|
||||
{
|
||||
|
||||
assert(!data.positions.empty() && !data.triangles.empty());
|
||||
assert(data.positions.size() == data.normals.size());
|
||||
|
||||
reset();
|
||||
if (m_vbo_id > 0) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
// vertices/normals data
|
||||
std::vector<float> vertices(6 * data.positions.size());
|
||||
@ -32,19 +34,22 @@ bool GL_Model::init_from(const GLModelInitializationData& data)
|
||||
}
|
||||
|
||||
m_indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = BoundingBoxf3();
|
||||
for (size_t i = 0; i < data.positions.size(); ++i) {
|
||||
m_bounding_box.merge(data.positions[i].cast<double>());
|
||||
}
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GL_Model::init_from(const TriangleMesh& mesh)
|
||||
void GL_Model::init_from(const TriangleMesh& mesh)
|
||||
{
|
||||
auto get_normal = [](const std::array<stl_vertex, 3>& triangle) {
|
||||
return (triangle[1] - triangle[0]).cross(triangle[2] - triangle[0]).normalized();
|
||||
};
|
||||
|
||||
reset();
|
||||
if (m_vbo_id > 0) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
assert(!mesh.its.vertices.empty() && !mesh.its.indices.empty()); // call require_shared_vertices() before to pass the mesh to this method
|
||||
|
||||
@ -68,10 +73,9 @@ bool GL_Model::init_from(const TriangleMesh& mesh)
|
||||
}
|
||||
|
||||
m_indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = mesh.bounding_box();
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GL_Model::reset()
|
||||
@ -88,6 +92,7 @@ void GL_Model::reset()
|
||||
}
|
||||
|
||||
m_indices_count = 0;
|
||||
m_bounding_box = BoundingBoxf3();
|
||||
}
|
||||
|
||||
void GL_Model::render() const
|
||||
@ -142,12 +147,14 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
||||
sines[i] = -::sin(angle);
|
||||
}
|
||||
|
||||
float total_height = tip_height + stem_height;
|
||||
|
||||
// tip vertices/normals
|
||||
data.positions.emplace_back(0.0f, 0.0f, 0.0f);
|
||||
data.normals.emplace_back(-Vec3f::UnitZ());
|
||||
data.positions.emplace_back(0.0f, 0.0f, total_height);
|
||||
data.normals.emplace_back(Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(tip_radius * sines[i], tip_radius * cosines[i], tip_height);
|
||||
data.positions.emplace_back(tip_radius * sines[i], tip_radius * cosines[i], stem_height);
|
||||
data.normals.emplace_back(sines[i], cosines[i], 0.0f);
|
||||
}
|
||||
|
||||
@ -155,21 +162,21 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v3 = (i < resolution - 1) ? i + 2 : 1;
|
||||
data.triangles.emplace_back(0, v3, i + 1);
|
||||
data.triangles.emplace_back(0, i + 1, v3);
|
||||
}
|
||||
|
||||
// tip cap outer perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(tip_radius * sines[i], tip_radius * cosines[i], tip_height);
|
||||
data.normals.emplace_back(Vec3f::UnitZ());
|
||||
data.positions.emplace_back(tip_radius * sines[i], tip_radius * cosines[i], stem_height);
|
||||
data.normals.emplace_back(-Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap inner perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], tip_height);
|
||||
data.normals.emplace_back(Vec3f::UnitZ());
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], stem_height);
|
||||
data.normals.emplace_back(-Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap triangles
|
||||
@ -177,23 +184,21 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
||||
{
|
||||
int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
|
||||
int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
|
||||
data.triangles.emplace_back(i + resolution + 1, v2, v3);
|
||||
data.triangles.emplace_back(i + resolution + 1, v3, i + 2 * resolution + 1);
|
||||
data.triangles.emplace_back(i + resolution + 1, v3, v2);
|
||||
data.triangles.emplace_back(i + resolution + 1, i + 2 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem bottom vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], tip_height);
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], stem_height);
|
||||
data.normals.emplace_back(sines[i], cosines[i], 0.0f);
|
||||
}
|
||||
|
||||
float total_height = tip_height + stem_height;
|
||||
|
||||
// stem top vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], total_height);
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], 0.0f);
|
||||
data.normals.emplace_back(sines[i], cosines[i], 0.0f);
|
||||
}
|
||||
|
||||
@ -202,24 +207,24 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
||||
{
|
||||
int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
|
||||
int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, v2, v3);
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, v3, i + 4 * resolution + 1);
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, v3, v2);
|
||||
data.triangles.emplace_back(i + 3 * resolution + 1, i + 4 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem cap vertices
|
||||
data.positions.emplace_back(0.0f, 0.0f, total_height);
|
||||
data.normals.emplace_back(Vec3f::UnitZ());
|
||||
data.positions.emplace_back(0.0f, 0.0f, 0.0f);
|
||||
data.normals.emplace_back(-Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
data.positions.emplace_back(stem_radius * sines[i], stem_radius * cosines[i], total_height);
|
||||
data.normals.emplace_back(Vec3f::UnitZ());
|
||||
data.positions.emplace_back(stem_radius* sines[i], stem_radius* cosines[i], 0.0f);
|
||||
data.normals.emplace_back(-Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// stem cap triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
|
||||
data.triangles.emplace_back(5 * resolution + 1, i + 5 * resolution + 2, v3);
|
||||
data.triangles.emplace_back(5 * resolution + 1, v3, i + 5 * resolution + 2);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define slic3r_GLModel_hpp_
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
@ -23,22 +24,26 @@ namespace GUI {
|
||||
unsigned int m_ibo_id{ 0 };
|
||||
size_t m_indices_count{ 0 };
|
||||
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
|
||||
public:
|
||||
virtual ~GL_Model() { reset(); }
|
||||
|
||||
bool init_from(const GLModelInitializationData& data);
|
||||
bool init_from(const TriangleMesh& mesh);
|
||||
void init_from(const GLModelInitializationData& data);
|
||||
void init_from(const TriangleMesh& mesh);
|
||||
void reset();
|
||||
void render() const;
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
|
||||
|
||||
private:
|
||||
void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
|
||||
};
|
||||
|
||||
|
||||
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
|
||||
// the arrow tip is at 0,0,0
|
||||
// the arrow has its axis of symmetry along the Z axis and is pointing downward
|
||||
// the origin of the arrow is in the center of the stem cap
|
||||
// the arrow has its axis of symmetry along the Z axis and is pointing upward
|
||||
GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height,
|
||||
float stem_radius, float stem_height);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user