mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
Tech ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL - Replace GLIndexedVertexArray with GLModel: GLVolume geometry + removed class GLIndexedVertexArray from codebase
(cherry picked from commit prusa3d/PrusaSlicer@1eac357739)
This commit is contained in:
parent
d85bbcba50
commit
d09dc36ff1
16 changed files with 765 additions and 1130 deletions
|
@ -2353,7 +2353,7 @@ int CLI::run(int argc, char **argv)
|
||||||
// continue;
|
// continue;
|
||||||
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
||||||
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
||||||
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, true, false, true);
|
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, false, true);
|
||||||
//glvolume_collection.volumes.back()->geometry_id = key.geometry_id;
|
//glvolume_collection.volumes.back()->geometry_id = key.geometry_id;
|
||||||
std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00";
|
std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00";
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,9 @@ public:
|
||||||
// Called on initial G-code preview on OpenGL vertex buffer interleaved normals and vertices.
|
// Called on initial G-code preview on OpenGL vertex buffer interleaved normals and vertices.
|
||||||
bool all_paths_inside_vertices_and_normals_interleaved(const std::vector<float>& paths, const Eigen::AlignedBox<float, 3>& bbox, bool ignore_bottom = true) const;
|
bool all_paths_inside_vertices_and_normals_interleaved(const std::vector<float>& paths, const Eigen::AlignedBox<float, 3>& bbox, bool ignore_bottom = true) const;
|
||||||
|
|
||||||
|
const std::pair<std::vector<Vec2d>, std::vector<Vec2d>>& top_bottom_convex_hull_decomposition_scene() const { return m_top_bottom_convex_hull_decomposition_scene; }
|
||||||
|
const std::pair<std::vector<Vec2d>, std::vector<Vec2d>>& top_bottom_convex_hull_decomposition_bed() const { return m_top_bottom_convex_hull_decomposition_bed; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Source definition of the print bed geometry (PrintConfig::printable_area)
|
// Source definition of the print bed geometry (PrintConfig::printable_area)
|
||||||
std::vector<Vec2d> m_bed_shape;
|
std::vector<Vec2d> m_bed_shape;
|
||||||
|
|
|
@ -131,8 +131,8 @@ set(SLIC3R_GUI_SOURCES
|
||||||
GUI/Gizmos/GLGizmoSimplify.hpp
|
GUI/Gizmos/GLGizmoSimplify.hpp
|
||||||
GUI/Gizmos/GLGizmoMmuSegmentation.cpp
|
GUI/Gizmos/GLGizmoMmuSegmentation.cpp
|
||||||
GUI/Gizmos/GLGizmoMmuSegmentation.hpp
|
GUI/Gizmos/GLGizmoMmuSegmentation.hpp
|
||||||
GUI/Gizmos/GLGizmoFaceDetector.cpp
|
#GUI/Gizmos/GLGizmoFaceDetector.cpp
|
||||||
GUI/Gizmos/GLGizmoFaceDetector.hpp
|
#GUI/Gizmos/GLGizmoFaceDetector.hpp
|
||||||
GUI/Gizmos/GLGizmoSeam.cpp
|
GUI/Gizmos/GLGizmoSeam.cpp
|
||||||
GUI/Gizmos/GLGizmoSeam.hpp
|
GUI/Gizmos/GLGizmoSeam.hpp
|
||||||
GUI/Gizmos/GLGizmoText.cpp
|
GUI/Gizmos/GLGizmoText.cpp
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,207 +57,6 @@ using ModelObjectPtrs = std::vector<ModelObject*>;
|
||||||
// Return appropriate color based on the ModelVolume.
|
// Return appropriate color based on the ModelVolume.
|
||||||
extern ColorRGBA color_from_model_volume(const ModelVolume& model_volume);
|
extern ColorRGBA color_from_model_volume(const ModelVolume& model_volume);
|
||||||
|
|
||||||
// A container for interleaved arrays of 3D vertices and normals,
|
|
||||||
// possibly indexed by triangles and / or quads.
|
|
||||||
class GLIndexedVertexArray {
|
|
||||||
public:
|
|
||||||
// Only Eigen types of Nx16 size are vectorized. This bounding box will not be vectorized.
|
|
||||||
static_assert(sizeof(Eigen::AlignedBox<float, 3>) == 24, "Eigen::AlignedBox<float, 3> is not being vectorized, thus it does not need to be aligned");
|
|
||||||
using BoundingBox = Eigen::AlignedBox<float, 3>;
|
|
||||||
|
|
||||||
GLIndexedVertexArray() { m_bounding_box.setEmpty(); }
|
|
||||||
GLIndexedVertexArray(const GLIndexedVertexArray &rhs) :
|
|
||||||
vertices_and_normals_interleaved(rhs.vertices_and_normals_interleaved),
|
|
||||||
triangle_indices(rhs.triangle_indices),
|
|
||||||
quad_indices(rhs.quad_indices),
|
|
||||||
m_bounding_box(rhs.m_bounding_box)
|
|
||||||
{ assert(!rhs.has_VBOs()); m_bounding_box.setEmpty(); }
|
|
||||||
GLIndexedVertexArray(GLIndexedVertexArray &&rhs) :
|
|
||||||
vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)),
|
|
||||||
triangle_indices(std::move(rhs.triangle_indices)),
|
|
||||||
quad_indices(std::move(rhs.quad_indices)),
|
|
||||||
m_bounding_box(rhs.m_bounding_box)
|
|
||||||
{ assert(! rhs.has_VBOs()); }
|
|
||||||
|
|
||||||
~GLIndexedVertexArray() { release_geometry(); }
|
|
||||||
|
|
||||||
GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs)
|
|
||||||
{
|
|
||||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
assert(triangle_indices_VBO_id == 0);
|
|
||||||
assert(quad_indices_VBO_id == 0);
|
|
||||||
assert(rhs.vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
assert(rhs.triangle_indices_VBO_id == 0);
|
|
||||||
assert(rhs.quad_indices_VBO_id == 0);
|
|
||||||
this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved;
|
|
||||||
this->triangle_indices = rhs.triangle_indices;
|
|
||||||
this->quad_indices = rhs.quad_indices;
|
|
||||||
this->m_bounding_box = rhs.m_bounding_box;
|
|
||||||
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
|
||||||
this->triangle_indices_size = rhs.triangle_indices_size;
|
|
||||||
this->quad_indices_size = rhs.quad_indices_size;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLIndexedVertexArray& operator=(GLIndexedVertexArray &&rhs)
|
|
||||||
{
|
|
||||||
assert(vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
assert(triangle_indices_VBO_id == 0);
|
|
||||||
assert(quad_indices_VBO_id == 0);
|
|
||||||
assert(rhs.vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
assert(rhs.triangle_indices_VBO_id == 0);
|
|
||||||
assert(rhs.quad_indices_VBO_id == 0);
|
|
||||||
this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved);
|
|
||||||
this->triangle_indices = std::move(rhs.triangle_indices);
|
|
||||||
this->quad_indices = std::move(rhs.quad_indices);
|
|
||||||
this->m_bounding_box = rhs.m_bounding_box;
|
|
||||||
this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size;
|
|
||||||
this->triangle_indices_size = rhs.triangle_indices_size;
|
|
||||||
this->quad_indices_size = rhs.quad_indices_size;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x)
|
|
||||||
std::vector<float> vertices_and_normals_interleaved;
|
|
||||||
std::vector<int> triangle_indices;
|
|
||||||
std::vector<int> quad_indices;
|
|
||||||
|
|
||||||
// When the geometry data is loaded into the graphics card as Vertex Buffer Objects,
|
|
||||||
// the above mentioned std::vectors are cleared and the following variables keep their original length.
|
|
||||||
size_t vertices_and_normals_interleaved_size{ 0 };
|
|
||||||
size_t triangle_indices_size{ 0 };
|
|
||||||
size_t quad_indices_size{ 0 };
|
|
||||||
|
|
||||||
// IDs of the Vertex Array Objects, into which the geometry has been loaded.
|
|
||||||
// Zero if the VBOs are not sent to GPU yet.
|
|
||||||
unsigned int vertices_and_normals_interleaved_VBO_id{ 0 };
|
|
||||||
unsigned int triangle_indices_VBO_id{ 0 };
|
|
||||||
unsigned int quad_indices_VBO_id{ 0 };
|
|
||||||
|
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
|
||||||
void load_mesh_full_shading(const TriangleMesh& mesh, bool smooth_normals = false);
|
|
||||||
void load_mesh(const TriangleMesh& mesh, bool smooth_normals = false) { this->load_mesh_full_shading(mesh, smooth_normals); }
|
|
||||||
#else
|
|
||||||
void load_mesh_full_shading(const TriangleMesh& mesh);
|
|
||||||
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
|
|
||||||
#endif // ENABLE_SMOOTH_NORMALS
|
|
||||||
|
|
||||||
void load_its_flat_shading(const indexed_triangle_set &its);
|
|
||||||
|
|
||||||
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
|
|
||||||
|
|
||||||
inline void reserve(size_t sz) {
|
|
||||||
this->vertices_and_normals_interleaved.reserve(sz * 6);
|
|
||||||
this->triangle_indices.reserve(sz * 3);
|
|
||||||
this->quad_indices.reserve(sz * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void push_geometry(float x, float y, float z, float nx, float ny, float nz) {
|
|
||||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this->vertices_and_normals_interleaved.size() + 6 > this->vertices_and_normals_interleaved.capacity())
|
|
||||||
this->vertices_and_normals_interleaved.reserve(next_highest_power_of_2(this->vertices_and_normals_interleaved.size() + 6));
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(nx);
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(ny);
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(nz);
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(x);
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(y);
|
|
||||||
this->vertices_and_normals_interleaved.emplace_back(z);
|
|
||||||
|
|
||||||
this->vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
|
||||||
m_bounding_box.extend(Vec3f(x, y, z));
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void push_geometry(double x, double y, double z, double nx, double ny, double nz) {
|
|
||||||
push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Derived, typename Derived2>
|
|
||||||
inline void push_geometry(const Eigen::MatrixBase<Derived>& p, const Eigen::MatrixBase<Derived2>& n) {
|
|
||||||
push_geometry(float(p(0)), float(p(1)), float(p(2)), float(n(0)), float(n(1)), float(n(2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void push_triangle(int idx1, int idx2, int idx3) {
|
|
||||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity())
|
|
||||||
this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3));
|
|
||||||
this->triangle_indices.emplace_back(idx1);
|
|
||||||
this->triangle_indices.emplace_back(idx2);
|
|
||||||
this->triangle_indices.emplace_back(idx3);
|
|
||||||
this->triangle_indices_size = this->triangle_indices.size();
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void push_quad(int idx1, int idx2, int idx3, int idx4) {
|
|
||||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this->quad_indices.size() + 4 > this->vertices_and_normals_interleaved.capacity())
|
|
||||||
this->quad_indices.reserve(next_highest_power_of_2(this->quad_indices.size() + 4));
|
|
||||||
this->quad_indices.emplace_back(idx1);
|
|
||||||
this->quad_indices.emplace_back(idx2);
|
|
||||||
this->quad_indices.emplace_back(idx3);
|
|
||||||
this->quad_indices.emplace_back(idx4);
|
|
||||||
this->quad_indices_size = this->quad_indices.size();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Finalize the initialization of the geometry & indices,
|
|
||||||
// upload the geometry and indices to OpenGL VBO objects
|
|
||||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
|
||||||
void finalize_geometry(bool opengl_initialized);
|
|
||||||
// Release the geometry data, release OpenGL VBOs.
|
|
||||||
void release_geometry();
|
|
||||||
|
|
||||||
void render() const;
|
|
||||||
void render(const std::pair<size_t, size_t>& tverts_range, const std::pair<size_t, size_t>& qverts_range) const;
|
|
||||||
|
|
||||||
// Is there any geometry data stored?
|
|
||||||
bool empty() const { return vertices_and_normals_interleaved_size == 0; }
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
this->vertices_and_normals_interleaved.clear();
|
|
||||||
this->triangle_indices.clear();
|
|
||||||
this->quad_indices.clear();
|
|
||||||
vertices_and_normals_interleaved_size = 0;
|
|
||||||
triangle_indices_size = 0;
|
|
||||||
quad_indices_size = 0;
|
|
||||||
m_bounding_box.setEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shrink the internal storage to tighly fit the data stored.
|
|
||||||
void shrink_to_fit() {
|
|
||||||
this->vertices_and_normals_interleaved.shrink_to_fit();
|
|
||||||
this->triangle_indices.shrink_to_fit();
|
|
||||||
this->quad_indices.shrink_to_fit();
|
|
||||||
}
|
|
||||||
|
|
||||||
const BoundingBox& bounding_box() const { return m_bounding_box; }
|
|
||||||
|
|
||||||
// Return an estimate of the memory consumed by this class.
|
|
||||||
size_t cpu_memory_used() const { return sizeof(*this) + vertices_and_normals_interleaved.capacity() * sizeof(float) + triangle_indices.capacity() * sizeof(int) + quad_indices.capacity() * sizeof(int); }
|
|
||||||
// Return an estimate of the memory held by GPU vertex buffers.
|
|
||||||
size_t gpu_memory_used() const
|
|
||||||
{
|
|
||||||
size_t memsize = 0;
|
|
||||||
if (this->vertices_and_normals_interleaved_VBO_id != 0)
|
|
||||||
memsize += this->vertices_and_normals_interleaved_size * 4;
|
|
||||||
if (this->triangle_indices_VBO_id != 0)
|
|
||||||
memsize += this->triangle_indices_size * 4;
|
|
||||||
if (this->quad_indices_VBO_id != 0)
|
|
||||||
memsize += this->quad_indices_size * 4;
|
|
||||||
return memsize;
|
|
||||||
}
|
|
||||||
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
BoundingBox m_bounding_box;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GLVolume {
|
class GLVolume {
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -400,15 +199,13 @@ public:
|
||||||
// Is mouse or rectangle selection over this object to select/deselect it ?
|
// Is mouse or rectangle selection over this object to select/deselect it ?
|
||||||
EHoverState hover;
|
EHoverState hover;
|
||||||
|
|
||||||
// Interleaved triangles & normals with indexed triangles & quads.
|
GUI::GLModel model;
|
||||||
GLIndexedVertexArray indexed_vertex_array;
|
|
||||||
// BBS
|
// BBS
|
||||||
mutable std::vector<GLIndexedVertexArray> mmuseg_ivas;
|
mutable std::vector<GUI::GLModel> mmuseg_models;
|
||||||
mutable ObjectBase::Timestamp mmuseg_ts;
|
mutable ObjectBase::Timestamp mmuseg_ts;
|
||||||
|
|
||||||
// Ranges of triangle and quad indices to be rendered.
|
// Ranges of triangle and quad indices to be rendered.
|
||||||
std::pair<size_t, size_t> tverts_range;
|
std::pair<size_t, size_t> tverts_range;
|
||||||
std::pair<size_t, size_t> qverts_range;
|
|
||||||
|
|
||||||
// If the qverts or tverts contain thick extrusions, then offsets keeps pointers of the starts
|
// If the qverts or tverts contain thick extrusions, then offsets keeps pointers of the starts
|
||||||
// of the extrusions per layer.
|
// of the extrusions per layer.
|
||||||
|
@ -418,13 +215,7 @@ public:
|
||||||
|
|
||||||
// Bounding box of this volume, in unscaled coordinates.
|
// Bounding box of this volume, in unscaled coordinates.
|
||||||
BoundingBoxf3 bounding_box() const {
|
BoundingBoxf3 bounding_box() const {
|
||||||
BoundingBoxf3 out;
|
return this->model.get_bounding_box();
|
||||||
if (! this->indexed_vertex_array.bounding_box().isEmpty()) {
|
|
||||||
out.min = this->indexed_vertex_array.bounding_box().min().cast<double>();
|
|
||||||
out.max = this->indexed_vertex_array.bounding_box().max().cast<double>();
|
|
||||||
out.defined = true;
|
|
||||||
};
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_color(const ColorRGBA& rgba) { color = rgba; }
|
void set_color(const ColorRGBA& rgba) { color = rgba; }
|
||||||
|
@ -517,18 +308,15 @@ public:
|
||||||
// convex hull
|
// convex hull
|
||||||
const TriangleMesh* convex_hull() const { return m_convex_hull.get(); }
|
const TriangleMesh* convex_hull() const { return m_convex_hull.get(); }
|
||||||
|
|
||||||
bool empty() const { return this->indexed_vertex_array.empty(); }
|
bool empty() const { return this->model.is_empty(); }
|
||||||
|
|
||||||
void set_range(double low, double high);
|
void set_range(double low, double high);
|
||||||
|
|
||||||
//BBS: add outline related logic and add virtual specifier
|
//BBS: add outline related logic and add virtual specifier
|
||||||
virtual void render(bool with_outline = false) const;
|
virtual void render(bool with_outline = false);
|
||||||
|
|
||||||
//BBS: add simple render function for thumbnail
|
//BBS: add simple render function for thumbnail
|
||||||
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors) const;
|
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors);
|
||||||
|
|
||||||
void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); }
|
|
||||||
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
|
||||||
|
|
||||||
void set_bounding_boxes_as_dirty() {
|
void set_bounding_boxes_as_dirty() {
|
||||||
m_transformed_bounding_box.reset();
|
m_transformed_bounding_box.reset();
|
||||||
|
@ -545,11 +333,11 @@ public:
|
||||||
|
|
||||||
// Return an estimate of the memory consumed by this class.
|
// Return an estimate of the memory consumed by this class.
|
||||||
size_t cpu_memory_used() const {
|
size_t cpu_memory_used() const {
|
||||||
//FIXME what to do wih m_convex_hull?
|
return sizeof(*this) + this->model.cpu_memory_used() + this->print_zs.capacity() * sizeof(coordf_t) +
|
||||||
return sizeof(*this) - sizeof(this->indexed_vertex_array) + this->indexed_vertex_array.cpu_memory_used() + this->print_zs.capacity() * sizeof(coordf_t) + this->offsets.capacity() * sizeof(size_t);
|
this->offsets.capacity() * sizeof(size_t);
|
||||||
}
|
}
|
||||||
// Return an estimate of the memory held by GPU vertex buffers.
|
// Return an estimate of the memory held by GPU vertex buffers.
|
||||||
size_t gpu_memory_used() const { return this->indexed_vertex_array.gpu_memory_used(); }
|
size_t gpu_memory_used() const { return this->model.gpu_memory_used(); }
|
||||||
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -557,9 +345,9 @@ public:
|
||||||
class GLWipeTowerVolume : public GLVolume {
|
class GLWipeTowerVolume : public GLVolume {
|
||||||
public:
|
public:
|
||||||
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
||||||
virtual void render(bool with_outline = false) const;
|
virtual void render(bool with_outline = false);
|
||||||
|
|
||||||
std::vector<GLIndexedVertexArray> iva_per_colors;
|
std::vector<GUI::GLModel> model_per_colors;
|
||||||
bool IsTransparent();
|
bool IsTransparent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -627,17 +415,15 @@ public:
|
||||||
~GLVolumeCollection() { clear(); }
|
~GLVolumeCollection() { clear(); }
|
||||||
|
|
||||||
std::vector<int> load_object(
|
std::vector<int> load_object(
|
||||||
const ModelObject *model_object,
|
const ModelObject* model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
const std::vector<int> &instance_idxs,
|
const std::vector<int>& instance_idxs);
|
||||||
bool opengl_initialized);
|
|
||||||
|
|
||||||
int load_object_volume(
|
int load_object_volume(
|
||||||
const ModelObject *model_object,
|
const ModelObject* model_object,
|
||||||
int obj_idx,
|
int obj_idx,
|
||||||
int volume_idx,
|
int volume_idx,
|
||||||
int instance_idx,
|
int instance_idx,
|
||||||
bool opengl_initialized,
|
|
||||||
bool in_assemble_view = false,
|
bool in_assemble_view = false,
|
||||||
bool use_loaded_id = false);
|
bool use_loaded_id = false);
|
||||||
|
|
||||||
|
@ -649,14 +435,13 @@ public:
|
||||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||||
SLAPrintObjectStep milestone,
|
SLAPrintObjectStep milestone,
|
||||||
// Timestamp of the last change of the milestone
|
// Timestamp of the last change of the milestone
|
||||||
size_t timestamp,
|
size_t timestamp);
|
||||||
bool opengl_initialized);
|
|
||||||
|
|
||||||
int load_wipe_tower_preview(
|
int load_wipe_tower_preview(
|
||||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
|
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width);
|
||||||
|
|
||||||
GLVolume* new_toolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0);
|
GLVolume* new_toolpath_volume(const ColorRGBA& rgba);
|
||||||
GLVolume* new_nontoolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0);
|
GLVolume* new_nontoolpath_volume(const ColorRGBA& rgba);
|
||||||
|
|
||||||
int get_selection_support_threshold_angle(bool&) const;
|
int get_selection_support_threshold_angle(bool&) const;
|
||||||
// Render the volumes by OpenGL.
|
// Render the volumes by OpenGL.
|
||||||
|
@ -667,13 +452,6 @@ public:
|
||||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
|
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
|
||||||
bool with_outline = true) const;
|
bool with_outline = true) const;
|
||||||
|
|
||||||
// Finalize the initialization of the geometry & indices,
|
|
||||||
// upload the geometry and indices to OpenGL VBO objects
|
|
||||||
// and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs.
|
|
||||||
void finalize_geometry(bool opengl_initialized) { for (auto* v : volumes) v->finalize_geometry(opengl_initialized); }
|
|
||||||
// Release the geometry data assigned to the volumes.
|
|
||||||
// If OpenGL VBOs were allocated, an OpenGL context has to be active to release them.
|
|
||||||
void release_geometry() { for (auto *v : volumes) v->release_geometry(); }
|
|
||||||
// Clear the geometry
|
// Clear the geometry
|
||||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||||
|
|
||||||
|
@ -724,17 +502,13 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
|
||||||
|
|
||||||
struct _3DScene
|
struct _3DScene
|
||||||
{
|
{
|
||||||
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GUI::GLModel::Geometry& geometry);
|
||||||
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const Polyline &polyline, float width, float height, float print_z, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GUI::GLModel::Geometry& geometry);
|
||||||
static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GLVolume& volume);
|
|
||||||
static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GLVolume& volume);
|
|
||||||
static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume);
|
|
||||||
static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -920,7 +920,7 @@ std::vector<int> GCodeViewer::get_plater_extruder()
|
||||||
|
|
||||||
//BBS: always load shell at preview
|
//BBS: always load shell at preview
|
||||||
void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& print, const BuildVolume& build_volume,
|
void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& print, const BuildVolume& build_volume,
|
||||||
const std::vector<BoundingBoxf3>& exclude_bounding_box, bool initialized, ConfigOptionMode mode, bool only_gcode)
|
const std::vector<BoundingBoxf3>& exclude_bounding_box, ConfigOptionMode mode, bool only_gcode)
|
||||||
{
|
{
|
||||||
// avoid processing if called with the same gcode_result
|
// avoid processing if called with the same gcode_result
|
||||||
if (m_last_result_id == gcode_result.id) {
|
if (m_last_result_id == gcode_result.id) {
|
||||||
|
@ -975,7 +975,7 @@ m_sequential_view.m_show_gcode_window = false;
|
||||||
//BBS: always load shell at preview
|
//BBS: always load shell at preview
|
||||||
/*if (wxGetApp().is_editor())
|
/*if (wxGetApp().is_editor())
|
||||||
{
|
{
|
||||||
//load_shells(print, initialized);
|
load_shells(print);
|
||||||
}
|
}
|
||||||
else {*/
|
else {*/
|
||||||
//BBS: add only gcode mode
|
//BBS: add only gcode mode
|
||||||
|
@ -3088,9 +3088,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: always load shell when preview
|
//BBS: always load shell when preview
|
||||||
void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_previewing)
|
void GCodeViewer::load_shells(const Print& print, bool force_previewing)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": initialized=%1%, force_previewing=%2%")%initialized %force_previewing;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": force_previewing=%1%") %force_previewing;
|
||||||
if ((print.id().id == m_shells.print_id)&&(print.get_modified_count() == m_shells.print_modify_count)) {
|
if ((print.id().id == m_shells.print_id)&&(print.get_modified_count() == m_shells.print_modify_count)) {
|
||||||
//BBS: update force previewing logic
|
//BBS: update force previewing logic
|
||||||
if (force_previewing)
|
if (force_previewing)
|
||||||
|
@ -3138,7 +3138,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p
|
||||||
instance_ids.resize(instance_index);
|
instance_ids.resize(instance_index);
|
||||||
|
|
||||||
size_t current_volumes_count = m_shells.volumes.volumes.size();
|
size_t current_volumes_count = m_shells.volumes.volumes.size();
|
||||||
m_shells.volumes.load_object(model_obj, object_idx, instance_ids, initialized);
|
m_shells.volumes.load_object(model_obj, object_idx, instance_ids);
|
||||||
|
|
||||||
// adjust shells' z if raft is present
|
// adjust shells' z if raft is present
|
||||||
const SlicingParameters& slicing_parameters = obj->slicing_parameters();
|
const SlicingParameters& slicing_parameters = obj->slicing_parameters();
|
||||||
|
@ -4080,14 +4080,6 @@ void GCodeViewer::render_shells()
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// when the background processing is enabled, it may happen that the shells data have been loaded
|
|
||||||
// before opengl has been initialized for the preview canvas.
|
|
||||||
// when this happens, the volumes' data have not been sent to gpu yet.
|
|
||||||
for (GLVolume* v : m_shells.volumes.volumes) {
|
|
||||||
if (!v->indexed_vertex_array.has_VBOs())
|
|
||||||
v->finalize_geometry(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
// glsafe(::glDepthMask(GL_FALSE));
|
// glsafe(::glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
|
|
|
@ -810,7 +810,7 @@ public:
|
||||||
// extract rendering data from the given parameters
|
// extract rendering data from the given parameters
|
||||||
//BBS: add only gcode mode
|
//BBS: add only gcode mode
|
||||||
void load(const GCodeProcessorResult& gcode_result, const Print& print, const BuildVolume& build_volume,
|
void load(const GCodeProcessorResult& gcode_result, const Print& print, const BuildVolume& build_volume,
|
||||||
const std::vector<BoundingBoxf3>& exclude_bounding_box, bool initialized, ConfigOptionMode mode, bool only_gcode = false);
|
const std::vector<BoundingBoxf3>& exclude_bounding_box, ConfigOptionMode mode, bool only_gcode = false);
|
||||||
// recalculate ranges in dependence of what is visible and sets tool/print colors
|
// recalculate ranges in dependence of what is visible and sets tool/print colors
|
||||||
void refresh(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
void refresh(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
||||||
void refresh_render_paths();
|
void refresh_render_paths();
|
||||||
|
@ -820,7 +820,7 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
//BBS: always load shell at preview
|
//BBS: always load shell at preview
|
||||||
void reset_shell();
|
void reset_shell();
|
||||||
void load_shells(const Print& print, bool initialized, bool force_previewing = false);
|
void load_shells(const Print& print, bool force_previewing = false);
|
||||||
void set_shells_on_preview(bool is_previewing) { m_shells.previewing = is_previewing; }
|
void set_shells_on_preview(bool is_previewing) { m_shells.previewing = is_previewing; }
|
||||||
//BBS: add all plates filament statistics
|
//BBS: add all plates filament statistics
|
||||||
void render_all_plates_stats(const std::vector<const GCodeProcessorResult*>& gcode_result_list, bool show = true) const;
|
void render_all_plates_stats(const std::vector<const GCodeProcessorResult*>& gcode_result_list, bool show = true) const;
|
||||||
|
@ -900,7 +900,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void load_toolpaths(const GCodeProcessorResult& gcode_result, const BuildVolume& build_volume, const std::vector<BoundingBoxf3>& exclude_bounding_box);
|
void load_toolpaths(const GCodeProcessorResult& gcode_result, const BuildVolume& build_volume, const std::vector<BoundingBoxf3>& exclude_bounding_box);
|
||||||
//BBS: always load shell at preview
|
//BBS: always load shell at preview
|
||||||
//void load_shells(const Print& print, bool initialized);
|
//void load_shells(const Print& print);
|
||||||
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
||||||
void render_toolpaths();
|
void render_toolpaths();
|
||||||
void render_shells();
|
void render_shells();
|
||||||
|
|
|
@ -97,10 +97,6 @@ void GLCanvas3D::load_render_colors()
|
||||||
|
|
||||||
// Number of floats
|
// Number of floats
|
||||||
static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
|
static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
|
||||||
// Reserve size in number of floats.
|
|
||||||
static constexpr const size_t VERTEX_BUFFER_RESERVE_SIZE = 131072 * 2; // 1.05MB
|
|
||||||
// Reserve size in number of floats, maximum sum of all preallocated buffers.
|
|
||||||
//static constexpr const size_t VERTEX_BUFFER_RESERVE_SIZE_SUM_MAX = 1024 * 1024 * 128 / 4; // 128MB
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -1175,10 +1171,6 @@ bool GLCanvas3D::init()
|
||||||
if (m_main_toolbar.is_enabled())
|
if (m_main_toolbar.is_enabled())
|
||||||
m_layers_editing.init();
|
m_layers_editing.init();
|
||||||
|
|
||||||
// on linux the gl context is not valid until the canvas is not shown on screen
|
|
||||||
// we defer the geometry finalization of volumes until the first call to render()
|
|
||||||
m_volumes.finalize_geometry(true);
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": before gizmo init";
|
BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": before gizmo init";
|
||||||
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
||||||
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
||||||
|
@ -2136,7 +2128,7 @@ std::vector<int> GLCanvas3D::load_object(const ModelObject& model_object, int ob
|
||||||
instance_idxs.emplace_back(i);
|
instance_idxs.emplace_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_initialized);
|
return m_volumes.load_object(&model_object, obj_idx, instance_idxs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
||||||
|
@ -2447,7 +2439,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
// Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
|
// Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
|
||||||
// later in this function.
|
// later in this function.
|
||||||
it->volume_idx = m_volumes.volumes.size();
|
it->volume_idx = m_volumes.volumes.size();
|
||||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_initialized, m_canvas_type == ECanvasType::CanvasAssembleView);
|
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_canvas_type == ECanvasType::CanvasAssembleView);
|
||||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||||
update_object_list = true;
|
update_object_list = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2504,31 +2496,32 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
GLVolume &volume = *m_volumes.volumes[it->volume_idx];
|
GLVolume &volume = *m_volumes.volumes[it->volume_idx];
|
||||||
if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
|
if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
|
||||||
// The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
|
// The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
|
||||||
volume.indexed_vertex_array.release_geometry();
|
volume.model.reset();
|
||||||
if (state.step[istep].state == PrintStateBase::DONE) {
|
if (state.step[istep].state == PrintStateBase::DONE) {
|
||||||
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
|
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
|
||||||
assert(! mesh.empty());
|
assert(! mesh.empty());
|
||||||
mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
|
mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
volume.indexed_vertex_array.load_mesh(mesh, true);
|
volume.model.init_from(mesh, true);
|
||||||
#else
|
#else
|
||||||
volume.indexed_vertex_array.load_mesh(mesh);
|
volume.model.init_from(mesh);
|
||||||
#endif // ENABLE_SMOOTH_NORMALS
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
} else {
|
}
|
||||||
// Reload the original volume.
|
else {
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
// Reload the original volume.
|
||||||
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
#else
|
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
|
||||||
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
#else
|
||||||
|
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||||
#endif // ENABLE_SMOOTH_NORMALS
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
}
|
}
|
||||||
volume.finalize_geometry(true);
|
|
||||||
}
|
}
|
||||||
//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
|
//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
|
||||||
// to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
|
// to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
|
||||||
// of various concenrs (model vs. 3D print path).
|
// of various concenrs (model vs. 3D print path).
|
||||||
volume.offsets = { state.step[istep].timestamp };
|
volume.offsets = { state.step[istep].timestamp };
|
||||||
} else if (state.step[istep].state == PrintStateBase::DONE) {
|
}
|
||||||
|
else if (state.step[istep].state == PrintStateBase::DONE) {
|
||||||
// Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
|
// Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
|
||||||
ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
|
ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
|
||||||
auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
|
auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
|
||||||
|
@ -2540,7 +2533,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
|
instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
|
||||||
else
|
else
|
||||||
shift_zs[object_idx] = 0.;
|
shift_zs[object_idx] = 0.;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
||||||
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
||||||
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
||||||
|
@ -2550,7 +2544,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
|
|
||||||
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
||||||
if (!instances[istep].empty())
|
if (!instances[istep].empty())
|
||||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
|
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||||
|
@ -2614,7 +2608,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
||||||
1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
|
1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
|
||||||
(float)wipe_tower_size(0), (float)wipe_tower_size(1), (float)wipe_tower_size(2), a,
|
(float)wipe_tower_size(0), (float)wipe_tower_size(1), (float)wipe_tower_size(2), a,
|
||||||
/*!print->is_step_done(psWipeTower)*/ true, brim_width, m_initialized);
|
/*!print->is_step_done(psWipeTower)*/ true, brim_width);
|
||||||
int volume_idx_wipe_tower_old = volume_idxs_wipe_tower_old[plate_id];
|
int volume_idx_wipe_tower_old = volume_idxs_wipe_tower_old[plate_id];
|
||||||
if (volume_idx_wipe_tower_old != -1)
|
if (volume_idx_wipe_tower_old != -1)
|
||||||
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
|
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
|
||||||
|
@ -2687,26 +2681,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& vol_old, bool gl_initialized, size_t prealloc_size = VERTEX_BUFFER_RESERVE_SIZE)
|
|
||||||
{
|
|
||||||
// Assign the large pre-allocated buffers to the new GLVolume.
|
|
||||||
vol_new.indexed_vertex_array = std::move(vol_old.indexed_vertex_array);
|
|
||||||
// Copy the content back to the old GLVolume.
|
|
||||||
vol_old.indexed_vertex_array = vol_new.indexed_vertex_array;
|
|
||||||
// Clear the buffers, but keep them pre-allocated.
|
|
||||||
vol_new.indexed_vertex_array.clear();
|
|
||||||
// Just make sure that clear did not clear the reserved memory.
|
|
||||||
// Reserving number of vertices (3x position + 3x color)
|
|
||||||
vol_new.indexed_vertex_array.reserve(prealloc_size / 6);
|
|
||||||
// Finalize the old geometry, possibly move data to the graphics card.
|
|
||||||
vol_old.finalize_geometry(gl_initialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLCanvas3D::load_shells(const Print& print, bool force_previewing)
|
void GLCanvas3D::load_shells(const Print& print, bool force_previewing)
|
||||||
{
|
{
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
{
|
{
|
||||||
m_gcode_viewer.load_shells(print, m_initialized, force_previewing);
|
m_gcode_viewer.load_shells(print, force_previewing);
|
||||||
m_gcode_viewer.update_shells_color_by_extruder(m_config);
|
m_gcode_viewer.update_shells_color_by_extruder(m_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2726,7 +2705,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
|
||||||
//when load gcode directly, it is too late
|
//when load gcode directly, it is too late
|
||||||
m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle);
|
m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle);
|
||||||
m_gcode_viewer.load(gcode_result, *this->fff_print(), wxGetApp().plater()->build_volume(), exclude_bounding_box,
|
m_gcode_viewer.load(gcode_result, *this->fff_print(), wxGetApp().plater()->build_volume(), exclude_bounding_box,
|
||||||
m_initialized, wxGetApp().get_mode(), only_gcode);
|
wxGetApp().get_mode(), only_gcode);
|
||||||
|
|
||||||
if (wxGetApp().is_editor()) {
|
if (wxGetApp().is_editor()) {
|
||||||
//BBS: always load shell at preview, do this in load_shells
|
//BBS: always load shell at preview, do this in load_shells
|
||||||
|
@ -5637,7 +5616,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
||||||
curr_color = vol->color;
|
curr_color = vol->color;
|
||||||
|
|
||||||
ColorRGBA new_color = adjust_color_for_rendering(curr_color);
|
ColorRGBA new_color = adjust_color_for_rendering(curr_color);
|
||||||
shader->set_uniform("uniform_color", new_color);
|
vol->model.set_color(new_color);
|
||||||
shader->set_uniform("volume_world_matrix", vol->world_matrix());
|
shader->set_uniform("volume_world_matrix", vol->world_matrix());
|
||||||
//BBS set all volume to orange
|
//BBS set all volume to orange
|
||||||
//shader->set_uniform("uniform_color", orange);
|
//shader->set_uniform("uniform_color", orange);
|
||||||
|
@ -7192,6 +7171,10 @@ void GLCanvas3D::_render_style_editor()
|
||||||
|
|
||||||
void GLCanvas3D::_render_volumes_for_picking() const
|
void GLCanvas3D::_render_volumes_for_picking() const
|
||||||
{
|
{
|
||||||
|
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||||
|
if (shader == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
// do not cull backfaces to show broken geometry, if any
|
// do not cull backfaces to show broken geometry, if any
|
||||||
glsafe(::glDisable(GL_CULL_FACE));
|
glsafe(::glDisable(GL_CULL_FACE));
|
||||||
|
|
||||||
|
@ -7209,8 +7192,10 @@ void GLCanvas3D::_render_volumes_for_picking() const
|
||||||
//BBS: remove the bed picking logic
|
//BBS: remove the bed picking logic
|
||||||
const unsigned int id = volume.second.first;
|
const unsigned int id = volume.second.first;
|
||||||
//const unsigned int id = 1 + volume.second.first;
|
//const unsigned int id = 1 + volume.second.first;
|
||||||
glsafe(::glColor4fv(picking_decode(id).data()));
|
volume.first->model.set_color(picking_decode(id));
|
||||||
|
shader->start_using();
|
||||||
volume.first->render();
|
volume.first->render();
|
||||||
|
shader->stop_using();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8384,22 +8369,23 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume)
|
||||||
skirt_height = std::min(skirt_height, print_zs.size());
|
skirt_height = std::min(skirt_height, print_zs.size());
|
||||||
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
||||||
|
|
||||||
GLVolume *volume = m_volumes.new_toolpath_volume(color, VERTEX_BUFFER_RESERVE_SIZE);
|
GLVolume* volume = m_volumes.new_toolpath_volume(color);
|
||||||
|
GLModel::Geometry init_data;
|
||||||
|
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||||
for (size_t i = 0; i < skirt_height; ++ i) {
|
for (size_t i = 0; i < skirt_height; ++ i) {
|
||||||
volume->print_zs.emplace_back(print_zs[i]);
|
volume->print_zs.emplace_back(print_zs[i]);
|
||||||
volume->offsets.emplace_back(volume->indexed_vertex_array.quad_indices.size());
|
volume->offsets.emplace_back(init_data.indices_count());
|
||||||
volume->offsets.emplace_back(volume->indexed_vertex_array.triangle_indices.size());
|
|
||||||
//BBS: usage of m_brim are deleted
|
//BBS: usage of m_brim are deleted
|
||||||
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
|
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), init_data);
|
||||||
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
||||||
if (volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
if (init_data.vertices_size_bytes() > MAX_VERTEX_BUFFER_SIZE) {
|
||||||
|
volume->model.init_from(std::move(init_data));
|
||||||
GLVolume &vol = *volume;
|
GLVolume &vol = *volume;
|
||||||
volume = m_volumes.new_toolpath_volume(vol.color);
|
volume = m_volumes.new_toolpath_volume(vol.color);
|
||||||
reserve_new_volume_finalize_old_volume(*volume, vol, m_initialized);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
volume->is_outside = ! build_volume.all_paths_inside_vertices_and_normals_interleaved(volume->indexed_vertex_array.vertices_and_normals_interleaved, volume->indexed_vertex_array.bounding_box());
|
volume->model.init_from(std::move(init_data));
|
||||||
volume->indexed_vertex_array.finalize_geometry(m_initialized);
|
volume->is_outside = !contains(build_volume, volume->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const BuildVolume& build_volume, const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values)
|
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const BuildVolume& build_volume, const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values)
|
||||||
|
@ -8571,6 +8557,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
// Allocate the volume before locking.
|
// Allocate the volume before locking.
|
||||||
GLVolume *volume = new GLVolume(color);
|
GLVolume *volume = new GLVolume(color);
|
||||||
volume->is_extrusion_path = true;
|
volume->is_extrusion_path = true;
|
||||||
|
// to prevent sending data to gpu (in the main thread) while
|
||||||
|
// editing the model geometry
|
||||||
|
volume->model.disable_render();
|
||||||
tbb::spin_mutex::scoped_lock lock;
|
tbb::spin_mutex::scoped_lock lock;
|
||||||
// Lock by ROII, so if the emplace_back() fails, the lock will be released.
|
// Lock by ROII, so if the emplace_back() fails, the lock will be released.
|
||||||
lock.acquire(new_volume_mutex);
|
lock.acquire(new_volume_mutex);
|
||||||
|
@ -8583,8 +8572,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||||
[&ctxt, &new_volume, is_selected_separate_extruder, this](const tbb::blocked_range<size_t>& range) {
|
[&ctxt, &new_volume, is_selected_separate_extruder, this](const tbb::blocked_range<size_t>& range) {
|
||||||
GLVolumePtrs vols;
|
GLVolumePtrs vols;
|
||||||
auto volume = [&ctxt, &vols](size_t layer_idx, int extruder, int feature) -> GLVolume& {
|
std::vector<GLModel::Geometry> geometries;
|
||||||
return *vols[ctxt.color_by_color_print()?
|
auto select_geometry = [&ctxt, &geometries](size_t layer_idx, int extruder, int feature) -> GLModel::Geometry& {
|
||||||
|
return geometries[ctxt.color_by_color_print() ?
|
||||||
ctxt.color_print_color_idx_by_layer_idx_and_extruder(layer_idx, extruder) :
|
ctxt.color_print_color_idx_by_layer_idx_and_extruder(layer_idx, extruder) :
|
||||||
ctxt.color_by_tool() ?
|
ctxt.color_by_tool() ?
|
||||||
std::min<int>(ctxt.number_tools() - 1, std::max<int>(extruder - 1, 0)) :
|
std::min<int>(ctxt.number_tools() - 1, std::max<int>(extruder - 1, 0)) :
|
||||||
|
@ -8592,22 +8582,26 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
if (ctxt.color_by_color_print() || ctxt.color_by_tool()) {
|
if (ctxt.color_by_color_print() || ctxt.color_by_tool()) {
|
||||||
for (size_t i = 0; i < ctxt.number_tools(); ++i)
|
for (size_t i = 0; i < ctxt.number_tools(); ++i) {
|
||||||
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
geometries.emplace_back(GLModel::Geometry());
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
||||||
for (GLVolume *vol : vols)
|
geometries = { GLModel::Geometry(), GLModel::Geometry(), GLModel::Geometry() };
|
||||||
// Reserving number of vertices (3x position + 3x color)
|
}
|
||||||
vol->indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6);
|
|
||||||
|
assert(vols.size() == geometries.size());
|
||||||
|
for (GLModel::Geometry& g : geometries) {
|
||||||
|
g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||||
|
}
|
||||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||||
const Layer *layer = ctxt.layers[idx_layer];
|
const Layer *layer = ctxt.layers[idx_layer];
|
||||||
|
|
||||||
if (is_selected_separate_extruder)
|
if (is_selected_separate_extruder) {
|
||||||
{
|
|
||||||
bool at_least_one_has_correct_extruder = false;
|
bool at_least_one_has_correct_extruder = false;
|
||||||
for (const LayerRegion* layerm : layer->regions())
|
for (const LayerRegion* layerm : layer->regions()) {
|
||||||
{
|
|
||||||
if (layerm->slices.surfaces.empty())
|
if (layerm->slices.surfaces.empty())
|
||||||
continue;
|
continue;
|
||||||
const PrintRegionConfig& cfg = layerm->region().config();
|
const PrintRegionConfig& cfg = layerm->region().config();
|
||||||
|
@ -8622,12 +8616,14 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GLVolume *vol : vols)
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
|
GLVolume* vol = vols[i];
|
||||||
if (vol->print_zs.empty() || vol->print_zs.back() != layer->print_z) {
|
if (vol->print_zs.empty() || vol->print_zs.back() != layer->print_z) {
|
||||||
vol->print_zs.emplace_back(layer->print_z);
|
vol->print_zs.emplace_back(layer->print_z);
|
||||||
vol->offsets.emplace_back(vol->indexed_vertex_array.quad_indices.size());
|
vol->offsets.emplace_back(geometries[i].indices_count());
|
||||||
vol->offsets.emplace_back(vol->indexed_vertex_array.triangle_indices.size());
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const PrintInstance &instance : *ctxt.shifted_copies) {
|
for (const PrintInstance &instance : *ctxt.shifted_copies) {
|
||||||
const Point © = instance.shift;
|
const Point © = instance.shift;
|
||||||
for (const LayerRegion *layerm : layer->regions()) {
|
for (const LayerRegion *layerm : layer->regions()) {
|
||||||
|
@ -8641,18 +8637,16 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
}
|
}
|
||||||
if (ctxt.has_perimeters)
|
if (ctxt.has_perimeters)
|
||||||
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
||||||
volume(idx_layer, layerm->region().config().wall_filament.value, 0));
|
select_geometry(idx_layer, layerm->region().config().wall_filament.value, 0));
|
||||||
if (ctxt.has_infill) {
|
if (ctxt.has_infill) {
|
||||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||||
// fill represents infill extrusions of a single island.
|
// fill represents infill extrusions of a single island.
|
||||||
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||||
if (! fill->entities.empty())
|
if (! fill->entities.empty())
|
||||||
_3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
_3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
||||||
volume(idx_layer,
|
select_geometry(idx_layer, is_solid_infill(fill->entities.front()->role()) ?
|
||||||
is_solid_infill(fill->entities.front()->role()) ?
|
|
||||||
layerm->region().config().solid_infill_filament :
|
layerm->region().config().solid_infill_filament :
|
||||||
layerm->region().config().sparse_infill_filament,
|
layerm->region().config().sparse_infill_filament, 1));
|
||||||
1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8661,28 +8655,25 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
if (support_layer) {
|
if (support_layer) {
|
||||||
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
||||||
_3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
_3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||||
volume(idx_layer,
|
select_geometry(idx_layer, (extrusion_entity->role() == erSupportMaterial || extrusion_entity->role() == erSupportTransition) ?
|
||||||
(extrusion_entity->role() == erSupportMaterial ||
|
|
||||||
extrusion_entity->role() == erSupportTransition) ?
|
|
||||||
support_layer->object()->config().support_filament :
|
support_layer->object()->config().support_filament :
|
||||||
support_layer->object()->config().support_interface_filament,
|
support_layer->object()->config().support_interface_filament, 2));
|
||||||
2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
||||||
for (size_t i = 0; i < vols.size(); ++i) {
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
GLVolume &vol = *vols[i];
|
GLVolume &vol = *vols[i];
|
||||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
if (geometries[i].vertices_size_bytes() > MAX_VERTEX_BUFFER_SIZE) {
|
||||||
|
vol.model.init_from(std::move(geometries[i]));
|
||||||
vols[i] = new_volume(vol.color);
|
vols[i] = new_volume(vol.color);
|
||||||
reserve_new_volume_finalize_old_volume(*vols[i], vol, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (GLVolume *vol : vols)
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
// Ideally one would call vol->indexed_vertex_array.finalize() here to move the buffers to the OpenGL driver,
|
if (!geometries[i].is_empty())
|
||||||
// but this code runs in parallel and the OpenGL driver is not thread safe.
|
vols[i]->model.init_from(std::move(geometries[i]));
|
||||||
vol->indexed_vertex_array.shrink_to_fit();
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
@ -8697,8 +8688,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||||
}
|
}
|
||||||
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) {
|
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) {
|
||||||
GLVolume* v = m_volumes.volumes[i];
|
GLVolume* v = m_volumes.volumes[i];
|
||||||
v->is_outside = ! build_volume.all_paths_inside_vertices_and_normals_interleaved(v->indexed_vertex_array.vertices_and_normals_interleaved, v->indexed_vertex_array.bounding_box());
|
v->is_outside = !contains(build_volume, v->model);
|
||||||
v->indexed_vertex_array.finalize_geometry(m_initialized);
|
// We are done editinig the model, now it can be sent to gpu
|
||||||
|
v->model.enable_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
@ -8719,7 +8711,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
||||||
struct Ctxt
|
struct Ctxt
|
||||||
{
|
{
|
||||||
const Print *print;
|
const Print *print;
|
||||||
const std::vector<ColorRGBA>* tool_colors;
|
const std::vector<ColorRGBA> *tool_colors;
|
||||||
Vec2f wipe_tower_pos;
|
Vec2f wipe_tower_pos;
|
||||||
float wipe_tower_angle;
|
float wipe_tower_angle;
|
||||||
|
|
||||||
|
@ -8771,6 +8763,9 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
||||||
auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) {
|
auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) {
|
||||||
auto *volume = new GLVolume(color);
|
auto *volume = new GLVolume(color);
|
||||||
volume->is_extrusion_path = true;
|
volume->is_extrusion_path = true;
|
||||||
|
// to prevent sending data to gpu (in the main thread) while
|
||||||
|
// editing the model geometry
|
||||||
|
volume->model.disable_render();
|
||||||
tbb::spin_mutex::scoped_lock lock;
|
tbb::spin_mutex::scoped_lock lock;
|
||||||
lock.acquire(new_volume_mutex);
|
lock.acquire(new_volume_mutex);
|
||||||
m_volumes.volumes.emplace_back(volume);
|
m_volumes.volumes.emplace_back(volume);
|
||||||
|
@ -8784,23 +8779,29 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
||||||
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||||
// Bounding box of this slab of a wipe tower.
|
// Bounding box of this slab of a wipe tower.
|
||||||
GLVolumePtrs vols;
|
GLVolumePtrs vols;
|
||||||
|
std::vector<GLModel::Geometry> geometries;
|
||||||
if (ctxt.color_by_tool()) {
|
if (ctxt.color_by_tool()) {
|
||||||
for (size_t i = 0; i < ctxt.number_tools(); ++i)
|
for (size_t i = 0; i < ctxt.number_tools(); ++i) {
|
||||||
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
geometries.emplace_back(GLModel::Geometry());
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
vols = { new_volume(ctxt.color_support()) };
|
vols = { new_volume(ctxt.color_support()) };
|
||||||
for (GLVolume *volume : vols)
|
geometries = { GLModel::Geometry() };
|
||||||
// Reserving number of vertices (3x position + 3x color)
|
}
|
||||||
volume->indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6);
|
|
||||||
|
assert(vols.size() == geometries.size());
|
||||||
|
for (GLModel::Geometry& g : geometries) {
|
||||||
|
g.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||||
|
}
|
||||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
|
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
|
||||||
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
|
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
|
||||||
for (size_t i = 0; i < vols.size(); ++i) {
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
GLVolume &vol = *vols[i];
|
GLVolume &vol = *vols[i];
|
||||||
if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
|
if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
|
||||||
vol.print_zs.emplace_back(layer.front().print_z);
|
vol.print_zs.emplace_back(layer.front().print_z);
|
||||||
vol.offsets.emplace_back(vol.indexed_vertex_array.quad_indices.size());
|
vol.offsets.emplace_back(geometries[i].indices_count());
|
||||||
vol.offsets.emplace_back(vol.indexed_vertex_array.triangle_indices.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const WipeTower::ToolChangeResult &extrusions : layer) {
|
for (const WipeTower::ToolChangeResult &extrusions : layer) {
|
||||||
|
@ -8843,19 +8844,21 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
||||||
e_prev = e;
|
e_prev = e;
|
||||||
}
|
}
|
||||||
_3DScene::thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
|
_3DScene::thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
|
||||||
*vols[ctxt.volume_idx(e.tool, 0)]);
|
geometries[ctxt.volume_idx(e.tool, 0)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < vols.size(); ++i) {
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
GLVolume &vol = *vols[i];
|
GLVolume &vol = *vols[i];
|
||||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
if (geometries[i].vertices_size_bytes() > MAX_VERTEX_BUFFER_SIZE) {
|
||||||
|
vol.model.init_from(std::move(geometries[i]));
|
||||||
vols[i] = new_volume(vol.color);
|
vols[i] = new_volume(vol.color);
|
||||||
reserve_new_volume_finalize_old_volume(*vols[i], vol, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (GLVolume *vol : vols)
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
vol->indexed_vertex_array.shrink_to_fit();
|
if (!geometries[i].is_empty())
|
||||||
|
vols[i]->model.init_from(std::move(geometries[i]));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
@ -8870,8 +8873,9 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
||||||
}
|
}
|
||||||
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) {
|
for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) {
|
||||||
GLVolume* v = m_volumes.volumes[i];
|
GLVolume* v = m_volumes.volumes[i];
|
||||||
v->is_outside = ! build_volume.all_paths_inside_vertices_and_normals_interleaved(v->indexed_vertex_array.vertices_and_normals_interleaved, v->indexed_vertex_array.bounding_box());
|
v->is_outside = !contains(build_volume, v->model);
|
||||||
v->indexed_vertex_array.finalize_geometry(m_initialized);
|
// We are done editinig the model, now it can be sent to gpu
|
||||||
|
v->model.enable_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
|
@ -8895,11 +8899,10 @@ void GLCanvas3D::_load_sla_shells()
|
||||||
m_volumes.volumes.emplace_back(new GLVolume(color));
|
m_volumes.volumes.emplace_back(new GLVolume(color));
|
||||||
GLVolume& v = *m_volumes.volumes.back();
|
GLVolume& v = *m_volumes.volumes.back();
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
v.indexed_vertex_array.load_mesh(mesh, true);
|
v.model.init_from(mesh, true);
|
||||||
#else
|
#else
|
||||||
v.indexed_vertex_array.load_mesh(mesh);
|
v.model.init_from(mesh);
|
||||||
#endif // ENABLE_SMOOTH_NORMALS
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
v.indexed_vertex_array.finalize_geometry(m_initialized);
|
|
||||||
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
|
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
|
||||||
v.composite_id.volume_id = volume_id;
|
v.composite_id.volume_id = volume_id;
|
||||||
v.set_instance_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0));
|
v.set_instance_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0));
|
||||||
|
|
|
@ -8,15 +8,50 @@
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
|
#include "libslic3r/BuildVolume.hpp"
|
||||||
|
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
|
#include <igl/per_face_normals.h>
|
||||||
|
#include <igl/per_corner_normals.h>
|
||||||
|
#include <igl/per_vertex_normals.h>
|
||||||
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
|
static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_normal>& normals)
|
||||||
|
{
|
||||||
|
using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
|
||||||
|
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
|
||||||
|
|
||||||
|
std::vector<Vec3f> face_normals = its_face_normals(mesh.its);
|
||||||
|
|
||||||
|
Eigen::MatrixXd vertices = MapMatrixXfUnaligned(mesh.its.vertices.front().data(),
|
||||||
|
Eigen::Index(mesh.its.vertices.size()), 3).cast<double>();
|
||||||
|
Eigen::MatrixXi indices = MapMatrixXiUnaligned(mesh.its.indices.front().data(),
|
||||||
|
Eigen::Index(mesh.its.indices.size()), 3);
|
||||||
|
Eigen::MatrixXd in_normals = MapMatrixXfUnaligned(face_normals.front().data(),
|
||||||
|
Eigen::Index(face_normals.size()), 3).cast<double>();
|
||||||
|
Eigen::MatrixXd out_normals;
|
||||||
|
|
||||||
|
igl::per_corner_normals(vertices, indices, in_normals, 1.0, out_normals);
|
||||||
|
|
||||||
|
normals = std::vector<stl_normal>(mesh.its.vertices.size());
|
||||||
|
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
|
||||||
|
for (size_t j = 0; j < 3; ++j) {
|
||||||
|
normals[mesh.its.indices[i][j]] = out_normals.row(i * 3 + j).cast<float>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SMOOTH_NORMALS
|
||||||
|
|
||||||
void GLModel::Geometry::reserve_vertices(size_t vertices_count)
|
void GLModel::Geometry::reserve_vertices(size_t vertices_count)
|
||||||
{
|
{
|
||||||
vertices.reserve(vertices_count * vertex_stride_floats(format));
|
vertices.reserve(vertices_count * vertex_stride_floats(format));
|
||||||
|
@ -206,6 +241,35 @@ Vec2f GLModel::Geometry::extract_tex_coord_2(size_t id) const
|
||||||
return { *(start + 0), *(start + 1) };
|
return { *(start + 0), *(start + 1) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLModel::Geometry::set_vertex(size_t id, const Vec3f& position, const Vec3f& normal)
|
||||||
|
{
|
||||||
|
assert(format.vertex_layout == EVertexLayout::P3N3);
|
||||||
|
assert(id < vertices_count());
|
||||||
|
if (id < vertices_count()) {
|
||||||
|
float* start = &vertices[id * vertex_stride_floats(format)];
|
||||||
|
*(start + 0) = position.x();
|
||||||
|
*(start + 1) = position.y();
|
||||||
|
*(start + 2) = position.z();
|
||||||
|
*(start + 3) = normal.x();
|
||||||
|
*(start + 4) = normal.y();
|
||||||
|
*(start + 5) = normal.z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLModel::Geometry::set_ushort_index(size_t id, unsigned short index)
|
||||||
|
{
|
||||||
|
assert(id < indices_count());
|
||||||
|
if (id < indices_count())
|
||||||
|
::memcpy(indices.data() + id * sizeof(unsigned short), &index, sizeof(unsigned short));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLModel::Geometry::set_uint_index(size_t id, unsigned int index)
|
||||||
|
{
|
||||||
|
assert(id < indices_count());
|
||||||
|
if (id < indices_count())
|
||||||
|
::memcpy(indices.data() + id * sizeof(unsigned int), &index, sizeof(unsigned int));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
|
unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
|
||||||
{
|
{
|
||||||
if (format.index_type != EIndexType::UINT) {
|
if (format.index_type != EIndexType::UINT) {
|
||||||
|
@ -218,7 +282,7 @@ unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ret = -1;
|
unsigned int ret = (unsigned int)-1;
|
||||||
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned int));
|
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned int));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -235,11 +299,21 @@ unsigned short GLModel::Geometry::extract_ushort_index(size_t id) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short ret = -1;
|
unsigned short ret = (unsigned short)-1;
|
||||||
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned short));
|
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned short));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLModel::Geometry::remove_vertex(size_t id)
|
||||||
|
{
|
||||||
|
assert(id < vertices_count());
|
||||||
|
if (id < vertices_count()) {
|
||||||
|
size_t stride = vertex_stride_floats(format);
|
||||||
|
std::vector<float>::iterator it = vertices.begin() + id * stride;
|
||||||
|
vertices.erase(it, it + stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t GLModel::Geometry::vertex_stride_floats(const Format& format)
|
size_t GLModel::Geometry::vertex_stride_floats(const Format& format)
|
||||||
{
|
{
|
||||||
switch (format.vertex_layout)
|
switch (format.vertex_layout)
|
||||||
|
@ -417,20 +491,23 @@ void GLModel::init_from(const indexed_triangle_set& its)
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry& data = m_render_data.geometry;
|
Geometry& data = m_render_data.geometry;
|
||||||
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, Geometry::EIndexType::UINT };
|
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(3 * its.indices.size()) };
|
||||||
data.reserve_vertices(3 * its.indices.size());
|
data.reserve_vertices(3 * its.indices.size());
|
||||||
data.reserve_indices(3 * its.indices.size());
|
data.reserve_indices(3 * its.indices.size());
|
||||||
|
|
||||||
// vertices + indices
|
// vertices + indices
|
||||||
unsigned int vertices_counter = 0;
|
unsigned int vertices_counter = 0;
|
||||||
for (uint32_t i = 0; i < its.indices.size(); ++i) {
|
for (uint32_t i = 0; i < its.indices.size(); ++i) {
|
||||||
stl_triangle_vertex_indices face = its.indices[i];
|
const stl_triangle_vertex_indices face = its.indices[i];
|
||||||
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
const stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
||||||
stl_vertex n = face_normal_normalized(vertex);
|
const stl_vertex n = face_normal_normalized(vertex);
|
||||||
for (size_t j = 0; j < 3; ++j) {
|
for (size_t j = 0; j < 3; ++j) {
|
||||||
data.add_vertex(vertex[j], n);
|
data.add_vertex(vertex[j], n);
|
||||||
}
|
}
|
||||||
vertices_counter += 3;
|
vertices_counter += 3;
|
||||||
|
if (data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||||
|
data.add_ushort_triangle((unsigned short)vertices_counter - 3, (unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
|
||||||
|
else
|
||||||
data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,6 +630,17 @@ static GLenum get_index_type(const GLModel::Geometry::Format& format)
|
||||||
|
|
||||||
void GLModel::render()
|
void GLModel::render()
|
||||||
{
|
{
|
||||||
|
render(std::make_pair<size_t, size_t>(0, indices_count()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLModel::render(const std::pair<size_t, size_t>& range)
|
||||||
|
{
|
||||||
|
if (m_render_disabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (range.second == range.first)
|
||||||
|
return;
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||||
|
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
|
@ -592,7 +680,7 @@ void GLModel::render()
|
||||||
shader->set_uniform("uniform_color", data.color);
|
shader->set_uniform("uniform_color", data.color);
|
||||||
|
|
||||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
|
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
|
||||||
glsafe(::glDrawElements(mode, indices_count(), index_type, nullptr));
|
glsafe(::glDrawElements(mode, range.second - range.first + 1, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format))));
|
||||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||||
|
|
||||||
if (tex_coord)
|
if (tex_coord)
|
||||||
|
@ -721,6 +809,61 @@ static void append_triangle(GLModel::Geometry& data, unsigned short v1, unsigned
|
||||||
data.add_ushort_index(v2);
|
data.add_ushort_index(v2);
|
||||||
data.add_ushort_index(v3);
|
data.add_ushort_index(v3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
inline bool all_vertices_inside(const GLModel::Geometry& geometry, Fn fn)
|
||||||
|
{
|
||||||
|
const size_t position_stride_floats = geometry.position_stride_floats(geometry.format);
|
||||||
|
const size_t position_offset_floats = geometry.position_offset_floats(geometry.format);
|
||||||
|
assert(position_stride_floats == 3);
|
||||||
|
if (geometry.vertices.empty() || position_stride_floats != 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto it = geometry.vertices.begin(); it != geometry.vertices.end(); ) {
|
||||||
|
it += position_offset_floats;
|
||||||
|
if (!fn({ *it, *(it + 1), *(it + 2) }))
|
||||||
|
return false;
|
||||||
|
it += (geometry.vertex_stride_floats(geometry.format) - position_offset_floats - position_stride_floats);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const BuildVolume& volume, const GLModel& model, bool ignore_bottom)
|
||||||
|
{
|
||||||
|
static constexpr const double epsilon = BuildVolume::BedEpsilon;
|
||||||
|
switch (volume.type()) {
|
||||||
|
case BuildVolume_Type::Rectangle:
|
||||||
|
{
|
||||||
|
BoundingBox3Base<Vec3d> build_volume = volume.bounding_volume().inflated(epsilon);
|
||||||
|
if (volume.printable_height() == 0.0)
|
||||||
|
build_volume.max.z() = std::numeric_limits<double>::max();
|
||||||
|
if (ignore_bottom)
|
||||||
|
build_volume.min.z() = -std::numeric_limits<double>::max();
|
||||||
|
const BoundingBoxf3& model_box = model.get_bounding_box();
|
||||||
|
return build_volume.contains(model_box.min) && build_volume.contains(model_box.max);
|
||||||
|
}
|
||||||
|
case BuildVolume_Type::Circle:
|
||||||
|
{
|
||||||
|
const Geometry::Circled& circle = volume.circle();
|
||||||
|
const Vec2f c = unscaled<float>(circle.center);
|
||||||
|
const float r = unscaled<double>(circle.radius) + float(epsilon);
|
||||||
|
const float r2 = sqr(r);
|
||||||
|
return volume.printable_height() == 0.0 ?
|
||||||
|
all_vertices_inside(model.get_geometry(), [c, r2](const Vec3f& p) { return (to_2d(p) - c).squaredNorm() <= r2; }) :
|
||||||
|
|
||||||
|
all_vertices_inside(model.get_geometry(), [c, r2, z = volume.printable_height() + epsilon](const Vec3f& p) { return (to_2d(p) - c).squaredNorm() <= r2 && p.z() <= z; });
|
||||||
|
}
|
||||||
|
case BuildVolume_Type::Convex:
|
||||||
|
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
||||||
|
case BuildVolume_Type::Custom:
|
||||||
|
return volume.printable_height() == 0.0 ?
|
||||||
|
all_vertices_inside(model.get_geometry(), [&volume](const Vec3f& p) { return Geometry::inside_convex_polygon(volume.top_bottom_convex_hull_decomposition_bed(), to_2d(p).cast<double>()); }) :
|
||||||
|
all_vertices_inside(model.get_geometry(), [&volume, z = volume.printable_height() + epsilon](const Vec3f& p) { return Geometry::inside_convex_polygon(volume.top_bottom_convex_hull_decomposition_bed(), to_2d(p).cast<double>()) && p.z() <= z; });
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
||||||
{
|
{
|
||||||
resolution = std::max<unsigned short>(4, resolution);
|
resolution = std::max<unsigned short>(4, resolution);
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Slic3r {
|
||||||
class TriangleMesh;
|
class TriangleMesh;
|
||||||
class Polygon;
|
class Polygon;
|
||||||
using Polygons = std::vector<Polygon>;
|
using Polygons = std::vector<Polygon>;
|
||||||
|
class BuildVolume;
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
@ -69,6 +70,11 @@ namespace GUI {
|
||||||
void add_vertex(const Vec3f& position, const Vec2f& tex_coord); // EVertexLayout::P3T2
|
void add_vertex(const Vec3f& position, const Vec2f& tex_coord); // EVertexLayout::P3T2
|
||||||
void add_vertex(const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3
|
void add_vertex(const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3
|
||||||
|
|
||||||
|
void set_vertex(size_t id, const Vec3f& position, const Vec3f& normal); // EVertexLayout::P3N3
|
||||||
|
|
||||||
|
void set_ushort_index(size_t id, unsigned short index);
|
||||||
|
void set_uint_index(size_t id, unsigned int index);
|
||||||
|
|
||||||
void add_ushort_index(unsigned short id);
|
void add_ushort_index(unsigned short id);
|
||||||
void add_uint_index(unsigned int id);
|
void add_uint_index(unsigned int id);
|
||||||
|
|
||||||
|
@ -86,7 +92,9 @@ namespace GUI {
|
||||||
unsigned int extract_uint_index(size_t id) const;
|
unsigned int extract_uint_index(size_t id) const;
|
||||||
unsigned short extract_ushort_index(size_t id) const;
|
unsigned short extract_ushort_index(size_t id) const;
|
||||||
|
|
||||||
bool is_empty() const { return vertices.empty() || indices.empty(); }
|
void remove_vertex(size_t id);
|
||||||
|
|
||||||
|
bool is_empty() const { return vertices_count() == 0 || indices_count() == 0; }
|
||||||
|
|
||||||
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
|
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
|
||||||
size_t indices_count() const { return indices.size() / index_stride_bytes(format); }
|
size_t indices_count() const { return indices.size() / index_stride_bytes(format); }
|
||||||
|
@ -133,6 +141,14 @@ namespace GUI {
|
||||||
private:
|
private:
|
||||||
RenderData m_render_data;
|
RenderData m_render_data;
|
||||||
|
|
||||||
|
// By default the vertex and index buffers data are sent to gpu at the first call to render() method.
|
||||||
|
// If you need to initialize a model from outside the main thread, so that a call to render() may happen
|
||||||
|
// before the initialization is complete, use the methods:
|
||||||
|
// disable_render()
|
||||||
|
// ... do your initialization ...
|
||||||
|
// enable_render()
|
||||||
|
// to keep the data on cpu side until needed.
|
||||||
|
bool m_render_disabled{ false };
|
||||||
BoundingBoxf3 m_bounding_box;
|
BoundingBoxf3 m_bounding_box;
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
|
||||||
|
@ -150,6 +166,7 @@ namespace GUI {
|
||||||
|
|
||||||
size_t indices_size_bytes() const { return indices_count() * Geometry::index_stride_bytes(m_render_data.geometry.format); }
|
size_t indices_size_bytes() const { return indices_count() * Geometry::index_stride_bytes(m_render_data.geometry.format); }
|
||||||
|
|
||||||
|
const Geometry& get_geometry() const { return m_render_data.geometry; }
|
||||||
void init_from(Geometry&& data);
|
void init_from(Geometry&& data);
|
||||||
void init_from(const TriangleMesh& mesh);
|
void init_from(const TriangleMesh& mesh);
|
||||||
void init_from(const indexed_triangle_set& its);
|
void init_from(const indexed_triangle_set& its);
|
||||||
|
@ -161,16 +178,40 @@ namespace GUI {
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void render();
|
void render();
|
||||||
|
void render(const std::pair<size_t, size_t>& range);
|
||||||
void render_instanced(unsigned int instances_vbo, unsigned int instances_count);
|
void render_instanced(unsigned int instances_vbo, unsigned int instances_count);
|
||||||
|
|
||||||
bool is_initialized() const { return vertices_count() > 0 && indices_count() > 0; }
|
bool is_initialized() const { return vertices_count() > 0 && indices_count() > 0; }
|
||||||
|
bool is_empty() const { return m_render_data.geometry.is_empty(); }
|
||||||
|
|
||||||
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; }
|
const std::string& get_filename() const { return m_filename; }
|
||||||
|
|
||||||
|
bool is_render_disabled() const { return m_render_disabled; }
|
||||||
|
void enable_render() { m_render_disabled = false; }
|
||||||
|
void disable_render() { m_render_disabled = true; }
|
||||||
|
|
||||||
|
size_t cpu_memory_used() const {
|
||||||
|
size_t ret = 0;
|
||||||
|
if (!m_render_data.geometry.vertices.empty())
|
||||||
|
ret += vertices_size_bytes();
|
||||||
|
if (!m_render_data.geometry.indices.empty())
|
||||||
|
ret += indices_size_bytes();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
size_t gpu_memory_used() const {
|
||||||
|
size_t ret = 0;
|
||||||
|
if (m_render_data.geometry.vertices.empty())
|
||||||
|
ret += vertices_size_bytes();
|
||||||
|
if (m_render_data.geometry.indices.empty())
|
||||||
|
ret += indices_size_bytes();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool send_to_gpu();
|
bool send_to_gpu();
|
||||||
};
|
};
|
||||||
|
bool contains(const BuildVolume& volume, const GLModel& model, bool ignore_bottom = true);
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
@ -32,9 +32,9 @@ std::string GLGizmoFaceDetector::on_get_name() const
|
||||||
|
|
||||||
void GLGizmoFaceDetector::on_render()
|
void GLGizmoFaceDetector::on_render()
|
||||||
{
|
{
|
||||||
if (m_iva.has_VBOs()) {
|
if (model.is_initialized()) {
|
||||||
::glColor4f(0.f, 0.f, 1.f, 0.4f);
|
model.set_color({0.f, 0.f, 1.f, 0.4f});
|
||||||
m_iva.render();
|
model.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ void GLGizmoFaceDetector::on_render_input_window(float x, float y, float bottom_
|
||||||
void GLGizmoFaceDetector::on_set_state()
|
void GLGizmoFaceDetector::on_set_state()
|
||||||
{
|
{
|
||||||
if (get_state() == On) {
|
if (get_state() == On) {
|
||||||
m_iva.release_geometry();
|
model.reset();
|
||||||
display_exterior_face();
|
display_exterior_face();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,10 @@ void GLGizmoFaceDetector::perform_recognition(const Selection& selection)
|
||||||
void GLGizmoFaceDetector::display_exterior_face()
|
void GLGizmoFaceDetector::display_exterior_face()
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
m_iva.release_geometry();
|
model.reset();
|
||||||
|
|
||||||
|
GLModel::Geometry init_data;
|
||||||
|
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||||
|
|
||||||
const ModelObjectPtrs& objects = wxGetApp().model().objects;
|
const ModelObjectPtrs& objects = wxGetApp().model().objects;
|
||||||
for (ModelObject* mo : objects) {
|
for (ModelObject* mo : objects) {
|
||||||
|
@ -110,19 +113,15 @@ void GLGizmoFaceDetector::display_exterior_face()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
m_iva.push_geometry(double(mv_its.vertices[facet_vert_idxs[i]](0)),
|
init_data.add_vertex((Vec3f) mv_its.vertices[facet_vert_idxs[i]].cast<float>(), Vec3f{0.0f, 0.0f, 1.0f});
|
||||||
double(mv_its.vertices[facet_vert_idxs[i]](1)),
|
|
||||||
double(mv_its.vertices[facet_vert_idxs[i]](2)),
|
|
||||||
0., 0., 1.);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_iva.push_triangle(cnt, cnt + 1, cnt + 2);
|
init_data.add_uint_triangle(cnt, cnt + 1, cnt + 2);
|
||||||
cnt += 3;
|
cnt += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
model.init_from(std::move(init_data));
|
||||||
m_iva.finalize_geometry(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonGizmosDataID GLGizmoFaceDetector::on_get_requirements() const
|
CommonGizmosDataID GLGizmoFaceDetector::on_get_requirements() const
|
||||||
|
|
|
@ -28,7 +28,7 @@ private:
|
||||||
void perform_recognition(const Selection& selection);
|
void perform_recognition(const Selection& selection);
|
||||||
void display_exterior_face();
|
void display_exterior_face();
|
||||||
|
|
||||||
GLIndexedVertexArray m_iva;
|
GUI::GLModel model;
|
||||||
double m_sample_interval = {0.5};
|
double m_sample_interval = {0.5};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -894,13 +894,16 @@ void GLGizmoFdmSupports::run_thread()
|
||||||
print->set_status(100, L("Support Generated"));
|
print->set_status(100, L("Support Generated"));
|
||||||
goto _finished;
|
goto _finished;
|
||||||
}
|
}
|
||||||
|
GLModel::Geometry init_data;
|
||||||
|
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT };
|
||||||
for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers())
|
for (const SupportLayer *support_layer : m_print_instance.print_object->support_layers())
|
||||||
{
|
{
|
||||||
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
||||||
{
|
{
|
||||||
_3DScene::extrusionentity_to_verts(extrusion_entity, float(support_layer->print_z), m_print_instance.shift, *m_support_volume);
|
_3DScene::extrusionentity_to_verts(extrusion_entity, float(support_layer->print_z), m_print_instance.shift, init_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_support_volume->model.init_from(std::move(init_data));
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished extrusionentity_to_verts, update status to 100%";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished extrusionentity_to_verts, update status to 100%";
|
||||||
print->set_status(100, L("Support Generated"));
|
print->set_status(100, L("Support Generated"));
|
||||||
|
|
||||||
|
@ -926,7 +929,6 @@ _finished:
|
||||||
void GLGizmoFdmSupports::generate_support_volume()
|
void GLGizmoFdmSupports::generate_support_volume()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",before finalize_geometry";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",before finalize_geometry";
|
||||||
m_support_volume->indexed_vertex_array.finalize_geometry(m_parent.is_initialized());
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
std::unique_lock<std::mutex> lck(m_mutex);
|
||||||
m_volume_ready = true;
|
m_volume_ready = true;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
||||||
// BBS
|
// BBS
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp"
|
//#include "slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
|
||||||
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
|
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
|
||||||
|
|
|
@ -2388,8 +2388,8 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
const int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
const int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
if (fb_width == 0 || fb_height == 0)
|
if (fb_width == 0 || fb_height == 0)
|
||||||
return;
|
return;
|
||||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
@ -2432,8 +2432,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
|
||||||
|
|
||||||
// Render command lists
|
// Render command lists
|
||||||
ImVec2 pos = draw_data->DisplayPos;
|
ImVec2 pos = draw_data->DisplayPos;
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
for (int n = 0; n < draw_data->CmdListsCount; ++n) {
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||||
|
@ -2441,19 +2440,14 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
|
||||||
glsafe(::glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))));
|
glsafe(::glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))));
|
||||||
glsafe(::glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))));
|
glsafe(::glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))));
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; ++cmd_i) {
|
||||||
{
|
|
||||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
if (pcmd->UserCallback)
|
if (pcmd->UserCallback)
|
||||||
{
|
|
||||||
// User callback (registered via ImDrawList::AddCallback)
|
// User callback (registered via ImDrawList::AddCallback)
|
||||||
pcmd->UserCallback(cmd_list, pcmd);
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
|
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
|
||||||
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) {
|
||||||
{
|
|
||||||
// Apply scissor/clipping rectangle
|
// Apply scissor/clipping rectangle
|
||||||
glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
|
glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
|
||||||
|
|
||||||
|
|
|
@ -926,7 +926,7 @@ void CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f
|
||||||
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
|
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
|
||||||
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
||||||
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
||||||
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, true, false, true);
|
glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, false, true);
|
||||||
glvolume_collection.volumes.back()->set_render_color(new_color);
|
glvolume_collection.volumes.back()->set_render_color(new_color);
|
||||||
glvolume_collection.volumes.back()->set_color(new_color);
|
glvolume_collection.volumes.back()->set_color(new_color);
|
||||||
//glvolume_collection.volumes.back()->printable = model_instance.printable;
|
//glvolume_collection.volumes.back()->printable = model_instance.printable;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue