mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-08 22:35:15 -06:00
Volume rewritten from Perl to C++,
generation of vertex arrays from paths rewritten from Perl to C++, parallelized.
This commit is contained in:
parent
50976e1b5a
commit
e6fddd364d
11 changed files with 825 additions and 701 deletions
|
@ -247,7 +247,11 @@ sub new {
|
|||
);
|
||||
}
|
||||
|
||||
package Slic3r::GUI::_3DScene::GLVertexArray;
|
||||
package Slic3r::GUI::_3DScene::GLVolume::Collection;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
'fallback' => 1;
|
||||
|
||||
sub CLONE_SKIP { 1 }
|
||||
|
||||
package main;
|
||||
|
@ -279,6 +283,7 @@ for my $class (qw(
|
|||
Slic3r::Geometry::BoundingBox
|
||||
Slic3r::Geometry::BoundingBoxf
|
||||
Slic3r::Geometry::BoundingBoxf3
|
||||
Slic3r::GUI::_3DScene::GLVolume
|
||||
Slic3r::Layer
|
||||
Slic3r::Layer::Region
|
||||
Slic3r::Layer::Support
|
||||
|
|
|
@ -593,7 +593,7 @@ int generate_layer_height_texture(
|
|||
#endif
|
||||
|
||||
// Clear the main texture and the 2nd LOD level.
|
||||
memset(data, 0, rows * cols * 5);
|
||||
// memset(data, 0, rows * cols * (level_of_detail_2nd_level ? 5 : 4));
|
||||
// 2nd LOD level data start
|
||||
unsigned char *data1 = reinterpret_cast<unsigned char*>(data) + rows * cols * 4;
|
||||
int ncells = std::min((cols-1) * rows, int(ceil(16. * (slicing_params.object_print_z_height() / slicing_params.min_layer_height))));
|
||||
|
|
|
@ -60,7 +60,8 @@ REGISTER_CLASS(Surface, "Surface");
|
|||
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
||||
REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2");
|
||||
REGISTER_CLASS(TriangleMesh, "TriangleMesh");
|
||||
REGISTER_CLASS(GLVertexArray, "GUI::_3DScene::GLVertexArray");
|
||||
REGISTER_CLASS(GLVolume, "GUI::_3DScene::GLVolume");
|
||||
REGISTER_CLASS(GLVolumeCollection, "GUI::_3DScene::GLVolume::Collection");
|
||||
|
||||
SV*
|
||||
ConfigBase__as_hash(ConfigBase* THIS) {
|
||||
|
|
|
@ -1,21 +1,172 @@
|
|||
#include "3DScene.hpp"
|
||||
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "../../libslic3r/ExtrusionEntity.hpp"
|
||||
#include "../../libslic3r/ExtrusionEntityCollection.hpp"
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
#include "../../libslic3r/Slicing.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/atomic.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void GLVertexArray::load_mesh(const TriangleMesh &mesh)
|
||||
{
|
||||
this->reserve_more(3 * 3 * mesh.facets_count());
|
||||
|
||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) {
|
||||
stl_facet &facet = mesh.stl.facet_start[i];
|
||||
for (int j = 0; j < 3; ++ j) {
|
||||
this->push_norm(facet.normal.x, facet.normal.y, facet.normal.z);
|
||||
this->push_vert(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLVolume::set_range(double min_z, double max_z)
|
||||
{
|
||||
this->qverts_range.first = 0;
|
||||
this->qverts_range.second = this->qverts.size();
|
||||
this->tverts_range.first = 0;
|
||||
this->tverts_range.second = this->tverts.size();
|
||||
if (! this->print_zs.empty()) {
|
||||
// The Z layer range is specified.
|
||||
// First test whether the Z span of this object is not out of (min_z, max_z) completely.
|
||||
if (this->print_zs.front() > max_z || this->print_zs.back() < min_z) {
|
||||
this->qverts_range.second = 0;
|
||||
this->tverts_range.second = 0;
|
||||
} else {
|
||||
// Then find the lowest layer to be displayed.
|
||||
size_t i = 0;
|
||||
for (; i < this->print_zs.size() && this->print_zs[i] < min_z; ++ i);
|
||||
if (i == this->print_zs.size()) {
|
||||
// This shall not happen.
|
||||
this->qverts_range.second = 0;
|
||||
this->tverts_range.second = 0;
|
||||
} else {
|
||||
// Remember start of the layer.
|
||||
this->qverts_range.first = this->offsets[i * 2];
|
||||
this->tverts_range.first = this->offsets[i * 2 + 1];
|
||||
// Some layers are above $min_z. Which?
|
||||
for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i);
|
||||
if (i < this->print_zs.size()) {
|
||||
this->qverts_range.second = this->offsets[i * 2];
|
||||
this->tverts_range.second = this->offsets[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
|
||||
{
|
||||
GLTexture *tex = this->layer_height_texture.get();
|
||||
if (tex == nullptr)
|
||||
// No layer_height_texture is assigned to this GLVolume, therefore the layer height texture cannot be filled.
|
||||
return;
|
||||
|
||||
// Always try to update the layer height profile.
|
||||
bool update = print_object->update_layer_height_profile(print_object->model_object()->layer_height_profile) || force;
|
||||
// Update if the layer height profile was changed, or when the texture is not valid.
|
||||
if (! update && ! tex->data.empty() && tex->cells > 0)
|
||||
// Texture is valid, don't update.
|
||||
return;
|
||||
|
||||
if (tex->data.empty()) {
|
||||
tex->width = 1024;
|
||||
tex->height = 1024;
|
||||
tex->levels = 2;
|
||||
tex->data.assign(tex->width * tex->height * 5, 0);
|
||||
}
|
||||
|
||||
SlicingParameters slicing_params = print_object->slicing_parameters();
|
||||
bool level_of_detail_2nd_level = true;
|
||||
tex->cells = Slic3r::generate_layer_height_texture(
|
||||
slicing_params,
|
||||
Slic3r::generate_object_layers(slicing_params, print_object->model_object()->layer_height_profile),
|
||||
tex->data.data(), tex->height, tex->width, level_of_detail_2nd_level);
|
||||
}
|
||||
|
||||
// 512x512 bitmaps are supported everywhere, but that may not be sufficent for super large print volumes.
|
||||
#define LAYER_HEIGHT_TEXTURE_WIDTH 1024
|
||||
#define LAYER_HEIGHT_TEXTURE_HEIGHT 1024
|
||||
|
||||
std::vector<int> GLVolumeCollection::load_object(
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by)
|
||||
{
|
||||
static float colors[4][4] = {
|
||||
{ 1.0f, 1.0f, 0.0f, 1.f },
|
||||
{ 1.0f, 0.5f, 0.5f, 1.f },
|
||||
{ 0.5f, 1.0f, 0.5f, 1.f },
|
||||
{ 0.5f, 0.5f, 1.0f, 1.f }
|
||||
};
|
||||
|
||||
// Object will have a single common layer height texture for all volumes.
|
||||
std::shared_ptr<GLTexture> layer_height_texture = std::make_shared<GLTexture>();
|
||||
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++ volume_idx) {
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
for (int instance_idx : instance_idxs) {
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
TriangleMesh mesh = model_volume->mesh;
|
||||
instance->transform_mesh(&mesh);
|
||||
volumes_idx.push_back(int(this->volumes.size()));
|
||||
float color[4];
|
||||
memcpy(color, colors[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||
color[3] = model_volume->modifier ? 0.5f : 1.f;
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
v.tverts.load_mesh(mesh);
|
||||
v.bounding_box = v.tverts.bounding_box();
|
||||
v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx;
|
||||
if (select_by == "object")
|
||||
v.select_group_id = obj_idx * 1000000;
|
||||
else if (select_by == "volume")
|
||||
v.select_group_id = obj_idx * 1000000 + volume_idx * 1000;
|
||||
else if (select_by == "instance")
|
||||
v.select_group_id = v.composite_id;
|
||||
if (drag_by == "object")
|
||||
v.drag_group_id = obj_idx * 1000;
|
||||
else if (drag_by == "instance")
|
||||
v.drag_group_id = obj_idx * 1000 + instance_idx;
|
||||
if (! model_volume->modifier)
|
||||
v.layer_height_texture = layer_height_texture;
|
||||
}
|
||||
}
|
||||
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
// caller is responsible for supplying NO lines with zero length
|
||||
void
|
||||
_3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
|
||||
const std::vector<double> &heights, bool closed, double top_z, const Point ©,
|
||||
GLVertexArray* qverts, GLVertexArray* tverts)
|
||||
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)
|
||||
{
|
||||
/* It looks like it's faster without reserving capacity...
|
||||
// each segment has 4 quads, thus 16 vertices; + 2 caps
|
||||
qverts->reserve_more(3 * 4 * (4 * lines.size() + 2));
|
||||
volume.qverts.reserve_more(3 * 4 * (4 * lines.size() + 2));
|
||||
|
||||
// two triangles for each corner
|
||||
tverts->reserve_more(3 * 3 * 2 * (lines.size() + 1));
|
||||
// two triangles for each corner
|
||||
volume.tverts.reserve_more(3 * 3 * 2 * (lines.size() + 1));
|
||||
*/
|
||||
|
||||
assert(! lines.empty());
|
||||
|
@ -69,59 +220,59 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||
// top-right vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the right calculated for the previous line
|
||||
tverts->push_norm(prev_xy_right_normal);
|
||||
tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
volume.tverts.push_norm(prev_xy_right_normal);
|
||||
volume.tverts.push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_right_normal);
|
||||
tverts->push_vert(a1.x, a1.y, middle_z);
|
||||
volume.tverts.push_norm(xy_right_normal);
|
||||
volume.tverts.push_vert(a1.x, a1.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
tverts->push_norm(0,0,1);
|
||||
tverts->push_vert(a.x, a.y, top_z);
|
||||
volume.tverts.push_norm(0,0,1);
|
||||
volume.tverts.push_vert(a.x, a.y, top_z);
|
||||
}
|
||||
// bottom-right vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the right calculated for the previous line
|
||||
tverts->push_norm(prev_xy_right_normal);
|
||||
tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
volume.tverts.push_norm(prev_xy_right_normal);
|
||||
volume.tverts.push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
tverts->push_norm(0,0,-1);
|
||||
tverts->push_vert(a.x, a.y, bottom_z);
|
||||
volume.tverts.push_norm(0,0,-1);
|
||||
volume.tverts.push_vert(a.x, a.y, bottom_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_right_normal);
|
||||
tverts->push_vert(a1.x, a1.y, middle_z);
|
||||
volume.tverts.push_norm(xy_right_normal);
|
||||
volume.tverts.push_vert(a1.x, a1.y, middle_z);
|
||||
}
|
||||
} else if (ccw < -EPSILON) {
|
||||
// top-left vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the left calculated for the previous line
|
||||
tverts->push_norm(prev_xy_left_normal);
|
||||
tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
volume.tverts.push_norm(prev_xy_left_normal);
|
||||
volume.tverts.push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
tverts->push_norm(0,0,1);
|
||||
tverts->push_vert(a.x, a.y, top_z);
|
||||
volume.tverts.push_norm(0,0,1);
|
||||
volume.tverts.push_vert(a.x, a.y, top_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_left_normal);
|
||||
tverts->push_vert(a2.x, a2.y, middle_z);
|
||||
volume.tverts.push_norm(xy_left_normal);
|
||||
volume.tverts.push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
// bottom-left vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the left calculated for the previous line
|
||||
tverts->push_norm(prev_xy_left_normal);
|
||||
tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
volume.tverts.push_norm(prev_xy_left_normal);
|
||||
volume.tverts.push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_left_normal);
|
||||
tverts->push_vert(a2.x, a2.y, middle_z);
|
||||
volume.tverts.push_norm(xy_left_normal);
|
||||
volume.tverts.push_vert(a2.x, a2.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
tverts->push_norm(0,0,-1);
|
||||
tverts->push_vert(a.x, a.y, bottom_z);
|
||||
volume.tverts.push_norm(0,0,-1);
|
||||
volume.tverts.push_vert(a.x, a.y, bottom_z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,112 +290,359 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||
// terminate open paths with caps
|
||||
if (i == 0) {
|
||||
// normal pointing downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_vert(a.x, a.y, bottom_z);
|
||||
|
||||
// normal pointing to the right
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_vert(a1.x, a1.y, middle_z);
|
||||
|
||||
// normal pointing upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_vert(a.x, a.y, top_z);
|
||||
|
||||
// normal pointing to the left
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
// we don't use 'else' because both cases are true if we have only one line
|
||||
if (i == lines.size()-1) {
|
||||
// normal pointing downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_vert(b.x, b.y, bottom_z);
|
||||
|
||||
// normal pointing to the left
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_vert(b2.x, b2.y, middle_z);
|
||||
|
||||
// normal pointing upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_vert(b.x, b.y, top_z);
|
||||
|
||||
// normal pointing to the right
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_vert(b1.x, b1.y, middle_z);
|
||||
}
|
||||
}
|
||||
|
||||
// bottom-right face
|
||||
{
|
||||
// normal going downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_vert(a.x, a.y, bottom_z);
|
||||
volume.qverts.push_vert(b.x, b.y, bottom_z);
|
||||
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_vert(b1.x, b1.y, middle_z);
|
||||
volume.qverts.push_vert(a1.x, a1.y, middle_z);
|
||||
}
|
||||
|
||||
// top-right face
|
||||
{
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_norm(xy_right_normal);
|
||||
volume.qverts.push_vert(a1.x, a1.y, middle_z);
|
||||
volume.qverts.push_vert(b1.x, b1.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_vert(b.x, b.y, top_z);
|
||||
volume.qverts.push_vert(a.x, a.y, top_z);
|
||||
}
|
||||
|
||||
// top-left face
|
||||
{
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_norm(0,0,1);
|
||||
volume.qverts.push_vert(a.x, a.y, top_z);
|
||||
volume.qverts.push_vert(b.x, b.y, top_z);
|
||||
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_vert(b2.x, b2.y, middle_z);
|
||||
volume.qverts.push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
|
||||
// bottom-left face
|
||||
{
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_norm(xy_left_normal);
|
||||
volume.qverts.push_vert(a2.x, a2.y, middle_z);
|
||||
volume.qverts.push_vert(b2.x, b2.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_norm(0,0,-1);
|
||||
volume.qverts.push_vert(b.x, b.y, bottom_z);
|
||||
volume.qverts.push_vert(a.x, a.y, bottom_z);
|
||||
}
|
||||
|
||||
first_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLVertexArray::load_mesh(const TriangleMesh &mesh)
|
||||
// Fill in the qverts and tverts with quads and triangles for the extrusion_path.
|
||||
static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, const Point ©, GLVolume &volume)
|
||||
{
|
||||
this->reserve_more(3 * 3 * mesh.facets_count());
|
||||
|
||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||
stl_facet &facet = mesh.stl.facet_start[i];
|
||||
for (int j = 0; j <= 2; ++j) {
|
||||
this->push_norm(facet.normal.x, facet.normal.y, facet.normal.z);
|
||||
this->push_vert(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z);
|
||||
Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(copy);
|
||||
Lines lines = polyline.lines();
|
||||
std::vector<double> widths(lines.size(), extrusion_path.width);
|
||||
std::vector<double> heights(lines.size(), extrusion_path.height);
|
||||
thick_lines_to_verts(lines, widths, heights, false, print_z, volume);
|
||||
}
|
||||
|
||||
// Fill in the qverts and tverts with quads and triangles for the extrusion_loop.
|
||||
static inline void extrusionentity_to_verts(const ExtrusionLoop &extrusion_loop, float print_z, const Point ©, GLVolume &volume)
|
||||
{
|
||||
Lines lines;
|
||||
std::vector<double> widths;
|
||||
std::vector<double> heights;
|
||||
for (const ExtrusionPath &extrusion_path : extrusion_loop.paths) {
|
||||
Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(copy);
|
||||
Lines lines_this = polyline.lines();
|
||||
append(lines, lines_this);
|
||||
widths.insert(widths.end(), lines_this.size(), extrusion_path.width);
|
||||
heights.insert(heights.end(), lines_this.size(), extrusion_path.height);
|
||||
}
|
||||
thick_lines_to_verts(lines, widths, heights, true, print_z, volume);
|
||||
}
|
||||
|
||||
// Fill in the qverts and tverts with quads and triangles for the extrusion_multi_path.
|
||||
static inline void extrusionentity_to_verts(const ExtrusionMultiPath &extrusion_multi_path, float print_z, const Point ©, GLVolume &volume)
|
||||
{
|
||||
Lines lines;
|
||||
std::vector<double> widths;
|
||||
std::vector<double> heights;
|
||||
for (const ExtrusionPath &extrusion_path : extrusion_multi_path.paths) {
|
||||
Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(copy);
|
||||
Lines lines_this = polyline.lines();
|
||||
append(lines, lines_this);
|
||||
widths.insert(widths.end(), lines_this.size(), extrusion_path.width);
|
||||
heights.insert(heights.end(), lines_this.size(), extrusion_path.height);
|
||||
}
|
||||
thick_lines_to_verts(lines, widths, heights, false, print_z, volume);
|
||||
}
|
||||
|
||||
static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume);
|
||||
|
||||
static inline void extrusionentity_to_verts(const ExtrusionEntityCollection &extrusion_entity_collection, float print_z, const Point ©, GLVolume &volume)
|
||||
{
|
||||
for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities)
|
||||
extrusionentity_to_verts(extrusion_entity, print_z, copy, volume);
|
||||
}
|
||||
|
||||
static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume)
|
||||
{
|
||||
if (extrusion_entity != nullptr) {
|
||||
auto *extrusion_path = dynamic_cast<const ExtrusionPath*>(extrusion_entity);
|
||||
if (extrusion_path != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_path, print_z, copy, volume);
|
||||
else {
|
||||
auto *extrusion_loop = dynamic_cast<const ExtrusionLoop*>(extrusion_entity);
|
||||
if (extrusion_loop != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_loop, print_z, copy, volume);
|
||||
else {
|
||||
auto *extrusion_multi_path = dynamic_cast<const ExtrusionMultiPath*>(extrusion_entity);
|
||||
if (extrusion_multi_path != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_multi_path, print_z, copy, volume);
|
||||
else {
|
||||
auto *extrusion_entity_collection = dynamic_cast<const ExtrusionEntityCollection*>(extrusion_entity);
|
||||
if (extrusion_entity_collection != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume);
|
||||
else {
|
||||
CONFESS("Unexpected extrusion_entity type in to_verts()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create 3D thick extrusion lines for a skirt and brim.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||
void _3DScene::_load_print_toolpaths(const Print *print, GLVolumeCollection *volumes)
|
||||
{
|
||||
if (! print->has_skirt() && print->config.brim_width.value == 0)
|
||||
return;
|
||||
|
||||
const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
||||
|
||||
// number of skirt layers
|
||||
size_t total_layer_count = 0;
|
||||
for (const PrintObject *print_object : print->objects)
|
||||
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||
size_t skirt_height = print->has_infinite_skirt() ?
|
||||
total_layer_count :
|
||||
std::min<size_t>(print->config.skirt_height.value, total_layer_count);
|
||||
if (skirt_height == 0 && print->config.brim_width.value > 0)
|
||||
skirt_height = 1;
|
||||
|
||||
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
||||
const PrintObject *object0 = print->objects.front();
|
||||
std::vector<float> print_zs;
|
||||
print_zs.reserve(skirt_height * 2);
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++ i)
|
||||
print_zs.push_back(float(object0->layers[i]->print_z));
|
||||
//FIXME why there are support layers?
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++ i)
|
||||
print_zs.push_back(float(object0->support_layers[i]->print_z));
|
||||
std::sort(print_zs.begin(), print_zs.end());
|
||||
print_zs.erase(std::unique(print_zs.begin(), print_zs.end()), print_zs.end());
|
||||
if (print_zs.size() > skirt_height)
|
||||
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
||||
|
||||
volumes->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &volume = *volumes->volumes.back();
|
||||
for (size_t i = 0; i < skirt_height; ++ i) {
|
||||
volume.print_zs.push_back(print_zs[i]);
|
||||
volume.offsets.push_back(volume.qverts.size());
|
||||
volume.offsets.push_back(volume.tverts.size());
|
||||
if (i == 0)
|
||||
extrusionentity_to_verts(print->brim, print_zs[i], Point(0, 0), volume);
|
||||
extrusionentity_to_verts(print->skirt, print_zs[i], Point(0, 0), volume);
|
||||
}
|
||||
auto bb = print->bounding_box();
|
||||
volume.bounding_box.merge(Pointf3(unscale(bb.min.x), unscale(bb.min.y), 0.f));
|
||||
volume.bounding_box.merge(Pointf3(unscale(bb.max.x), unscale(bb.max.y), 0.f));
|
||||
}
|
||||
|
||||
// Create 3D thick extrusion lines for object forming extrusions.
|
||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||
// one for perimeters, one for infill and one for supports.
|
||||
void _3DScene::_load_print_object_toolpaths(
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes)
|
||||
{
|
||||
struct Ctxt
|
||||
{
|
||||
const Points *shifted_copies;
|
||||
std::vector<const Layer*> layers;
|
||||
// Bounding box of the object and its copies.
|
||||
BoundingBoxf3 bbox;
|
||||
bool has_perimeters;
|
||||
bool has_infill;
|
||||
bool has_support;
|
||||
|
||||
// static const size_t alloc_size_max () { return 32 * 1048576 / 4; }
|
||||
static const size_t alloc_size_max () { return 4 * 1048576 / 4; }
|
||||
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||
|
||||
static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
||||
static const float* color_infill () { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
||||
static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||
} ctxt;
|
||||
|
||||
ctxt.shifted_copies = &print_object->_shifted_copies;
|
||||
|
||||
// order layers by print_z
|
||||
ctxt.layers.reserve(print_object->layers.size() + print_object->support_layers.size());
|
||||
for (const Layer *layer : print_object->layers)
|
||||
ctxt.layers.push_back(layer);
|
||||
for (const Layer *layer : print_object->support_layers)
|
||||
ctxt.layers.push_back(layer);
|
||||
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||
|
||||
for (const Point ©: print_object->_shifted_copies) {
|
||||
BoundingBox cbb = print_object->bounding_box();
|
||||
cbb.translate(copy.x, copy.y);
|
||||
ctxt.bbox.merge(Pointf3(unscale(cbb.min.x), unscale(cbb.min.y), 0.f));
|
||||
ctxt.bbox.merge(Pointf3(unscale(cbb.max.x), unscale(cbb.max.y), 0.f));
|
||||
}
|
||||
|
||||
// Maximum size of an allocation block: 32MB / sizeof(float)
|
||||
ctxt.has_perimeters = print_object->state.is_done(posPerimeters);
|
||||
ctxt.has_infill = print_object->state.is_done(posInfill);
|
||||
ctxt.has_support = print_object->state.is_done(posSupportMaterial);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
||||
|
||||
//FIXME Improve the heuristics for a grain size.
|
||||
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
||||
std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size(), GLVolumeCollection());
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||
[&ctxt, &volumes_per_thread](const tbb::blocked_range<size_t>& range) {
|
||||
std::vector<GLVolume*> &volumes = volumes_per_thread[range.begin()].volumes;
|
||||
volumes.emplace_back(new GLVolume(ctxt.color_perimeters()));
|
||||
volumes.emplace_back(new GLVolume(ctxt.color_infill()));
|
||||
volumes.emplace_back(new GLVolume(ctxt.color_support()));
|
||||
size_t vols[3] = { 0, 1, 2 };
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
GLVolume &volume = *volumes[i];
|
||||
volume.bounding_box = ctxt.bbox;
|
||||
volume.qverts.reserve(ctxt.alloc_size_reserve());
|
||||
volume.tverts.reserve(ctxt.alloc_size_reserve());
|
||||
}
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
const Layer *layer = ctxt.layers[idx_layer];
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
GLVolume &vol = *volumes[vols[i]];
|
||||
if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
|
||||
vol.print_zs.push_back(layer->print_z);
|
||||
vol.offsets.push_back(vol.qverts.size());
|
||||
vol.offsets.push_back(vol.tverts.size());
|
||||
}
|
||||
}
|
||||
for (const Point ©: *ctxt.shifted_copies) {
|
||||
for (const LayerRegion *layerm : layer->regions) {
|
||||
if (ctxt.has_perimeters)
|
||||
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, *volumes[vols[0]]);
|
||||
if (ctxt.has_infill)
|
||||
extrusionentity_to_verts(layerm->fills, float(layer->print_z), copy, *volumes[vols[1]]);
|
||||
}
|
||||
if (ctxt.has_support) {
|
||||
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
||||
if (support_layer) {
|
||||
extrusionentity_to_verts(support_layer->support_fills, float(layer->print_z), copy, *volumes[vols[2]]);
|
||||
extrusionentity_to_verts(support_layer->support_interface_fills, float(layer->print_z), copy, *volumes[vols[2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
GLVolume &vol = *volumes[vols[i]];
|
||||
if (vol.qverts.size() > ctxt.alloc_size_max() || vol.tverts.size() > ctxt.alloc_size_max()) {
|
||||
// Shrink the old vectors to preserve memory.
|
||||
vol.qverts.shrink_to_fit();
|
||||
vol.tverts.shrink_to_fit();
|
||||
// Store the vertex arrays and restart their containers.
|
||||
vols[i] = volumes.size();
|
||||
volumes.emplace_back(new GLVolume(vol.color));
|
||||
GLVolume &vol_new = *volumes.back();
|
||||
vol_new.bounding_box = ctxt.bbox;
|
||||
vol_new.qverts.reserve(ctxt.alloc_size_reserve());
|
||||
vol_new.tverts.reserve(ctxt.alloc_size_reserve());
|
||||
}
|
||||
}
|
||||
}
|
||||
while (! volumes.empty() && volumes.back()->empty()) {
|
||||
delete volumes.back();
|
||||
volumes.pop_back();
|
||||
}
|
||||
});
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - merging results";
|
||||
|
||||
size_t volume_ptr = volumes->volumes.size();
|
||||
size_t num_volumes = volume_ptr;
|
||||
for (const GLVolumeCollection &v : volumes_per_thread)
|
||||
num_volumes += v.volumes.size();
|
||||
volumes->volumes.resize(num_volumes, nullptr);
|
||||
for (GLVolumeCollection &v : volumes_per_thread) {
|
||||
memcpy(volumes->volumes.data() + volume_ptr, v.volumes.data(), v.volumes.size() * sizeof(void*));
|
||||
volume_ptr += v.volumes.size();
|
||||
v.volumes.clear();
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,8 +8,20 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
class Print;
|
||||
class PrintObject;
|
||||
class Model;
|
||||
class ModelObject;
|
||||
|
||||
class GLVertexArray {
|
||||
public:
|
||||
public:
|
||||
GLVertexArray() {}
|
||||
GLVertexArray(const GLVertexArray &rhs) : verts(rhs.verts), norms(rhs.norms) {}
|
||||
GLVertexArray(GLVertexArray &&rhs) : verts(std::move(rhs.verts)), norms(std::move(rhs.norms)) {}
|
||||
|
||||
GLVertexArray& operator=(const GLVertexArray &rhs) { verts = rhs.verts; norms = rhs.norms; return *this; }
|
||||
GLVertexArray& operator=(GLVertexArray &&rhs) { verts = std::move(rhs.verts); norms = std::move(rhs.norms); return *this; }
|
||||
|
||||
std::vector<float> verts, norms;
|
||||
|
||||
void reserve(size_t len) {
|
||||
|
@ -41,14 +53,174 @@ class GLVertexArray {
|
|||
this->norms.push_back(z);
|
||||
};
|
||||
void load_mesh(const TriangleMesh &mesh);
|
||||
|
||||
size_t size() const { return verts.size(); }
|
||||
bool empty() const { return verts.empty(); }
|
||||
void shrink_to_fit() { this->verts.shrink_to_fit(); this->norms.shrink_to_fit(); }
|
||||
|
||||
BoundingBoxf3 bounding_box() const {
|
||||
BoundingBoxf3 bbox;
|
||||
if (! this->verts.empty()) {
|
||||
bbox.min.x = bbox.max.x = this->verts[0];
|
||||
bbox.min.y = bbox.max.y = this->verts[1];
|
||||
bbox.min.z = bbox.max.z = this->verts[2];
|
||||
for (size_t i = 3; i < this->verts.size(); i += 3) {
|
||||
bbox.min.x = std::min<coordf_t>(bbox.min.x, this->verts[i + 0]);
|
||||
bbox.min.y = std::min<coordf_t>(bbox.min.y, this->verts[i + 1]);
|
||||
bbox.min.z = std::min<coordf_t>(bbox.min.z, this->verts[i + 2]);
|
||||
bbox.max.x = std::max<coordf_t>(bbox.max.x, this->verts[i + 0]);
|
||||
bbox.max.y = std::max<coordf_t>(bbox.max.y, this->verts[i + 1]);
|
||||
bbox.max.z = std::max<coordf_t>(bbox.max.z, this->verts[i + 2]);
|
||||
}
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
};
|
||||
|
||||
class GLTexture
|
||||
{
|
||||
public:
|
||||
GLTexture() : width(0), height(0), levels(0), cells(0) {}
|
||||
|
||||
// Texture data
|
||||
std::vector<char> data;
|
||||
// Width of the texture, top level.
|
||||
size_t width;
|
||||
// Height of the texture, top level.
|
||||
size_t height;
|
||||
// For how many levels of detail is the data allocated?
|
||||
size_t levels;
|
||||
// Number of texture cells allocated for the height texture.
|
||||
size_t cells;
|
||||
};
|
||||
|
||||
class GLVolume {
|
||||
public:
|
||||
GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) :
|
||||
composite_id(-1),
|
||||
select_group_id(-1),
|
||||
drag_group_id(-1),
|
||||
selected(false),
|
||||
hover(false),
|
||||
qverts_range(0, size_t(-1)),
|
||||
tverts_range(0, size_t(-1))
|
||||
{
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
color[3] = a;
|
||||
}
|
||||
GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
|
||||
|
||||
std::vector<int> load_object(
|
||||
const ModelObject *model_object,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by);
|
||||
|
||||
// Bounding box of this volume, in unscaled coordinates.
|
||||
BoundingBoxf3 bounding_box;
|
||||
// Offset of the volume to be rendered.
|
||||
Pointf3 origin;
|
||||
// Color of the triangles / quads held by this volume.
|
||||
float color[4];
|
||||
|
||||
// An ID containing the object ID, volume ID and instance ID.
|
||||
int composite_id;
|
||||
// An ID for group selection. It may be the same for all meshes of all object instances, or for just a single object instance.
|
||||
int select_group_id;
|
||||
// An ID for group dragging. It may be the same for all meshes of all object instances, or for just a single object instance.
|
||||
int drag_group_id;
|
||||
// Is this object selected?
|
||||
bool selected;
|
||||
// Boolean: Is mouse over this object?
|
||||
bool hover;
|
||||
|
||||
// Geometric data.
|
||||
// Quad vertices.
|
||||
GLVertexArray qverts;
|
||||
std::pair<size_t, size_t> qverts_range;
|
||||
// Triangle vertices.
|
||||
GLVertexArray tverts;
|
||||
std::pair<size_t, size_t> tverts_range;
|
||||
// If the qverts or tverts contain thick extrusions, then offsets keeps pointers of the starts
|
||||
// of the extrusions per layer.
|
||||
// The offsets stores tripples of (z_top, qverts_idx, tverts_idx) in a linear array.
|
||||
std::vector<coordf_t> print_zs;
|
||||
std::vector<size_t> offsets;
|
||||
|
||||
int object_idx() const { return this->composite_id / 1000000; }
|
||||
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
|
||||
int instance_idx() const { return this->composite_id % 1000; }
|
||||
BoundingBoxf3 transformed_bounding_box() const { BoundingBoxf3 bb = this->bounding_box; bb.translate(this->origin); return bb; }
|
||||
bool empty() const { return qverts.size() < 4 && tverts.size() < 3; }
|
||||
|
||||
void set_range(coordf_t low, coordf_t high);
|
||||
|
||||
void* qverts_to_render_ptr() { return qverts.verts.data() + qverts_range.first; }
|
||||
void* qnorms_to_render_ptr() { return qverts.norms.data() + qverts_range.first; }
|
||||
size_t qverts_to_render_cnt() { return std::min(qverts.verts.size(), qverts_range.second - qverts_range.first); }
|
||||
void* tverts_to_render_ptr() { return tverts.verts.data() + tverts_range.first; }
|
||||
void* tnorms_to_render_ptr() { return tverts.norms.data() + tverts_range.first; }
|
||||
size_t tverts_to_render_cnt() { return std::min(tverts.verts.size(), tverts_range.second - tverts_range.first); }
|
||||
|
||||
std::shared_ptr<GLTexture> layer_height_texture;
|
||||
|
||||
bool has_layer_height_texture() const
|
||||
{ return this->layer_height_texture.get() != nullptr; }
|
||||
size_t layer_height_texture_width() const
|
||||
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->width; }
|
||||
size_t layer_height_texture_height() const
|
||||
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->height; }
|
||||
size_t layer_height_texture_cells() const
|
||||
{ return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->cells; }
|
||||
void* layer_height_texture_data_ptr_level0() {
|
||||
return (layer_height_texture.get() == nullptr) ? 0 :
|
||||
(void*)layer_height_texture->data.data();
|
||||
}
|
||||
void* layer_height_texture_data_ptr_level1() {
|
||||
return (layer_height_texture.get() == nullptr) ? 0 :
|
||||
(void*)(layer_height_texture->data.data() + layer_height_texture->width * layer_height_texture->height * 4);
|
||||
}
|
||||
double layer_height_texture_z_to_row_id() const {
|
||||
return (this->layer_height_texture.get() == nullptr) ? 0. :
|
||||
double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * bounding_box.max.z);
|
||||
}
|
||||
void generate_layer_height_texture(PrintObject *print_object, bool force);
|
||||
};
|
||||
|
||||
class GLVolumeCollection
|
||||
{
|
||||
public:
|
||||
std::vector<GLVolume*> volumes;
|
||||
|
||||
GLVolumeCollection() {};
|
||||
~GLVolumeCollection() { clear(); };
|
||||
|
||||
std::vector<int> load_object(
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by);
|
||||
|
||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||
bool empty() const { return volumes.empty(); }
|
||||
void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); }
|
||||
};
|
||||
|
||||
class _3DScene
|
||||
{
|
||||
public:
|
||||
static void _extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
|
||||
const std::vector<double> &heights, bool closed, double top_z, const Point ©,
|
||||
GLVertexArray* qverts, GLVertexArray* tverts);
|
||||
public:
|
||||
static void _load_print_toolpaths(
|
||||
const Print *print,
|
||||
GLVolumeCollection *volumes);
|
||||
|
||||
static void _load_print_object_toolpaths(
|
||||
const PrintObject *print_object,
|
||||
GLVolumeCollection *volumes);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,26 +3,101 @@
|
|||
#include <xsinit.h>
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
%name{Slic3r::GUI::_3DScene::GLVertexArray} class GLVertexArray {
|
||||
GLVertexArray();
|
||||
~GLVertexArray();
|
||||
void load_mesh(TriangleMesh* mesh) const
|
||||
%code%{ THIS->load_mesh(*mesh); %};
|
||||
size_t size() const
|
||||
%code%{ RETVAL = THIS->verts.size(); %};
|
||||
void* verts_ptr() const
|
||||
%code%{ RETVAL = THIS->verts.empty() ? 0 : &THIS->verts.front(); %};
|
||||
void* norms_ptr() const
|
||||
%code%{ RETVAL = THIS->verts.empty() ? 0 : &THIS->norms.front(); %};
|
||||
%name{Slic3r::GUI::_3DScene::GLVolume} class GLVolume {
|
||||
GLVolume();
|
||||
~GLVolume();
|
||||
|
||||
std::vector<double> color()
|
||||
%code%{ RETVAL.reserve(4); RETVAL.push_back(THIS->color[0]); RETVAL.push_back(THIS->color[1]); RETVAL.push_back(THIS->color[2]); RETVAL.push_back(THIS->color[3]); %};
|
||||
int composite_id()
|
||||
%code%{ RETVAL = THIS->composite_id; %};
|
||||
int select_group_id()
|
||||
%code%{ RETVAL = THIS->select_group_id; %};
|
||||
int drag_group_id()
|
||||
%code%{ RETVAL = THIS->drag_group_id; %};
|
||||
int selected()
|
||||
%code%{ RETVAL = THIS->selected; %};
|
||||
void set_selected(int i)
|
||||
%code%{ THIS->selected = i; %};
|
||||
int hover()
|
||||
%code%{ RETVAL = THIS->hover; %};
|
||||
void set_hover(int i)
|
||||
%code%{ THIS->hover = i; %};
|
||||
|
||||
int object_idx() const;
|
||||
int volume_idx() const;
|
||||
int instance_idx() const;
|
||||
bool empty() const;
|
||||
Clone<Pointf3> origin() const
|
||||
%code%{ RETVAL = THIS->origin; %};
|
||||
Clone<BoundingBoxf3> bounding_box() const
|
||||
%code%{ RETVAL = THIS->bounding_box; %};
|
||||
Clone<BoundingBoxf3> transformed_bounding_box() const;
|
||||
|
||||
void* qverts_to_render_ptr();
|
||||
void* qnorms_to_render_ptr();
|
||||
int qverts_to_render_cnt();
|
||||
void* tverts_to_render_ptr();
|
||||
void* tnorms_to_render_ptr();
|
||||
int tverts_to_render_cnt();
|
||||
|
||||
bool has_layer_height_texture();
|
||||
int layer_height_texture_width();
|
||||
int layer_height_texture_height();
|
||||
int layer_height_texture_cells();
|
||||
void* layer_height_texture_data_ptr_level0();
|
||||
void* layer_height_texture_data_ptr_level1();
|
||||
double layer_height_texture_z_to_row_id() const;
|
||||
void generate_layer_height_texture(PrintObject *print_object, bool force);
|
||||
};
|
||||
|
||||
|
||||
%name{Slic3r::GUI::_3DScene::GLVolume::Collection} class GLVolumeCollection {
|
||||
GLVolumeCollection();
|
||||
~GLVolumeCollection();
|
||||
|
||||
std::vector<int> load_object(ModelObject *object, int obj_idx, std::vector<int> instance_idxs, std::string color_by, std::string select_by, std::string drag_by);
|
||||
|
||||
void erase()
|
||||
%code{% THIS->clear(); %};
|
||||
|
||||
int count()
|
||||
%code{% RETVAL = THIS->volumes.size(); %};
|
||||
|
||||
void set_range(double low, double high);
|
||||
%{
|
||||
|
||||
SV*
|
||||
GLVolumeCollection::arrayref()
|
||||
CODE:
|
||||
AV* av = newAV();
|
||||
av_fill(av, THIS->volumes.size()-1);
|
||||
int i = 0;
|
||||
for (GLVolume *v : THIS->volumes) {
|
||||
av_store(av, i++, perl_to_SV_ref(*v));
|
||||
}
|
||||
RETVAL = newRV_noinc((SV*)av);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
%package{Slic3r::GUI::_3DScene};
|
||||
%{
|
||||
|
||||
void
|
||||
_extrusionentity_to_verts_do(Lines lines, std::vector<double> widths, std::vector<double> heights, bool closed, double top_z, Point* copy, GLVertexArray* qverts, GLVertexArray* tverts)
|
||||
_load_print_toolpaths(print, volumes)
|
||||
Print *print;
|
||||
GLVolumeCollection *volumes;
|
||||
CODE:
|
||||
_3DScene::_extrusionentity_to_verts_do(lines, widths, heights, closed,
|
||||
top_z, *copy, qverts, tverts);
|
||||
_3DScene::_load_print_toolpaths(print, volumes);
|
||||
|
||||
%}
|
||||
void
|
||||
_load_print_object_toolpaths(print_object, volumes)
|
||||
PrintObject *print_object;
|
||||
GLVolumeCollection *volumes;
|
||||
CODE:
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes);
|
||||
|
||||
%}
|
||||
|
|
|
@ -143,20 +143,6 @@ _constant()
|
|||
|
||||
void reset_layer_height_profile();
|
||||
|
||||
int generate_layer_height_texture(void *data, int rows, int cols, bool force = true)
|
||||
%code%{
|
||||
force |= THIS->update_layer_height_profile(THIS->model_object()->layer_height_profile);
|
||||
if (force) {
|
||||
SlicingParameters slicing_params = THIS->slicing_parameters();
|
||||
bool level_of_detail_2nd_level = true;
|
||||
RETVAL = generate_layer_height_texture(
|
||||
slicing_params,
|
||||
generate_object_layers(slicing_params, THIS->model_object()->layer_height_profile),
|
||||
data, rows, cols, level_of_detail_2nd_level);
|
||||
} else
|
||||
RETVAL = 0;
|
||||
%};
|
||||
|
||||
int ptr()
|
||||
%code%{ RETVAL = (int)(intptr_t)THIS; %};
|
||||
};
|
||||
|
|
|
@ -233,7 +233,10 @@ PrintObjectSupportMaterial* O_OBJECT_SLIC3R
|
|||
Ref<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
|
||||
Clone<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
|
||||
|
||||
GLVertexArray* O_OBJECT_SLIC3R
|
||||
GLVolume* O_OBJECT_SLIC3R
|
||||
Ref<GLVolume> O_OBJECT_SLIC3R_T
|
||||
GLVolumeCollection* O_OBJECT_SLIC3R
|
||||
Ref<GLVolumeCollection> O_OBJECT_SLIC3R_T
|
||||
|
||||
Axis T_UV
|
||||
ExtrusionLoopRole T_UV
|
||||
|
|
|
@ -211,7 +211,10 @@
|
|||
%typemap{ModelInstancePtrs*};
|
||||
%typemap{Ref<ModelInstancePtrs>}{simple};
|
||||
%typemap{Clone<ModelInstancePtrs>}{simple};
|
||||
%typemap{GLVertexArray*};
|
||||
%typemap{GLVolume*};
|
||||
%typemap{Ref<GLVolume>}{simple};
|
||||
%typemap{GLVolumeCollection*};
|
||||
%typemap{Ref<GLVolumeCollection>}{simple};
|
||||
|
||||
%typemap{PrintRegionPtrs*};
|
||||
%typemap{PrintObjectPtrs*};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue