Tech ENABLE_GCODE_VIEWER -> Bed axes rendered using the new OpenGL model class

This commit is contained in:
enricoturri1966 2020-05-12 11:33:50 +02:00
parent 3475604362
commit 8d5cea82f4
6 changed files with 154 additions and 37 deletions

View File

@ -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())

View File

@ -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:

View File

@ -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);

View File

@ -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; }

View File

@ -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;

View File

@ -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);