Tech ENABLE_SEQUENTIAL_LIMITS -> 1st installment of visualization of objects clearance for sequential prints
This commit is contained in:
parent
9537c4e8d0
commit
75677ba810
14 changed files with 889 additions and 87 deletions
|
@ -1194,9 +1194,18 @@ bool Print::has_brim() const
|
|||
return std::any_of(m_objects.begin(), m_objects.end(), [](PrintObject *object) { return object->has_brim(); });
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons)
|
||||
#else
|
||||
static inline bool sequential_print_horizontal_clearance_valid(const Print &print)
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
{
|
||||
Polygons convex_hulls_other;
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
std::vector<size_t> intersecting_idxs;
|
||||
bool intersection_detected = false;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
|
||||
for (const PrintObject *print_object : print.objects()) {
|
||||
assert(! print_object->model_object()->instances.empty());
|
||||
|
@ -1221,21 +1230,49 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin
|
|||
}
|
||||
// Make a copy, so it may be rotated for instances.
|
||||
Polygon convex_hull0 = it_convex_hull->second;
|
||||
double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
|
||||
const double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
|
||||
if (std::abs(z_diff) > EPSILON)
|
||||
convex_hull0.rotate(z_diff);
|
||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||
for (const PrintInstance &instance : print_object->instances()) {
|
||||
Polygon convex_hull = convex_hull0;
|
||||
// instance.shift is a position of a centered object, while model object may not be centered.
|
||||
// Conver the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
|
||||
// Convert the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
|
||||
convex_hull.translate(instance.shift - print_object->center_offset());
|
||||
if (! intersection(convex_hulls_other, (Polygons)convex_hull).empty())
|
||||
return false;
|
||||
convex_hulls_other.emplace_back(std::move(convex_hull));
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
for (size_t i = 0; i < convex_hulls_other.size(); ++i) {
|
||||
if (!intersection((Polygons)convex_hulls_other[i], (Polygons)convex_hull).empty()) {
|
||||
if (polygons == nullptr)
|
||||
return false;
|
||||
else {
|
||||
intersection_detected = true;
|
||||
intersecting_idxs.push_back(i);
|
||||
intersecting_idxs.push_back(convex_hulls_other.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!intersection(convex_hulls_other, (Polygons)convex_hull).empty())
|
||||
return false;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
convex_hulls_other.emplace_back(std::move(convex_hull));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (intersection_detected) {
|
||||
assert(polygons != nullptr);
|
||||
|
||||
std::sort(intersecting_idxs.begin(), intersecting_idxs.end());
|
||||
intersecting_idxs.erase(std::unique(intersecting_idxs.begin(), intersecting_idxs.end()), intersecting_idxs.end());
|
||||
for (size_t i : intersecting_idxs) {
|
||||
polygons->emplace_back(std::move(convex_hulls_other[i]));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sequential_print_vertical_clearance_valid(const Print &print)
|
||||
|
|
|
@ -502,6 +502,10 @@ public:
|
|||
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
||||
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; } // #ys_FIXME just for testing
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
static bool sequential_print_horizontal_clearance_valid(const Print& print, Polygons* polygons = nullptr);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
protected:
|
||||
// methods for handling regions
|
||||
PrintRegion* get_region(size_t idx) { return m_regions[idx]; }
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
#define ENABLE_START_GCODE_VISUALIZATION (1 && ENABLE_2_4_0_ALPHA0)
|
||||
// Enable visualization of seams in preview
|
||||
#define ENABLE_SEAMS_VISUALIZATION (1 && ENABLE_2_4_0_ALPHA0)
|
||||
// Enable visualization of objects clearance for sequential prints
|
||||
#define ENABLE_SEQUENTIAL_LIMITS (1 && ENABLE_2_4_0_ALPHA0)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
|
|
@ -98,12 +98,6 @@ const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
|||
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
|
||||
const float Bed3D::Axes::DefaultTipLength = 5.0f;
|
||||
|
||||
void Bed3D::Axes::set_stem_length(float length)
|
||||
{
|
||||
m_stem_length = length;
|
||||
m_arrow.reset();
|
||||
}
|
||||
|
||||
void Bed3D::Axes::render() const
|
||||
{
|
||||
auto render_axis = [this](const Transform3f& transform) {
|
||||
|
@ -113,7 +107,10 @@ void Bed3D::Axes::render() const
|
|||
glsafe(::glPopMatrix());
|
||||
};
|
||||
|
||||
const_cast<GLModel*>(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (!m_arrow.is_initialized())
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
const_cast<GLModel*>(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr)
|
||||
|
@ -124,18 +121,30 @@ void Bed3D::Axes::render() const
|
|||
shader->start_using();
|
||||
|
||||
// x axis
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.75f, 0.0f, 0.0f, 1.0f });
|
||||
#else
|
||||
std::array<float, 4> color = { 0.75f, 0.0f, 0.0f, 1.0f };
|
||||
shader->set_uniform("uniform_color", color);
|
||||
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0f }).cast<float>());
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
|
||||
|
||||
// y axis
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.75f, 0.0f, 1.0f });
|
||||
#else
|
||||
color = { 0.0f, 0.75f, 0.0f, 1.0f };
|
||||
shader->set_uniform("uniform_color", color);
|
||||
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0f }).cast<float>());
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
|
||||
|
||||
// z axis
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.0f, 0.75f, 1.0f });
|
||||
#else
|
||||
color = { 0.0f, 0.0f, 0.75f, 1.0f };
|
||||
shader->set_uniform("uniform_color", color);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
|
||||
|
||||
shader->stop_using();
|
||||
|
@ -475,6 +484,10 @@ void Bed3D::render_model() const
|
|||
GLModel* model = const_cast<GLModel*>(&m_model);
|
||||
|
||||
if (model->get_filename() != m_model_filename && model->init_from_file(m_model_filename)) {
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
model->set_color(-1, m_model_color);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
// 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();
|
||||
shift(2) = -0.03;
|
||||
|
@ -488,7 +501,9 @@ void Bed3D::render_model() const
|
|||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
#if !ENABLE_SEQUENTIAL_LIMITS
|
||||
shader->set_uniform("uniform_color", m_model_color);
|
||||
#endif // !ENABLE_SEQUENTIAL_LIMITS
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_model_offset(0), m_model_offset(1), m_model_offset(2));
|
||||
model->render();
|
||||
|
|
|
@ -17,8 +17,8 @@ class GeometryBuffer
|
|||
{
|
||||
struct Vertex
|
||||
{
|
||||
Vec3f position = Vec3f::Zero();
|
||||
Vec2f tex_coords = Vec2f::Zero();
|
||||
Vec3f position{ Vec3f::Zero() };
|
||||
Vec2f tex_coords{ Vec2f::Zero() };
|
||||
};
|
||||
|
||||
std::vector<Vertex> m_vertices;
|
||||
|
@ -53,7 +53,10 @@ class Bed3D
|
|||
public:
|
||||
const Vec3d& get_origin() const { return m_origin; }
|
||||
void set_origin(const Vec3d& origin) { m_origin = origin; }
|
||||
void set_stem_length(float length);
|
||||
void set_stem_length(float length) {
|
||||
m_stem_length = length;
|
||||
m_arrow.reset();
|
||||
}
|
||||
float get_total_length() const { return m_stem_length + DefaultTipLength; }
|
||||
void render() const;
|
||||
};
|
||||
|
|
|
@ -241,6 +241,9 @@ void GCodeViewer::SequentialRangeCap::reset() {
|
|||
void GCodeViewer::SequentialView::Marker::init()
|
||||
{
|
||||
m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f));
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
m_model.set_color(-1, { 1.0f, 1.0f, 1.0f, 0.5f });
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& position)
|
||||
|
@ -262,7 +265,9 @@ void GCodeViewer::SequentialView::Marker::render() const
|
|||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
shader->start_using();
|
||||
#if !ENABLE_SEQUENTIAL_LIMITS
|
||||
shader->set_uniform("uniform_color", m_color);
|
||||
#endif // !ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixf(m_world_transform.data()));
|
||||
|
|
|
@ -581,7 +581,9 @@ public:
|
|||
Vec3f m_world_position;
|
||||
Transform3f m_world_transform;
|
||||
float m_z_offset{ 0.5f };
|
||||
#if !ENABLE_SEQUENTIAL_LIMITS
|
||||
std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 0.5f };
|
||||
#endif // !ENABLE_SEQUENTIAL_LIMITS
|
||||
bool m_visible{ true };
|
||||
|
||||
public:
|
||||
|
@ -590,7 +592,9 @@ public:
|
|||
const BoundingBoxf3& get_bounding_box() const { return m_model.get_bounding_box(); }
|
||||
|
||||
void set_world_position(const Vec3f& position);
|
||||
#if !ENABLE_SEQUENTIAL_LIMITS
|
||||
void set_color(const std::array<float, 4>& color) { m_color = color; }
|
||||
#endif // !ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
bool is_visible() const { return m_visible; }
|
||||
void set_visible(bool visible) { m_visible = visible; }
|
||||
|
|
|
@ -1069,6 +1069,80 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas
|
|||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons)
|
||||
{
|
||||
m_model.reset();
|
||||
if (polygons.empty())
|
||||
return;
|
||||
|
||||
size_t triangles_count = 0;
|
||||
for (const Polygon& poly : polygons) {
|
||||
triangles_count += poly.points.size() - 2;
|
||||
}
|
||||
size_t vertices_count = 3 * triangles_count;
|
||||
|
||||
GLModel::InitializationData data;
|
||||
GLModel::InitializationData::Entity entity;
|
||||
entity.type = GLModel::PrimitiveType::Triangles;
|
||||
entity.color = { 0.3333f, 0.3333f, 0.3333f, 1.0f };
|
||||
entity.positions.reserve(vertices_count);
|
||||
entity.normals.reserve(vertices_count);
|
||||
entity.indices.reserve(vertices_count);
|
||||
|
||||
for (const Polygon& poly : polygons) {
|
||||
std::vector<Vec3d> triangulation = triangulate_expolygon_3d(ExPolygon(poly), false);
|
||||
for (const Vec3d& v : triangulation) {
|
||||
entity.positions.emplace_back(v.cast<float>());
|
||||
entity.normals.emplace_back(Vec3f::UnitZ());
|
||||
size_t positions_count = entity.positions.size();
|
||||
if (positions_count % 3 == 0) {
|
||||
entity.indices.emplace_back(positions_count - 3);
|
||||
entity.indices.emplace_back(positions_count - 2);
|
||||
entity.indices.emplace_back(positions_count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
|
||||
for (const Polygon& poly : polygons) {
|
||||
GLModel::InitializationData::Entity ent;
|
||||
ent.type = GLModel::PrimitiveType::LineLoop;
|
||||
ent.color = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
ent.positions.reserve(poly.points.size());
|
||||
ent.indices.reserve(poly.points.size());
|
||||
unsigned int id_count = 0;
|
||||
for (const Point& p : poly.points) {
|
||||
ent.positions.emplace_back(unscale<float>(p.x()), unscale<float>(p.y()), 0.0f);
|
||||
ent.normals.emplace_back(Vec3f::UnitZ());
|
||||
ent.indices.emplace_back(id_count++);
|
||||
}
|
||||
|
||||
data.entities.emplace_back(ent);
|
||||
}
|
||||
|
||||
m_model.init_from(data);
|
||||
}
|
||||
|
||||
void GLCanvas3D::SequentialPrintClearance::render() const
|
||||
{
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
m_model.render();
|
||||
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
float GLCanvas3D::Slope::s_window_width;
|
||||
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
|
||||
|
@ -1669,6 +1743,9 @@ void GLCanvas3D::render()
|
|||
_render_gcode();
|
||||
_render_sla_slices();
|
||||
_render_selection();
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
_render_sequential_clearance();
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
_render_bed(!camera.is_looking_downward(), true);
|
||||
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
|
@ -2204,7 +2281,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("wipe_tower"))->value;
|
||||
bool co = dynamic_cast<const ConfigOptionBool*>(m_config->option("complete_objects"))->value;
|
||||
|
||||
if ((extruders_count > 1) && wt && !co) {
|
||||
if (extruders_count > 1 && wt && !co) {
|
||||
// Height of a print (Show at least a slab)
|
||||
double height = std::max(m_model->bounding_box().max(2), 10.0);
|
||||
|
||||
|
@ -5140,6 +5217,13 @@ void GLCanvas3D::_render_selection() const
|
|||
m_selection.render(scale_factor);
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void GLCanvas3D::_render_sequential_clearance() const
|
||||
{
|
||||
m_sequential_print_clearance.render();
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void GLCanvas3D::_render_selection_center() const
|
||||
{
|
||||
|
|
|
@ -541,6 +541,19 @@ private:
|
|||
|
||||
void load_arrange_settings();
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
class SequentialPrintClearance
|
||||
{
|
||||
GLModel m_model;
|
||||
|
||||
public:
|
||||
void set(const Polygons& polygons);
|
||||
void render() const;
|
||||
};
|
||||
|
||||
SequentialPrintClearance m_sequential_print_clearance;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
public:
|
||||
explicit GLCanvas3D(wxGLCanvas* canvas);
|
||||
~GLCanvas3D();
|
||||
|
@ -782,6 +795,12 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void set_sequential_print_clearance(const Polygons& polygons) {
|
||||
m_sequential_print_clearance.set(polygons);
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
|
||||
|
@ -808,6 +827,9 @@ private:
|
|||
void _render_objects() const;
|
||||
void _render_gcode() const;
|
||||
void _render_selection() const;
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void _render_sequential_clearance() const;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void _render_selection_center() const;
|
||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
#include "GLModel.hpp"
|
||||
|
||||
#include "3DScene.hpp"
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
#include "GUI_App.hpp"
|
||||
#include "GLShader.hpp"
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
@ -13,6 +18,45 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void GLModel::init_from(const InitializationData& data)
|
||||
{
|
||||
if (!m_render_data.empty()) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
for (const InitializationData::Entity& entity : data.entities) {
|
||||
if (entity.positions.empty() || entity.indices.empty())
|
||||
continue;
|
||||
|
||||
assert(entity.normals.empty() || entity.normals.size() == entity.positions.size());
|
||||
|
||||
RenderData rdata;
|
||||
rdata.type = entity.type;
|
||||
rdata.color = entity.color;
|
||||
|
||||
// vertices/normals data
|
||||
std::vector<float> vertices(6 * entity.positions.size());
|
||||
for (size_t i = 0; i < entity.positions.size(); ++i) {
|
||||
const size_t offset = i * 6;
|
||||
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(entity.positions[i].data()), 3 * sizeof(float));
|
||||
if (!entity.normals.empty())
|
||||
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(entity.normals[i].data()), 3 * sizeof(float));
|
||||
}
|
||||
|
||||
// indices data
|
||||
std::vector<unsigned int> indices = entity.indices;
|
||||
|
||||
rdata.indices_count = static_cast<unsigned int>(indices.size());
|
||||
|
||||
// update bounding box
|
||||
for (size_t i = 0; i < entity.positions.size(); ++i) {
|
||||
m_bounding_box.merge(entity.positions[i].cast<double>());
|
||||
}
|
||||
|
||||
send_to_gpu(rdata, vertices, indices);
|
||||
m_render_data.emplace_back(rdata);
|
||||
}
|
||||
#else
|
||||
void GLModel::init_from(const GLModelInitializationData& data)
|
||||
{
|
||||
assert(!data.positions.empty() && !data.triangles.empty());
|
||||
|
@ -44,10 +88,41 @@ void GLModel::init_from(const GLModelInitializationData& data)
|
|||
}
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
void GLModel::init_from(const TriangleMesh& mesh)
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (!m_render_data.empty()) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
RenderData data;
|
||||
data.type = PrimitiveType::Triangles;
|
||||
|
||||
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);
|
||||
|
||||
unsigned int vertices_count = 0;
|
||||
for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||
const stl_facet& facet = mesh.stl.facet_start[i];
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
size_t offset = i * 18 + j * 6;
|
||||
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(facet.vertex[j].data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(facet.normal.data()), 3 * sizeof(float));
|
||||
}
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
indices[i * 3 + j] = vertices_count + j;
|
||||
}
|
||||
vertices_count += 3;
|
||||
}
|
||||
|
||||
data.indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = mesh.bounding_box();
|
||||
|
||||
send_to_gpu(data, vertices, indices);
|
||||
m_render_data.emplace_back(data);
|
||||
#else
|
||||
if (m_vbo_id > 0) // call reset() if you want to reuse this model
|
||||
return;
|
||||
|
||||
|
@ -72,6 +147,7 @@ void GLModel::init_from(const TriangleMesh& mesh)
|
|||
m_bounding_box = mesh.bounding_box();
|
||||
|
||||
send_to_gpu(vertices, indices);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
bool GLModel::init_from_file(const std::string& filename)
|
||||
|
@ -99,8 +175,29 @@ bool GLModel::init_from_file(const std::string& filename)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void GLModel::set_color(int entity_id, const std::array<float, 4>& color)
|
||||
{
|
||||
for (size_t i = 0; i < m_render_data.size(); ++i) {
|
||||
if (entity_id == -1 || static_cast<int>(i) == entity_id)
|
||||
m_render_data[i].color = color;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
void GLModel::reset()
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
for (RenderData& data : m_render_data) {
|
||||
// release gpu memory
|
||||
if (data.ibo_id > 0)
|
||||
glsafe(::glDeleteBuffers(1, &data.ibo_id));
|
||||
if (data.vbo_id > 0)
|
||||
glsafe(::glDeleteBuffers(1, &data.vbo_id));
|
||||
}
|
||||
|
||||
m_render_data.clear();
|
||||
#else
|
||||
// release gpu memory
|
||||
if (m_ibo_id > 0) {
|
||||
glsafe(::glDeleteBuffers(1, &m_ibo_id));
|
||||
|
@ -113,12 +210,49 @@ void GLModel::reset()
|
|||
}
|
||||
|
||||
m_indices_count = 0;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
m_bounding_box = BoundingBoxf3();
|
||||
m_filename = std::string();
|
||||
}
|
||||
|
||||
void GLModel::render() const
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
for (const RenderData& data : m_render_data) {
|
||||
if (data.vbo_id == 0 || data.ibo_id == 0)
|
||||
continue;
|
||||
|
||||
GLenum mode;
|
||||
switch (data.type)
|
||||
{
|
||||
default:
|
||||
case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; }
|
||||
case PrimitiveType::Lines: { mode = GL_LINES; break; }
|
||||
case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; }
|
||||
case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; }
|
||||
}
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0));
|
||||
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
||||
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
if (shader != nullptr)
|
||||
shader->set_uniform("uniform_color", data.color);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id));
|
||||
glsafe(::glDrawElements(mode, static_cast<GLsizei>(data.indices_count), GL_UNSIGNED_INT, (const void*)0));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
|
||||
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
|
||||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
#else
|
||||
if (m_vbo_id == 0 || m_ibo_id == 0)
|
||||
return;
|
||||
|
||||
|
@ -137,8 +271,28 @@ void GLModel::render() const
|
|||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
|
||||
{
|
||||
assert(data.vbo_id == 0);
|
||||
assert(data.ibo_id == 0);
|
||||
|
||||
// vertex data -> send to gpu
|
||||
glsafe(::glGenBuffers(1, &data.vbo_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// indices data -> send to gpu
|
||||
glsafe(::glGenBuffers(1, &data.ibo_id));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id));
|
||||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
#else
|
||||
void GLModel::send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
|
||||
{
|
||||
// vertex data -> send to gpu
|
||||
|
@ -153,60 +307,138 @@ void GLModel::send_to_gpu(const std::vector<float>& vertices, const std::vector<
|
|||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
||||
{
|
||||
auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
|
||||
entity.positions.emplace_back(position);
|
||||
entity.normals.emplace_back(normal);
|
||||
};
|
||||
auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
|
||||
entity.indices.emplace_back(v1);
|
||||
entity.indices.emplace_back(v2);
|
||||
entity.indices.emplace_back(v3);
|
||||
};
|
||||
#else
|
||||
GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
data.positions.emplace_back(position);
|
||||
data.normals.emplace_back(normal);
|
||||
};
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
resolution = std::max(4, resolution);
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
GLModel::InitializationData data;
|
||||
GLModel::InitializationData::Entity entity;
|
||||
entity.type = GLModel::PrimitiveType::Triangles;
|
||||
#else
|
||||
GLModelInitializationData data;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
const float angle_step = 2.0f * M_PI / static_cast<float>(resolution);
|
||||
std::vector<float> cosines(resolution);
|
||||
std::vector<float> sines(resolution);
|
||||
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
float angle = angle_step * static_cast<float>(i);
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const float angle = angle_step * static_cast<float>(i);
|
||||
cosines[i] = ::cos(angle);
|
||||
sines[i] = -::sin(angle);
|
||||
}
|
||||
|
||||
const float total_height = tip_height + stem_height;
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
// tip vertices/normals
|
||||
append_vertex(entity, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// tip triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int v3 = (i < resolution - 1) ? i + 2 : 1;
|
||||
append_indices(entity, 0, i + 1, v3);
|
||||
}
|
||||
|
||||
// tip cap outer perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap inner perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int v2 = (i < resolution - 1) ? i + resolution + 2 : resolution + 1;
|
||||
const int v3 = (i < resolution - 1) ? i + 2 * resolution + 2 : 2 * resolution + 1;
|
||||
append_indices(entity, i + resolution + 1, v3, v2);
|
||||
append_indices(entity, i + resolution + 1, i + 2 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem bottom vertices
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem top vertices
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int v2 = (i < resolution - 1) ? i + 3 * resolution + 2 : 3 * resolution + 1;
|
||||
const int v3 = (i < resolution - 1) ? i + 4 * resolution + 2 : 4 * resolution + 1;
|
||||
append_indices(entity, i + 3 * resolution + 1, v3, v2);
|
||||
append_indices(entity, i + 3 * resolution + 1, i + 4 * resolution + 1, v3);
|
||||
}
|
||||
|
||||
// stem cap vertices
|
||||
append_vertex(entity, Vec3f::Zero(), -Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(entity, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// stem cap triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int v3 = (i < resolution - 1) ? i + 5 * resolution + 3 : 5 * resolution + 2;
|
||||
append_indices(entity, 5 * resolution + 1, v3, i + 5 * resolution + 2);
|
||||
}
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#else
|
||||
// tip vertices/normals
|
||||
append_vertex(data, { 0.0f, 0.0f, total_height }, Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// tip triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
int v3 = (i < resolution - 1) ? i + 2 : 1;
|
||||
data.triangles.emplace_back(0, i + 1, v3);
|
||||
}
|
||||
|
||||
// tip cap outer perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { tip_radius * sines[i], tip_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap inner perimeter vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// tip cap triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
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, v3, v2);
|
||||
|
@ -214,20 +446,17 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
|||
}
|
||||
|
||||
// stem bottom vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], stem_height }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem top vertices
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, { sines[i], cosines[i], 0.0f });
|
||||
}
|
||||
|
||||
// stem triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
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, v3, v2);
|
||||
|
@ -236,31 +465,50 @@ GLModelInitializationData stilized_arrow(int resolution, float tip_radius, float
|
|||
|
||||
// stem cap vertices
|
||||
append_vertex(data, Vec3f::Zero(), -Vec3f::UnitZ());
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_vertex(data, { stem_radius * sines[i], stem_radius * cosines[i], 0.0f }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// stem cap triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
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, v3, i + 5 * resolution + 2);
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
|
||||
entity.positions.emplace_back(position);
|
||||
entity.normals.emplace_back(normal);
|
||||
};
|
||||
auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
|
||||
entity.indices.emplace_back(v1);
|
||||
entity.indices.emplace_back(v2);
|
||||
entity.indices.emplace_back(v3);
|
||||
};
|
||||
#else
|
||||
GLModelInitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
data.positions.emplace_back(position);
|
||||
data.normals.emplace_back(normal);
|
||||
};
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
resolution = std::max(2, resolution);
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
GLModel::InitializationData data;
|
||||
GLModel::InitializationData::Entity entity;
|
||||
entity.type = GLModel::PrimitiveType::Triangles;
|
||||
#else
|
||||
GLModelInitializationData data;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
const float half_thickness = 0.5f * thickness;
|
||||
const float half_stem_width = 0.5f * stem_width;
|
||||
|
@ -270,6 +518,153 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
const float inner_radius = radius - half_stem_width;
|
||||
const float step_angle = 0.5f * PI / static_cast<float>(resolution);
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
// tip
|
||||
// top face vertices
|
||||
append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { -tip_height, radius, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitZ());
|
||||
|
||||
// top face triangles
|
||||
append_indices(entity, 0, 1, 2);
|
||||
append_indices(entity, 0, 2, 4);
|
||||
append_indices(entity, 4, 2, 3);
|
||||
|
||||
// bottom face vertices
|
||||
append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { -tip_height, radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, -Vec3f::UnitZ());
|
||||
|
||||
// bottom face triangles
|
||||
append_indices(entity, 5, 7, 6);
|
||||
append_indices(entity, 5, 9, 7);
|
||||
append_indices(entity, 9, 8, 7);
|
||||
|
||||
// side faces vertices
|
||||
append_vertex(entity, { 0.0f, outer_radius, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
Vec3f normal(-half_tip_width, tip_height, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, -half_thickness }, normal);
|
||||
append_vertex(entity, { -tip_height, radius, -half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0f, radius + half_tip_width, half_thickness }, normal);
|
||||
append_vertex(entity, { -tip_height, radius, half_thickness }, normal);
|
||||
|
||||
normal = Vec3f(-half_tip_width, -tip_height, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(entity, { -tip_height, radius, -half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, normal);
|
||||
append_vertex(entity, { -tip_height, radius, half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, normal);
|
||||
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, inner_radius, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, radius - half_tip_width, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const int ii = i * 4;
|
||||
append_indices(entity, 10 + ii, 11 + ii, 13 + ii);
|
||||
append_indices(entity, 10 + ii, 13 + ii, 12 + ii);
|
||||
}
|
||||
|
||||
// stem
|
||||
// top face vertices
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(entity, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(entity, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// top face triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_indices(entity, 26 + i, 27 + i, 27 + resolution + i);
|
||||
append_indices(entity, 27 + i, 28 + resolution + i, 27 + resolution + i);
|
||||
}
|
||||
|
||||
// bottom face vertices
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(entity, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(entity, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// bottom face triangles
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
append_indices(entity, 28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
|
||||
append_indices(entity, 29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
|
||||
}
|
||||
|
||||
// side faces vertices and triangles
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
const float c = ::cos(angle);
|
||||
const float s = ::sin(angle);
|
||||
append_vertex(entity, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
const float c = ::cos(angle);
|
||||
const float s = ::sin(angle);
|
||||
append_vertex(entity, { inner_radius * s, inner_radius * c, half_thickness }, { -s, -c, 0.0f });
|
||||
}
|
||||
|
||||
int first_id = 26 + 4 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int ii = first_id + i;
|
||||
append_indices(entity, ii, ii + 1, ii + resolution + 2);
|
||||
append_indices(entity, ii, ii + resolution + 2, ii + resolution + 1);
|
||||
}
|
||||
|
||||
append_vertex(entity, { inner_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { outer_radius, 0.0f, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { inner_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { outer_radius, 0.0f, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
first_id = 26 + 6 * (resolution + 1);
|
||||
append_indices(entity, first_id, first_id + 1, first_id + 3);
|
||||
append_indices(entity, first_id, first_id + 3, first_id + 2);
|
||||
|
||||
for (int i = resolution; i >= 0; --i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
const float c = ::cos(angle);
|
||||
const float s = ::sin(angle);
|
||||
append_vertex(entity, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = resolution; i >= 0; --i) {
|
||||
const float angle = static_cast<float>(i) * step_angle;
|
||||
const float c = ::cos(angle);
|
||||
const float s = ::sin(angle);
|
||||
append_vertex(entity, { outer_radius * s, outer_radius * c, +half_thickness }, { s, c, 0.0f });
|
||||
}
|
||||
|
||||
first_id = 30 + 6 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
const int ii = first_id + i;
|
||||
append_indices(entity, ii, ii + 1, ii + resolution + 2);
|
||||
append_indices(entity, ii, ii + resolution + 2, ii + resolution + 1);
|
||||
}
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#else
|
||||
// tip
|
||||
// top face vertices
|
||||
append_vertex(data, { 0.0f, outer_radius, half_thickness }, Vec3f::UnitZ());
|
||||
|
@ -321,8 +716,7 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
append_vertex(data, { 0.0f, inner_radius, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int ii = i * 4;
|
||||
data.triangles.emplace_back(10 + ii, 11 + ii, 13 + ii);
|
||||
data.triangles.emplace_back(10 + ii, 13 + ii, 12 + ii);
|
||||
|
@ -330,56 +724,48 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
|
||||
// stem
|
||||
// top face vertices
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), half_thickness }, Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// top face triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
data.triangles.emplace_back(26 + i, 27 + i, 27 + resolution + i);
|
||||
data.triangles.emplace_back(27 + i, 28 + resolution + i, 27 + resolution + i);
|
||||
}
|
||||
|
||||
// bottom face vertices
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { inner_radius * ::sin(angle), inner_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
append_vertex(data, { outer_radius * ::sin(angle), outer_radius * ::cos(angle), -half_thickness }, -Vec3f::UnitZ());
|
||||
}
|
||||
|
||||
// bottom face triangles
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
data.triangles.emplace_back(28 + 2 * resolution + i, 29 + 3 * resolution + i, 29 + 2 * resolution + i);
|
||||
data.triangles.emplace_back(29 + 2 * resolution + i, 29 + 3 * resolution + i, 30 + 3 * resolution + i);
|
||||
}
|
||||
|
||||
// side faces vertices and triangles
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { inner_radius * s, inner_radius * c, -half_thickness }, { -s, -c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = 0; i <= resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i <= resolution; ++i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
|
@ -387,8 +773,7 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
}
|
||||
|
||||
int first_id = 26 + 4 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
int ii = first_id + i;
|
||||
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
|
||||
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
|
||||
|
@ -403,16 +788,14 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
data.triangles.emplace_back(first_id, first_id + 1, first_id + 3);
|
||||
data.triangles.emplace_back(first_id, first_id + 3, first_id + 2);
|
||||
|
||||
for (int i = resolution; i >= 0; --i)
|
||||
{
|
||||
for (int i = resolution; i >= 0; --i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
append_vertex(data, { outer_radius * s, outer_radius * c, -half_thickness }, { s, c, 0.0f });
|
||||
}
|
||||
|
||||
for (int i = resolution; i >= 0; --i)
|
||||
{
|
||||
for (int i = resolution; i >= 0; --i) {
|
||||
float angle = static_cast<float>(i) * step_angle;
|
||||
float c = ::cos(angle);
|
||||
float s = ::sin(angle);
|
||||
|
@ -420,16 +803,33 @@ GLModelInitializationData circular_arrow(int resolution, float radius, float tip
|
|||
}
|
||||
|
||||
first_id = 30 + 6 * (resolution + 1);
|
||||
for (int i = 0; i < resolution; ++i)
|
||||
{
|
||||
for (int i = 0; i < resolution; ++i) {
|
||||
int ii = first_id + i;
|
||||
data.triangles.emplace_back(ii, ii + 1, ii + resolution + 2);
|
||||
data.triangles.emplace_back(ii, ii + resolution + 2, ii + resolution + 1);
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModel::InitializationData::Entity& entity, const Vec3f& position, const Vec3f& normal) {
|
||||
entity.positions.emplace_back(position);
|
||||
entity.normals.emplace_back(normal);
|
||||
};
|
||||
auto append_indices = [](GLModel::InitializationData::Entity& entity, unsigned int v1, unsigned int v2, unsigned int v3) {
|
||||
entity.indices.emplace_back(v1);
|
||||
entity.indices.emplace_back(v2);
|
||||
entity.indices.emplace_back(v3);
|
||||
};
|
||||
|
||||
GLModel::InitializationData data;
|
||||
GLModel::InitializationData::Entity entity;
|
||||
entity.type = GLModel::PrimitiveType::Triangles;
|
||||
#else
|
||||
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
|
||||
{
|
||||
auto append_vertex = [](GLModelInitializationData& data, const Vec3f& position, const Vec3f& normal) {
|
||||
|
@ -438,6 +838,7 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
|
|||
};
|
||||
|
||||
GLModelInitializationData data;
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
const float half_thickness = 0.5f * thickness;
|
||||
const float half_stem_width = 0.5f * stem_width;
|
||||
|
@ -445,6 +846,87 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
|
|||
const float total_height = tip_height + stem_height;
|
||||
|
||||
// top face vertices
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0, total_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
|
||||
|
||||
// top face triangles
|
||||
append_indices(entity, 0, 1, 6);
|
||||
append_indices(entity, 6, 1, 5);
|
||||
append_indices(entity, 4, 5, 3);
|
||||
append_indices(entity, 5, 1, 3);
|
||||
append_indices(entity, 1, 2, 3);
|
||||
|
||||
// bottom face vertices
|
||||
append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { 0.0, total_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitZ());
|
||||
append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitZ());
|
||||
|
||||
// bottom face triangles
|
||||
append_indices(entity, 7, 13, 8);
|
||||
append_indices(entity, 13, 12, 8);
|
||||
append_indices(entity, 12, 11, 10);
|
||||
append_indices(entity, 8, 12, 10);
|
||||
append_indices(entity, 9, 8, 10);
|
||||
|
||||
// side faces vertices
|
||||
append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitX());
|
||||
append_vertex(entity, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitX());
|
||||
|
||||
append_vertex(entity, { half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
Vec3f normal(tip_height, half_tip_width, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(entity, { half_tip_width, stem_height, -half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0, total_height, -half_thickness }, normal);
|
||||
append_vertex(entity, { half_tip_width, stem_height, half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0, total_height, half_thickness }, normal);
|
||||
|
||||
normal = Vec3f(-tip_height, half_tip_width, 0.0f);
|
||||
normal.normalize();
|
||||
append_vertex(entity, { 0.0, total_height, -half_thickness }, normal);
|
||||
append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, normal);
|
||||
append_vertex(entity, { 0.0, total_height, half_thickness }, normal);
|
||||
append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, normal);
|
||||
|
||||
append_vertex(entity, { -half_tip_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { -half_tip_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
append_vertex(entity, { -half_stem_width, stem_height, -half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(entity, { -half_stem_width, stem_height, half_thickness }, -Vec3f::UnitX());
|
||||
append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitX());
|
||||
|
||||
append_vertex(entity, { -half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { half_stem_width, 0.0, -half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { -half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
|
||||
append_vertex(entity, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
const int ii = i * 4;
|
||||
append_indices(entity, 14 + ii, 15 + ii, 17 + ii);
|
||||
append_indices(entity, 14 + ii, 17 + ii, 16 + ii);
|
||||
}
|
||||
|
||||
data.entities.emplace_back(entity);
|
||||
#else
|
||||
append_vertex(data, { half_stem_width, 0.0, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { half_stem_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
append_vertex(data, { half_tip_width, stem_height, half_thickness }, Vec3f::UnitZ());
|
||||
|
@ -517,12 +999,12 @@ GLModelInitializationData straight_arrow(float tip_width, float tip_height, floa
|
|||
append_vertex(data, { half_stem_width, 0.0, half_thickness }, -Vec3f::UnitY());
|
||||
|
||||
// side face triangles
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
int ii = i * 4;
|
||||
data.triangles.emplace_back(14 + ii, 15 + ii, 17 + ii);
|
||||
data.triangles.emplace_back(14 + ii, 17 + ii, 16 + ii);
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -12,40 +12,115 @@ class TriangleMesh;
|
|||
|
||||
namespace GUI {
|
||||
|
||||
#if !ENABLE_SEQUENTIAL_LIMITS
|
||||
struct GLModelInitializationData
|
||||
{
|
||||
std::vector<Vec3f> positions;
|
||||
std::vector<Vec3f> normals;
|
||||
std::vector<Vec3i> triangles;
|
||||
};
|
||||
#endif // !ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
class GLModel
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
public:
|
||||
enum class PrimitiveType : unsigned char
|
||||
{
|
||||
Triangles,
|
||||
Lines,
|
||||
LineStrip,
|
||||
LineLoop
|
||||
};
|
||||
|
||||
struct RenderData
|
||||
{
|
||||
PrimitiveType type;
|
||||
unsigned int vbo_id{ 0 };
|
||||
unsigned int ibo_id{ 0 };
|
||||
size_t indices_count{ 0 };
|
||||
std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
};
|
||||
|
||||
struct InitializationData
|
||||
{
|
||||
struct Entity
|
||||
{
|
||||
PrimitiveType type;
|
||||
std::vector<Vec3f> positions;
|
||||
std::vector<Vec3f> normals;
|
||||
std::vector<unsigned int> indices;
|
||||
std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
};
|
||||
|
||||
std::vector<Entity> entities;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<RenderData> m_render_data;
|
||||
#else
|
||||
unsigned int m_vbo_id{ 0 };
|
||||
unsigned int m_ibo_id{ 0 };
|
||||
size_t m_indices_count{ 0 };
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
std::string m_filename;
|
||||
|
||||
public:
|
||||
GLModel() = default;
|
||||
virtual ~GLModel() { reset(); }
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void init_from(const InitializationData& data);
|
||||
#else
|
||||
void init_from(const GLModelInitializationData& data);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
void init_from(const TriangleMesh& mesh);
|
||||
bool init_from_file(const std::string& filename);
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
// if entity_id == -1 set the color of all entities
|
||||
void set_color(int entity_id, const std::array<float, 4>& color);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
void reset();
|
||||
void render() const;
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
bool is_initialized() const { return !m_render_data.empty(); }
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
|
||||
const std::string& get_filename() const { return m_filename; }
|
||||
|
||||
private:
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
void send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
|
||||
#else
|
||||
void send_to_gpu(const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
};
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
// 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 arrow has its axis of symmetry along the Z axis and is pointing upward
|
||||
// used to render bed axes and sequential marker
|
||||
GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height);
|
||||
|
||||
// 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 arrow is contained in the 1st quadrant of the XY plane and is pointing counterclockwise
|
||||
// used to render sidebar hints for rotations
|
||||
GLModel::InitializationData circular_arrow(int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness);
|
||||
|
||||
// create an arrow with the given dimensions
|
||||
// the origin of the arrow is in the center of the stem cap
|
||||
// the arrow is contained in XY plane and has its main axis along the Y axis
|
||||
// used to render sidebar hints for position and scale
|
||||
GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness);
|
||||
#else
|
||||
// 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 arrow has its axis of symmetry along the Z axis and is pointing upward
|
||||
|
@ -60,6 +135,7 @@ namespace GUI {
|
|||
// the origin of the arrow is in the center of the stem cap
|
||||
// the arrow is contained in XY plane and has its main axis along the Y axis
|
||||
GLModelInitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -26,8 +26,6 @@ static const float DEFAULT_HIGHLIGHT_COLOR[4] = { 1.0f, 0.38f, 0.0f, 1.0f };
|
|||
static const float AXES_COLOR[][4] = { { 0.75f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.75f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.75f, 1.0f } };
|
||||
static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
|
||||
|
||||
|
||||
class ImGuiWrapper;
|
||||
class GLCanvas3D;
|
||||
enum class CommonGizmosDataID;
|
||||
|
|
|
@ -2828,12 +2828,12 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||
|
||||
// If the update_background_process() was not called by the timer, kill the timer,
|
||||
// so the update_restart_background_process() will not be called again in vain.
|
||||
this->background_process_timer.Stop();
|
||||
background_process_timer.Stop();
|
||||
// Update the "out of print bed" state of ModelInstances.
|
||||
this->update_print_volume_state();
|
||||
update_print_volume_state();
|
||||
// Apply new config to the possibly running background task.
|
||||
bool was_running = this->background_process.running();
|
||||
Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config());
|
||||
bool was_running = background_process.running();
|
||||
Print::ApplyStatus invalidated = background_process.apply(q->model(), wxGetApp().preset_bundle->full_config());
|
||||
|
||||
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
|
||||
if (view3D->is_layers_editing_enabled())
|
||||
|
@ -2842,40 +2842,56 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||
if (invalidated == Print::APPLY_STATUS_INVALIDATED) {
|
||||
// Some previously calculated data on the Print was invalidated.
|
||||
// Hide the slicing results, as the current slicing status is no more valid.
|
||||
this->sidebar->show_sliced_info_sizer(false);
|
||||
sidebar->show_sliced_info_sizer(false);
|
||||
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
|
||||
// Otherwise they will be just refreshed.
|
||||
if (this->preview != nullptr) {
|
||||
if (preview != nullptr) {
|
||||
// If the preview is not visible, the following line just invalidates the preview,
|
||||
// but the G-code paths or SLA preview are calculated first once the preview is made visible.
|
||||
reset_gcode_toolpaths();
|
||||
this->preview->reload_print();
|
||||
preview->reload_print();
|
||||
}
|
||||
// In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
|
||||
// In SLA mode, we need to reload the 3D scene every time to show the support structures.
|
||||
if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower")))
|
||||
if (printer_technology == ptSLA || (printer_technology == ptFFF && config->opt_bool("wipe_tower")))
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
|
||||
}
|
||||
|
||||
if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! this->background_process.empty()) {
|
||||
if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! background_process.empty()) {
|
||||
// The delayed error message is no more valid.
|
||||
this->delayed_error_message.clear();
|
||||
delayed_error_message.clear();
|
||||
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
|
||||
std::string warning;
|
||||
std::string err = this->background_process.validate(&warning);
|
||||
std::string err = background_process.validate(&warning);
|
||||
if (err.empty()) {
|
||||
notification_manager->set_all_slicing_errors_gray(true);
|
||||
if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled())
|
||||
if (invalidated != Print::APPLY_STATUS_UNCHANGED && background_processing_enabled())
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_RESTART;
|
||||
|
||||
// Pass a warning from validation and either show a notification,
|
||||
// or hide the old one.
|
||||
process_validation_warning(warning);
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (printer_technology == ptFFF) {
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance(Polygons());
|
||||
view3D->get_canvas3d()->set_as_dirty();
|
||||
view3D->get_canvas3d()->request_extra_frame();
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
} else {
|
||||
// The print is not valid.
|
||||
// Show error as notification.
|
||||
notification_manager->push_slicing_error_notification(err);
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (printer_technology == ptFFF) {
|
||||
const Print* print = background_process.fff_print();
|
||||
Polygons polygons;
|
||||
if (print->config().complete_objects)
|
||||
Print::sequential_print_horizontal_clearance_valid(*print, &polygons);
|
||||
view3D->get_canvas3d()->set_sequential_print_clearance(polygons);
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
} else if (! this->delayed_error_message.empty()) {
|
||||
|
@ -3011,8 +3027,7 @@ void Plater::priv::update_fff_scene()
|
|||
if (this->preview != nullptr)
|
||||
this->preview->reload_print();
|
||||
// In case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
|
||||
view3D->reload_scene(true);
|
||||
|
||||
view3D->reload_scene(true);
|
||||
}
|
||||
|
||||
void Plater::priv::update_sla_scene()
|
||||
|
|
|
@ -18,7 +18,11 @@
|
|||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
static const std::array<float, 4> UNIFORM_SCALE_COLOR = { 0.923f, 0.504f, 0.264f, 1.0f };
|
||||
#else
|
||||
static const float UNIFORM_SCALE_COLOR[4] = { 0.923f, 0.504f, 0.264f, 1.0f };
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -1869,8 +1873,31 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons
|
|||
glsafe(::glEnd());
|
||||
}
|
||||
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
static std::array<float, 4> get_color(Axis axis)
|
||||
{
|
||||
return { AXES_COLOR[axis][0], AXES_COLOR[axis][1], AXES_COLOR[axis][2], AXES_COLOR[axis][3] };
|
||||
};
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
if (boost::ends_with(sidebar_field, "x")) {
|
||||
glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0));
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(X));
|
||||
m_arrow.render();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "y")) {
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(Y));
|
||||
m_arrow.render();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "z")) {
|
||||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, get_color(Z));
|
||||
m_arrow.render();
|
||||
}
|
||||
#else
|
||||
auto set_color = [](Axis axis) {
|
||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
if (shader != nullptr)
|
||||
|
@ -1889,10 +1916,33 @@ void Selection::render_sidebar_position_hints(const std::string& sidebar_field)
|
|||
glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
|
||||
m_arrow.render();
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const
|
||||
{
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
auto render_sidebar_rotation_hint = [this]() {
|
||||
m_curved_arrow.render();
|
||||
glsafe(::glRotated(180.0, 0.0, 0.0, 1.0));
|
||||
m_curved_arrow.render();
|
||||
};
|
||||
|
||||
if (boost::ends_with(sidebar_field, "x")) {
|
||||
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
|
||||
const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(X));
|
||||
render_sidebar_rotation_hint();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "y")) {
|
||||
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
|
||||
const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(Y));
|
||||
render_sidebar_rotation_hint();
|
||||
}
|
||||
else if (boost::ends_with(sidebar_field, "z")) {
|
||||
const_cast<GLModel*>(&m_curved_arrow)->set_color(-1, get_color(Z));
|
||||
render_sidebar_rotation_hint();
|
||||
}
|
||||
#else
|
||||
auto set_color = [](Axis axis) {
|
||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
if (shader != nullptr)
|
||||
|
@ -1917,6 +1967,7 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field)
|
|||
set_color(Z);
|
||||
render_sidebar_rotation_hint();
|
||||
}
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
}
|
||||
|
||||
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const
|
||||
|
@ -1924,9 +1975,13 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con
|
|||
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
|
||||
|
||||
auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) {
|
||||
#if ENABLE_SEQUENTIAL_LIMITS
|
||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis));
|
||||
#else
|
||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
if (shader != nullptr)
|
||||
shader->set_uniform("uniform_color", uniform_scale ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis], 4);
|
||||
#endif // ENABLE_SEQUENTIAL_LIMITS
|
||||
|
||||
glsafe(::glTranslated(0.0, 5.0, 0.0));
|
||||
m_arrow.render();
|
||||
|
|
Loading…
Add table
Reference in a new issue