ENABLE_GCODE_VIEWER -> Completed implementation of new GLModel class

This commit is contained in:
enricoturri1966 2020-05-27 08:06:02 +02:00
parent 8f91b4f4f4
commit aa04f0e555
8 changed files with 105 additions and 44 deletions

View File

@ -358,14 +358,23 @@ void Bed3D::calc_bounding_boxes() const
// extend to contain axes // extend to contain axes
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
m_extended_bounding_box.merge(m_axes.get_total_length() * Vec3d::Ones()); m_extended_bounding_box.merge(m_axes.get_origin() + m_axes.get_total_length() * Vec3d::Ones());
#else m_extended_bounding_box.merge(m_extended_bounding_box.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, m_extended_bounding_box.max(2)));
m_extended_bounding_box.merge(m_axes.length + Axes::ArrowLength * Vec3d::Ones());
#endif // ENABLE_GCODE_VIEWER
// extend to contain model, if any
BoundingBoxf3 model_bb = m_model.get_bounding_box();
if (model_bb.defined)
{
model_bb.translate(m_model_offset);
m_extended_bounding_box.merge(model_bb);
}
#else
m_extended_bounding_box.merge(m_axes.get_total_length() * Vec3d::Ones());
m_extended_bounding_box.merge(m_axes.length + Axes::ArrowLength * Vec3d::Ones());
// extend to contain model, if any // extend to contain model, if any
if (!m_model.get_filename().empty()) if (!m_model.get_filename().empty())
m_extended_bounding_box.merge(m_model.get_transformed_bounding_box()); m_extended_bounding_box.merge(m_model.get_transformed_bounding_box());
#endif // ENABLE_GCODE_VIEWER
} }
void Bed3D::calc_triangles(const ExPolygon& poly) void Bed3D::calc_triangles(const ExPolygon& poly)
@ -621,7 +630,11 @@ void Bed3D::render_model() const
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad // move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
Vec3d shift = m_bounding_box.center(); Vec3d shift = m_bounding_box.center();
shift(2) = -0.03; shift(2) = -0.03;
#if ENABLE_GCODE_VIEWER
m_model_offset = shift;
#else
m_model.set_offset(shift); m_model.set_offset(shift);
#endif // ENABLE_GCODE_VIEWER
// update extended bounding box // update extended bounding box
calc_bounding_boxes(); calc_bounding_boxes();
@ -633,7 +646,15 @@ void Bed3D::render_model() const
if (shader != nullptr) if (shader != nullptr)
{ {
shader->start_using(); shader->start_using();
#if ENABLE_GCODE_VIEWER
shader->set_uniform("uniform_color", m_model_color);
::glPushMatrix();
::glTranslated(m_model_offset(0), m_model_offset(1), m_model_offset(2));
#endif // ENABLE_GCODE_VIEWER
m_model.render(); m_model.render();
#if ENABLE_GCODE_VIEWER
::glPopMatrix();
#endif // ENABLE_GCODE_VIEWER
shader->stop_using(); shader->stop_using();
} }
} }

View File

