Skip to content

Commit

Permalink
Merge branch 'lm_triangle_selector'
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasmatena committed Jul 24, 2020
2 parents 0280a2a + 248fba8 commit 87824ef
Show file tree
Hide file tree
Showing 9 changed files with 1,171 additions and 228 deletions.
2 changes: 2 additions & 0 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ add_library(libslic3r STATIC
Utils.hpp
Time.cpp
Time.hpp
TriangleSelector.cpp
TriangleSelector.hpp
MTUtils.hpp
VoronoiOffset.cpp
VoronoiOffset.hpp
Expand Down
17 changes: 17 additions & 0 deletions src/libslic3r/Format/3mf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const char* OBJECTID_ATTR = "objectid";
const char* TRANSFORM_ATTR = "transform";
const char* PRINTABLE_ATTR = "printable";
const char* INSTANCESCOUNT_ATTR = "instances_count";
const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";

const char* KEY_ATTR = "key";
const char* VALUE_ATTR = "value";
Expand Down Expand Up @@ -283,6 +284,7 @@ namespace Slic3r {
{
std::vector<float> vertices;
std::vector<unsigned int> triangles;
std::vector<std::string> custom_supports;

bool empty()
{
Expand All @@ -293,6 +295,7 @@ namespace Slic3r {
{
vertices.clear();
triangles.clear();
custom_supports.clear();
}
};

Expand Down Expand Up @@ -1539,6 +1542,8 @@ namespace Slic3r {
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V1_ATTR));
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V2_ATTR));
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V3_ATTR));

m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
return true;
}

Expand Down Expand Up @@ -1872,6 +1877,13 @@ namespace Slic3r {
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
volume->calculate_convex_hull();

// recreate custom supports from previously loaded attribute
assert(geometry.custom_supports.size() == triangles_count);
for (unsigned i=0; i<triangles_count; ++i) {
if (! geometry.custom_supports[i].empty())
volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[i]);
}

// apply the remaining volume's metadata
for (const Metadata& metadata : volume_data.metadata)
{
Expand Down Expand Up @@ -2383,6 +2395,11 @@ namespace Slic3r {
{
stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" ";
}

std::string custom_supports_data_string = volume->m_supported_facets.get_triangle_as_string(i);
if (! custom_supports_data_string.empty())
stream << CUSTOM_SUPPORTS_ATTR << "=\"" << custom_supports_data_string << "\" ";

stream << "/>\n";
}
}
Expand Down
86 changes: 71 additions & 15 deletions src/libslic3r/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ModelArrange.hpp"
#include "Geometry.hpp"
#include "MTUtils.hpp"
#include "TriangleSelector.hpp"

#include "Format/AMF.hpp"
#include "Format/OBJ.hpp"
Expand Down Expand Up @@ -1830,28 +1831,25 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
}


std::vector<int> FacetsAnnotation::get_facets(FacetSupportType type) const
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, FacetSupportType type) const
{
std::vector<int> out;
for (auto& [facet_idx, this_type] : m_data)
if (this_type == type)
out.push_back(facet_idx);
TriangleSelector selector(mv.mesh());
selector.deserialize(m_data);
indexed_triangle_set out = selector.get_facets(type);
return out;
}



void FacetsAnnotation::set_facet(int idx, FacetSupportType type)
bool FacetsAnnotation::set(const TriangleSelector& selector)
{
bool changed = true;

if (type == FacetSupportType::NONE)
changed = m_data.erase(idx) != 0;
else
m_data[idx] = type;

if (changed)
std::map<int, std::vector<bool>> sel_map = selector.serialize();
if (sel_map != m_data) {
m_data = sel_map;
update_timestamp();
return true;
}
return false;
}


Expand All @@ -1864,6 +1862,64 @@ void FacetsAnnotation::clear()



// Following function takes data from a triangle and encodes it as string
// of hexadecimal numbers (one digit per triangle). Used for 3MF export,
// changing it may break backwards compatibility !!!!!
std::string FacetsAnnotation::get_triangle_as_string(int triangle_idx) const
{
std::string out;

auto triangle_it = m_data.find(triangle_idx);
if (triangle_it != m_data.end()) {
const std::vector<bool>& code = triangle_it->second;
int offset = 0;
while (offset < int(code.size())) {
int next_code = 0;
for (int i=3; i>=0; --i) {
next_code = next_code << 1;
next_code |= int(code[offset + i]);
}
offset += 4;

assert(next_code >=0 && next_code <= 15);
char digit = next_code < 10 ? next_code + '0' : (next_code-10)+'A';
out.insert(out.begin(), digit);
}
}
return out;
}



