Prepare multi volume source for cut surface job
This commit is contained in:
parent
6f1bcd2469
commit
e90c2c8e9a
@ -940,8 +940,8 @@ bool GLGizmoEmboss::process()
|
||||
const TextConfiguration &tc = data.text_configuration;
|
||||
if (tc.font_item.prop.use_surface) {
|
||||
// Model to cut surface from.
|
||||
auto sources = UseSurfaceData::get_sources_to_cut_surface_from(m_volume);
|
||||
if (sources.empty()) return false;
|
||||
UseSurfaceData::ModelSource source = UseSurfaceData::create_source(m_volume);
|
||||
if (source.its.empty()) return false;
|
||||
|
||||
Transform3d text_tr = m_volume->get_matrix();
|
||||
auto& fix_3mf = m_volume->text_configuration->fix_3mf_tr;
|
||||
@ -953,7 +953,7 @@ bool GLGizmoEmboss::process()
|
||||
assert(is_outside || m_volume->is_negative_volume() ||
|
||||
m_volume->is_modifier());
|
||||
UseSurfaceData surface_data{std::move(data), text_tr, is_outside,
|
||||
std::move(sources)};
|
||||
std::move(source)};
|
||||
job = std::make_unique<UseSurfaceJob>(std::move(surface_data));
|
||||
} else {
|
||||
job = std::make_unique<EmbossUpdateJob>(std::move(data));
|
||||
|
@ -318,62 +318,63 @@ void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
priv::update_volume(std::move(m_result), m_input);
|
||||
}
|
||||
|
||||
UseSurfaceData::ModelSources UseSurfaceData::get_sources_to_cut_surface_from(
|
||||
UseSurfaceData::ModelSource UseSurfaceData::create_source(
|
||||
const ModelVolume *text_volume)
|
||||
{
|
||||
if (text_volume == nullptr) return {};
|
||||
if (!text_volume->text_configuration.has_value()) return {};
|
||||
const auto &volumes = text_volume->get_object()->volumes;
|
||||
const ModelVolumePtrs &volumes = text_volume->get_object()->volumes;
|
||||
// no other volume in object
|
||||
if (volumes.size() <= 1) return {};
|
||||
|
||||
// One volume transformation is used for transform others
|
||||
// Most common cut is into one volume so it is cheaper to do not transform this volume
|
||||
// NOTE: Preparation is made on Main thred!
|
||||
auto find_biggest = [&text_volume]
|
||||
(const ModelVolumePtrs& volumes, const ObjectID& text_volume_id)->const ModelVolume * {
|
||||
const ModelVolume *biggest = nullptr;
|
||||
size_t biggest_size = 0;
|
||||
for (const ModelVolume *v: volumes) {
|
||||
if (v->id() == text_volume_id) continue;
|
||||
if (!v->is_model_part()) continue;
|
||||
const TriangleMesh &tm = v->mesh();
|
||||
if (tm.empty()) continue;
|
||||
if (tm.its.empty()) continue;
|
||||
if (biggest_size > tm.its.indices.size()) continue;
|
||||
biggest_size = tm.its.indices.size();
|
||||
biggest = v;
|
||||
}
|
||||
assert(biggest != nullptr);
|
||||
return biggest;
|
||||
};
|
||||
|
||||
UseSurfaceData::ModelSources result;
|
||||
const ModelVolume *biggest_volume = find_biggest(volumes, text_volume->id());
|
||||
const TriangleMesh &biggest_tm = biggest_volume->mesh();
|
||||
|
||||
// IMPROVE: Copy only AOI by shapes and projection
|
||||
// NOTE: copy of source mesh tringles and it slows down on big meshes
|
||||
ModelSource result{
|
||||
{biggest_tm.its}, // copy !!!
|
||||
biggest_volume->get_transformation().get_matrix(),
|
||||
biggest_tm.bounding_box()
|
||||
};
|
||||
|
||||
Transform3d tr_inv = result.tr.inverse();
|
||||
// Improve create object from part or use gl_volume
|
||||
// Get first model part in object
|
||||
for (const ModelVolume *v : volumes) {
|
||||
if (v->id() == text_volume->id()) continue;
|
||||
if (v->id() == biggest_volume->id()) continue;
|
||||
if (!v->is_model_part()) continue;
|
||||
const TriangleMesh &tm = v->mesh();
|
||||
if (tm.empty()) continue;
|
||||
if (tm.its.empty()) continue;
|
||||
UseSurfaceData::ModelSource ms = {tm.its,
|
||||
v->get_transformation().get_matrix(),
|
||||
tm.bounding_box()};
|
||||
result.push_back(std::move(ms));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UseSurfaceData::ModelSource UseSurfaceData::merge(ModelSources &sources)
|
||||
{
|
||||
if (sources.size() == 1) return sources.front();
|
||||
// find biggest its
|
||||
size_t max_index = 0;
|
||||
size_t max_vertices = 0;
|
||||
// calc sum of counts for resize
|
||||
size_t count_vertices = 0;
|
||||
size_t count_indices = 0;
|
||||
for (const ModelSource &source : sources) {
|
||||
count_vertices += source.its.vertices.size();
|
||||
count_indices += source.its.indices.size();
|
||||
if (max_vertices < source.its.vertices.size()) {
|
||||
max_vertices = source.its.vertices.size();
|
||||
max_index = &source - &sources.front();
|
||||
}
|
||||
Transform3d tr = v->get_matrix() * tr_inv;
|
||||
indexed_triangle_set its = tm.its; // copy !!!
|
||||
its_transform(its, tr);
|
||||
result.its.emplace_back(std::move(its));
|
||||
}
|
||||
|
||||
ModelSource &result = sources[max_index];
|
||||
result.its.vertices.reserve(count_vertices);
|
||||
result.its.indices.reserve(count_indices);
|
||||
Transform3d result_tr_inv = result.tr.inverse();
|
||||
for (size_t i = 0; i < sources.size(); i++) {
|
||||
if (i == max_index) continue;
|
||||
ModelSource &source = sources[i];
|
||||
Transform3d tr = source.tr * result_tr_inv;
|
||||
its_transform(source.its, tr);
|
||||
its_merge(result.its, std::move(source.its));
|
||||
}
|
||||
result.bb = bounding_box(result.its);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -405,12 +406,10 @@ void UseSurfaceJob::process(Ctl &ctl) {
|
||||
|
||||
if (was_canceled()) return;
|
||||
|
||||
const UseSurfaceData::ModelSource &source = UseSurfaceData::merge(m_input.sources);
|
||||
|
||||
Transform3d mesh_tr_inv = source.tr.inverse();
|
||||
Transform3d mesh_tr_inv = m_input.source.tr.inverse();
|
||||
Transform3d cut_projection_tr = mesh_tr_inv * m_input.text_tr;
|
||||
Transform3d emboss_tr = cut_projection_tr.inverse();
|
||||
BoundingBoxf3 mesh_bb_tr = source.bb.transformed(emboss_tr);
|
||||
BoundingBoxf3 mesh_bb_tr = m_input.source.bb.transformed(emboss_tr);
|
||||
std::pair<float, float> z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
|
||||
|
||||
const Emboss::FontFile &ff = *m_input.font_file.font_file;
|
||||
@ -426,10 +425,9 @@ void UseSurfaceJob::process(Ctl &ctl) {
|
||||
for (ExPolygon &shape : shapes)
|
||||
shape.translate(-projection_center);
|
||||
|
||||
// TODO: prepare multi model -> source.its
|
||||
|
||||
// Use CGAL to cut surface from triangle mesh
|
||||
SurfaceCut cut = cut_surface(shapes, {source.its}, cut_projection, projection_ratio);
|
||||
SurfaceCut cut = cut_surface(shapes, m_input.source.its,
|
||||
cut_projection, projection_ratio);
|
||||
if (cut.empty())
|
||||
throw priv::EmbossJobException(
|
||||
_u8L("There is no valid surface for text projection.").c_str());
|
||||
@ -514,8 +512,8 @@ bool priv::check(const EmbossDataUpdate &input, bool is_main_thread){
|
||||
}
|
||||
bool priv::check(const UseSurfaceData &input, bool is_main_thread){
|
||||
bool res = check((EmbossDataUpdate) input, is_main_thread);
|
||||
assert(!input.sources.empty());
|
||||
res &= !input.sources.empty();
|
||||
assert(!input.source.its.empty());
|
||||
res &= !input.source.its.empty();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -161,32 +161,22 @@ struct UseSurfaceData : public EmbossDataUpdate
|
||||
|
||||
struct ModelSource
|
||||
{
|
||||
// IMPROVE: copy of source mesh tringles
|
||||
// copy could slow down on big meshes
|
||||
// but proccessing on thread need it
|
||||
indexed_triangle_set its;
|
||||
// IMPROVE: Copy only AOI by shapes and projection
|
||||
// NOTE: copy of source mesh tringles and it slows down on big meshes
|
||||
std::vector<indexed_triangle_set> its;
|
||||
// Transformation of volume inside of object
|
||||
Transform3d tr;
|
||||
// extract bounds for projection
|
||||
BoundingBoxf3 bb;
|
||||
};
|
||||
using ModelSources = std::vector<ModelSource>;
|
||||
ModelSources sources;
|
||||
ModelSource source;
|
||||
|
||||
/// <summary>
|
||||
/// Copied triangles from object to be able create mesh for cut surface
|
||||
/// Copied triangles from object to be able create mesh for cut surface from
|
||||
/// </summary>
|
||||
/// <param name="text_volume">Define text in object</param>
|
||||
/// <returns>Source data for cut surface from</returns>
|
||||
static ModelSources get_sources_to_cut_surface_from(
|
||||
const ModelVolume *text_volume);
|
||||
|
||||
/// <summary>
|
||||
/// Merging of source together
|
||||
/// </summary>
|
||||
/// <param name="sources">Define input by multiple triangle models</param>
|
||||
/// <returns>Create one Source</returns>
|
||||
static ModelSource merge(ModelSources& sources);
|
||||
static ModelSource create_source(const ModelVolume *text_volume);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -202,6 +192,8 @@ public:
|
||||
UseSurfaceJob(UseSurfaceData &&input);
|
||||
void process(Ctl &ctl) override;
|
||||
void finalize(bool canceled, std::exception_ptr &eptr) override;
|
||||
// prepare multi volume input
|
||||
static std::vector<indexed_triangle_set> transform_volumes(ModelVolume *mv);
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
Loading…
Reference in New Issue
Block a user