@ -8,6 +8,9 @@
#endif // ENABLE_GCODE_VIEWER #endif // ENABLE_GCODE_VIEWER
#include <tuple> #include <tuple>
#if ENABLE_GCODE_VIEWER
#include <array>
#endif // ENABLE_GCODE_VIEWER
#if !ENABLE_GCODE_VIEWER #if !ENABLE_GCODE_VIEWER
class GLUquadric; class GLUquadric;
@ -52,10 +55,13 @@ class Bed3D
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
class Axes class Axes
{ {
public:
static const float DefaultStemRadius; static const float DefaultStemRadius;
static const float DefaultStemLength; static const float DefaultStemLength;
static const float DefaultTipRadius; static const float DefaultTipRadius;
static const float DefaultTipLength; static const float DefaultTipLength;
private:
#else #else
struct Axes struct Axes
{ {
@ -67,7 +73,7 @@ class Bed3D
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
Vec3d m_origin{ Vec3d::Zero() }; Vec3d m_origin{ Vec3d::Zero() };
float m_stem_length{ DefaultStemLength }; float m_stem_length{ DefaultStemLength };
mutable GL_Model m_arrow; mutable GLModel m_arrow;
public: public:
#else #else
@ -82,6 +88,7 @@ class Bed3D
#endif // !ENABLE_GCODE_VIEWER #endif // !ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
const Vec3d& get_origin() const { return m_origin; }
void set_origin(const Vec3d& origin) { m_origin = origin; } void set_origin(const Vec3d& origin) { m_origin = origin; }
void set_stem_length(float length); void set_stem_length(float length);
float get_total_length() const { return m_stem_length + DefaultTipLength; } float get_total_length() const { return m_stem_length + DefaultTipLength; }
@ -113,7 +120,13 @@ private:
GeometryBuffer m_triangles; GeometryBuffer m_triangles;
GeometryBuffer m_gridlines; GeometryBuffer m_gridlines;
mutable GLTexture m_texture; mutable GLTexture m_texture;
#if ENABLE_GCODE_VIEWER
mutable GLModel m_model;
mutable Vec3d m_model_offset{ Vec3d::Zero() };
std::array<float, 4> m_model_color{ 0.235f, 0.235f, 0.235f, 1.0f };
#else
mutable GLBed m_model; mutable GLBed m_model;
#endif // ENABLE_GCODE_VIEWER
// temporary texture shown until the main texture has still no levels compressed // temporary texture shown until the main texture has still no levels compressed
mutable GLTexture m_temp_texture; mutable GLTexture m_temp_texture;
mutable unsigned int m_vbo_id; mutable unsigned int m_vbo_id;

View File

@ -1822,6 +1822,7 @@ void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height
thick_point_to_verts(point, width, height, volume); thick_point_to_verts(point, width, height, volume);
} }
#if !ENABLE_GCODE_VIEWER
GLModel::GLModel() GLModel::GLModel()
: m_filename("") : m_filename("")
{ {
@ -1904,7 +1905,6 @@ void GLModel::render() const
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
#if !ENABLE_GCODE_VIEWER
bool GLArrow::on_init() bool GLArrow::on_init()
{ {
Pointf3s vertices; Pointf3s vertices;
@ -2076,7 +2076,6 @@ bool GLCurvedArrow::on_init()
m_volume.indexed_vertex_array.finalize_geometry(true); m_volume.indexed_vertex_array.finalize_geometry(true);
return true; return true;
} }
#endif // !ENABLE_GCODE_VIEWER
bool GLBed::on_init_from_file(const std::string& filename) bool GLBed::on_init_from_file(const std::string& filename)
{ {
@ -2108,5 +2107,6 @@ bool GLBed::on_init_from_file(const std::string& filename)
return true; return true;
} }
#endif // !ENABLE_GCODE_VIEWER
} // namespace Slic3r } // namespace Slic3r

View File

@ -599,6 +599,7 @@ private:
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = nullptr); GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = nullptr);
#if !ENABLE_GCODE_VIEWER
class GLModel class GLModel
{ {
protected: protected:
@ -636,7 +637,6 @@ protected:
virtual bool on_init_from_file(const std::string& filename) { return false; } virtual bool on_init_from_file(const std::string& filename) { return false; }
}; };
#if !ENABLE_GCODE_VIEWER
class GLArrow : public GLModel class GLArrow : public GLModel
{ {
protected: protected:
@ -653,13 +653,13 @@ public:
protected: protected:
bool on_init() override; bool on_init() override;
}; };
#endif // !ENABLE_GCODE_VIEWER
class GLBed : public GLModel class GLBed : public GLModel
{ {
protected: protected:
bool on_init_from_file(const std::string& filename) override; bool on_init_from_file(const std::string& filename) override;
}; };
#endif // !ENABLE_GCODE_VIEWER
struct _3DScene struct _3DScene
{ {

View File

@ -219,7 +219,7 @@ public:
{ {
class Marker class Marker
{ {
GL_Model m_model; GLModel m_model;
Transform3f m_world_transform; Transform3f m_world_transform;
BoundingBoxf3 m_world_bounding_box; BoundingBoxf3 m_world_bounding_box;
std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 1.0f }; std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 1.0f };

View File

@ -3,13 +3,17 @@
#include "3DScene.hpp" #include "3DScene.hpp"
#include "libslic3r/TriangleMesh.hpp" #include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Model.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <GL/glew.h> #include <GL/glew.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
void GL_Model::init_from(const GLModelInitializationData& data) void GLModel::init_from(const GLModelInitializationData& data)
{ {
assert(!data.positions.empty() && !data.triangles.empty()); assert(!data.positions.empty() && !data.triangles.empty());
assert(data.positions.size() == data.normals.size()); assert(data.positions.size() == data.normals.size());
@ -20,8 +24,9 @@ void GL_Model::init_from(const GLModelInitializationData& data)
// vertices/normals data // vertices/normals data
std::vector<float> vertices(6 * data.positions.size()); std::vector<float> vertices(6 * data.positions.size());
for (size_t i = 0; i < data.positions.size(); ++i) { for (size_t i = 0; i < data.positions.size(); ++i) {
::memcpy(static_cast<void*>(&vertices[i * 6]), static_cast<const void*>(data.positions[i].data()), 3 * sizeof(float)); size_t offset = i * 6;
::memcpy(static_cast<void*>(&vertices[3 + i * 6]), static_cast<const void*>(data.normals[i].data()), 3 * sizeof(float)); ::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(data.positions[i].data()), 3 * sizeof(float));
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(data.normals[i].data()), 3 * sizeof(float));
} }
// indices data // indices data
@ -41,34 +46,26 @@ void GL_Model::init_from(const GLModelInitializationData& data)
send_to_gpu(vertices, indices); send_to_gpu(vertices, indices);
} }
void GL_Model::init_from(const TriangleMesh& mesh) void GLModel::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();
};
if (m_vbo_id > 0) // call reset() if you want to reuse this model if (m_vbo_id > 0) // call reset() if you want to reuse this model
return; return;
assert(!mesh.its.vertices.empty() && !mesh.its.indices.empty()); // call require_shared_vertices() before to pass the mesh to this method std::vector<float> vertices = std::vector<float>(18 * mesh.stl.stats.number_of_facets);
std::vector<unsigned int> indices = std::vector<unsigned int>(3 * mesh.stl.stats.number_of_facets);
// vertices data -> load from mesh unsigned int vertices_count = 0;
std::vector<float> vertices(6 * mesh.its.vertices.size()); for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
for (size_t i = 0; i < mesh.its.vertices.size(); ++i) { const stl_facet& facet = mesh.stl.facet_start[i];
::memcpy(static_cast<void*>(&vertices[i * 6]), static_cast<const void*>(mesh.its.vertices[i].data()), 3 * sizeof(float)); for (uint32_t j = 0; j < 3; ++j) {
} uint32_t offset = i * 18 + j * 6;
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(facet.vertex[j].data()), 3 * sizeof(float));
// indices/normals data -> load from mesh ::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(facet.normal.data()), 3 * sizeof(float));
std::vector<unsigned int> indices(3 * mesh.its.indices.size());
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
const stl_triangle_vertex_indices& triangle = mesh.its.indices[i];
for (size_t j = 0; j < 3; ++j) {
indices[i * 3 + j] = static_cast<unsigned int>(triangle[j]);
} }
Vec3f normal = get_normal({ mesh.its.vertices[triangle[0]], mesh.its.vertices[triangle[1]], mesh.its.vertices[triangle[2]] }); for (uint32_t j = 0; j < 3; ++j) {
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[0]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float)); indices[i * 3 + j] = vertices_count + j;
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[1]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float)); }
::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[2]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float)); vertices_count += 3;
} }
m_indices_count = static_cast<unsigned int>(indices.size()); m_indices_count = static_cast<unsigned int>(indices.size());
@ -77,7 +74,32 @@ void GL_Model::init_from(const TriangleMesh& mesh)
send_to_gpu(vertices, indices); send_to_gpu(vertices, indices);
} }
void GL_Model::reset() bool GLModel::init_from_file(const std::string& filename)
{
if (!boost::filesystem::exists(filename))
return false;
if (!boost::algorithm::iends_with(filename, ".stl"))
return false;
Model model;
try
{
model = Model::read_from_file(filename);
}
catch (std::exception&)
{
return false;
}
init_from(model.mesh());
m_filename = filename;
return true;
}
void GLModel::reset()
{ {
// release gpu memory // release gpu memory
if (m_ibo_id > 0) { if (m_ibo_id > 0) {
@ -92,9 +114,10 @@ void GL_Model::reset()
m_indices_count = 0; m_indices_count = 0;
m_bounding_box = BoundingBoxf3(); m_bounding_box = BoundingBoxf3();
m_filename = std::string();
} }
void GL_Model::render() const void GLModel::render() const
{ {
if (m_vbo_id == 0 || m_ibo_id == 0) if (m_vbo_id == 0 || m_ibo_id == 0)
return; return;
@ -116,7 +139,7 @@ void GL_Model::render() const
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
} }
void GL_Model::send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices) void GLModel::send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
{ {
// vertex data -> send to gpu // vertex data -> send to gpu
glsafe(::glGenBuffers(1, &m_vbo_id)); glsafe(::glGenBuffers(1, &m_vbo_id));

View File

@ -4,6 +4,7 @@
#include "libslic3r/Point.hpp" #include "libslic3r/Point.hpp"
#include "libslic3r/BoundingBox.hpp" #include "libslic3r/BoundingBox.hpp"
#include <vector> #include <vector>
#include <string>
namespace Slic3r { namespace Slic3r {
@ -18,24 +19,28 @@ namespace GUI {
std::vector<Vec3i> triangles; std::vector<Vec3i> triangles;
}; };
class GL_Model class GLModel
{ {
unsigned int m_vbo_id{ 0 }; unsigned int m_vbo_id{ 0 };
unsigned int m_ibo_id{ 0 }; unsigned int m_ibo_id{ 0 };
size_t m_indices_count{ 0 }; size_t m_indices_count{ 0 };
BoundingBoxf3 m_bounding_box; BoundingBoxf3 m_bounding_box;
std::string m_filename;
public: public:
virtual ~GL_Model() { reset(); } virtual ~GLModel() { reset(); }
void init_from(const GLModelInitializationData& data); void init_from(const GLModelInitializationData& data);
void init_from(const TriangleMesh& mesh); void init_from(const TriangleMesh& mesh);
bool init_from_file(const std::string& filename);
void reset(); void reset();
void render() const; void render() const;
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; } const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
const std::string& get_filename() const { return m_filename; }
private: private:
void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices); void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
}; };
@ -44,8 +49,7 @@ namespace GUI {
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution // create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
// the origin of the arrow is in the center of the stem cap // 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 // 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, GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height);
float stem_radius, float stem_height);
// create an arrow whose stem is a quarter of circle, with the given dimensions and resolution // create an arrow whose stem is a quarter of circle, with the given dimensions and resolution
// the origin of the arrow is in the center of the circle // the origin of the arrow is in the center of the circle

View File

@ -207,8 +207,8 @@ private:
GLUquadricObj* m_quadric; GLUquadricObj* m_quadric;
#endif // ENABLE_RENDER_SELECTION_CENTER #endif // ENABLE_RENDER_SELECTION_CENTER
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
GL_Model m_arrow; GLModel m_arrow;
GL_Model m_curved_arrow; GLModel m_curved_arrow;
#else #else
mutable GLArrow m_arrow; mutable GLArrow m_arrow;
mutable GLCurvedArrow m_curved_arrow; mutable GLCurvedArrow m_curved_arrow;