// Recover triangle splitting & state from string of hexadecimal values previously
// generated by get_triangle_as_string. Used to load from 3MF.
void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::string& str)
{
assert(! str.empty());
m_data[triangle_id] = std::vector<bool>(); // zero current state or create new
std::vector<bool>& code = m_data[triangle_id];

for (auto it = str.crbegin(); it != str.crend(); ++it) {
const char ch = *it;
int dec = 0;
if (ch >= '0' && ch<='9')
dec = int(ch - '0');
else if (ch >='A' && ch <= 'F')
dec = 10 + int(ch - 'A');
else
assert(false);

// Convert to binary and append into code.
for (int i=0; i<4; ++i) {
code.insert(code.end(), bool(dec & (1 << i)));
}
}


}



// Test whether the two models contain the same number of ModelObjects with the same set of IDs
// ordered in the same order. In that case it is not necessary to kill the background processing.
bool model_object_list_equal(const Model &model_old, const Model &model_new)
Expand Down Expand Up @@ -1935,7 +1991,7 @@ bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject
return true;
}
return false;
};
}

extern bool model_has_multi_part_objects(const Model &model)
{
Expand Down
11 changes: 8 additions & 3 deletions src/libslic3r/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ModelVolume;
class ModelWipeTower;
class Print;
class SLAPrint;
class TriangleSelector;

namespace UndoRedo {
class StackImpl;
Expand Down Expand Up @@ -394,6 +395,7 @@ enum class ModelVolumeType : int {
};

enum class FacetSupportType : int8_t {
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits!
NONE = 0,
ENFORCER = 1,
BLOCKER = 2
Expand All @@ -403,9 +405,12 @@ class FacetsAnnotation {
public:
using ClockType = std::chrono::steady_clock;

std::vector<int> get_facets(FacetSupportType type) const;
void set_facet(int idx, FacetSupportType type);
const std::map<int, std::vector<bool>>& get_data() const { return m_data; }
bool set(const TriangleSelector& selector);
indexed_triangle_set get_facets(const ModelVolume& mv, FacetSupportType type) const;
void clear();
std::string get_triangle_as_string(int i) const;
void set_triangle_from_string(int triangle_id, const std::string& str);

ClockType::time_point get_timestamp() const { return timestamp; }
bool is_same_as(const FacetsAnnotation& other) const {
Expand All @@ -418,7 +423,7 @@ class FacetsAnnotation {
}

private:
std::map<int, FacetSupportType> m_data;
std::map<int, std::vector<bool>> m_data;

ClockType::time_point timestamp;
void update_timestamp() {
Expand Down
17 changes: 9 additions & 8 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2673,14 +2673,14 @@ void PrintObject::project_and_append_custom_supports(
FacetSupportType type, std::vector<ExPolygons>& expolys) const
{
for (const ModelVolume* mv : this->model_object()->volumes) {
const std::vector<int> custom_facets = mv->m_supported_facets.get_facets(type);
if (custom_facets.empty())
const indexed_triangle_set custom_facets = mv->m_supported_facets.get_facets(*mv, type);
if (custom_facets.indices.empty())
continue;

const TriangleMesh& mesh = mv->mesh();
const Transform3f& tr1 = mv->get_matrix().cast<float>();
const Transform3f& tr2 = this->trafo().cast<float>();
const Transform3f tr = tr2 * tr1;
const float tr_det_sign = (tr.matrix().determinant() > 0. ? 1.f : -1.f);


// The projection will be at most a pentagon. Let's minimize heap
Expand All @@ -2705,22 +2705,23 @@ void PrintObject::project_and_append_custom_supports(
};

// Vector to collect resulting projections from each triangle.
std::vector<TriangleProjections> projections_of_triangles(custom_facets.size());
std::vector<TriangleProjections> projections_of_triangles(custom_facets.indices.size());

// Iterate over all triangles.
tbb::parallel_for(
tbb::blocked_range<size_t>(0, custom_facets.size()),
tbb::blocked_range<size_t>(0, custom_facets.indices.size()),
[&](const tbb::blocked_range<size_t>& range) {
for (size_t idx = range.begin(); idx < range.end(); ++ idx) {

std::array<Vec3f, 3> facet;

// Transform the triangle into worlds coords.
for (int i=0; i<3; ++i)
facet[i] = tr * mesh.its.vertices[mesh.its.indices[custom_facets[idx]](i)];
facet[i] = tr * custom_facets.vertices[custom_facets.indices[idx](i)];

// Ignore triangles with upward-pointing normal.
if ((facet[1]-facet[0]).cross(facet[2]-facet[0]).z() > 0.)
// Ignore triangles with upward-pointing normal. Don't forget about mirroring.
float z_comp = (facet[1]-facet[0]).cross(facet[2]-facet[0]).z();
if (tr_det_sign * z_comp > 0.)
continue;

// Sort the three vertices according to z-coordinate.
Expand Down
Loading

0 comments on commit 87824ef

Please sign in to comment.