Inform user about unsuccessfull cut surface from job
This commit is contained in:
parent
ff604785f6
commit
4af976e19c
@ -116,7 +116,6 @@ static bool is_text_empty(const std::string &text){
|
|||||||
return text.empty() ||
|
return text.empty() ||
|
||||||
text.find_first_not_of(" \n\t\r") == std::string::npos;
|
text.find_first_not_of(" \n\t\r") == std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
||||||
@ -909,6 +908,32 @@ static inline void execute_job(std::shared_ptr<Job> j)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UseSurfaceData::ModelSources get_sources_to_cut_surface_from(
|
||||||
|
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;
|
||||||
|
// no other volume in object
|
||||||
|
if (volumes.size() <= 1) return {};
|
||||||
|
|
||||||
|
UseSurfaceData::ModelSources result;
|
||||||
|
// 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->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;
|
||||||
|
}
|
||||||
|
|
||||||
bool GLGizmoEmboss::process()
|
bool GLGizmoEmboss::process()
|
||||||
{
|
{
|
||||||
// no volume is selected -> selection from right panel
|
// no volume is selected -> selection from right panel
|
||||||
@ -940,8 +965,8 @@ bool GLGizmoEmboss::process()
|
|||||||
const TextConfiguration &tc = data.text_configuration;
|
const TextConfiguration &tc = data.text_configuration;
|
||||||
if (tc.font_item.prop.use_surface) {
|
if (tc.font_item.prop.use_surface) {
|
||||||
// Model to cut surface from.
|
// Model to cut surface from.
|
||||||
const ModelVolume *mesh = get_volume_to_cut_surface_from();
|
auto sources = get_sources_to_cut_surface_from(m_volume);
|
||||||
if (mesh == nullptr) return false;
|
if (sources.empty()) return false;
|
||||||
|
|
||||||
Transform3d text_tr = m_volume->get_matrix();
|
Transform3d text_tr = m_volume->get_matrix();
|
||||||
auto& fix_3mf = m_volume->text_configuration->fix_3mf_tr;
|
auto& fix_3mf = m_volume->text_configuration->fix_3mf_tr;
|
||||||
@ -952,12 +977,8 @@ bool GLGizmoEmboss::process()
|
|||||||
// check that there is not unexpected volume type
|
// check that there is not unexpected volume type
|
||||||
assert(is_outside || m_volume->is_negative_volume() ||
|
assert(is_outside || m_volume->is_negative_volume() ||
|
||||||
m_volume->is_modifier());
|
m_volume->is_modifier());
|
||||||
UseSurfaceData surface_data{std::move(data),
|
UseSurfaceData surface_data{std::move(data), text_tr, is_outside,
|
||||||
text_tr,
|
std::move(sources)};
|
||||||
is_outside,
|
|
||||||
mesh->mesh().its /*copy*/,
|
|
||||||
mesh->get_matrix(),
|
|
||||||
mesh->mesh().bounding_box()};
|
|
||||||
job = std::make_unique<UseSurfaceJob>(std::move(surface_data));
|
job = std::make_unique<UseSurfaceJob>(std::move(surface_data));
|
||||||
} else {
|
} else {
|
||||||
job = std::make_unique<EmbossUpdateJob>(std::move(data));
|
job = std::make_unique<EmbossUpdateJob>(std::move(data));
|
||||||
@ -1024,29 +1045,6 @@ void GLGizmoEmboss::select_stored_font_item()
|
|||||||
m_stored_wx_font = WxFontUtils::load_wxFont(m_stored_font_item->path);
|
m_stored_wx_font = WxFontUtils::load_wxFont(m_stored_font_item->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModelVolume * GLGizmoEmboss::get_volume_to_cut_surface_from()
|
|
||||||
{
|
|
||||||
if (m_volume == nullptr) return nullptr;
|
|
||||||
if (!m_volume->text_configuration.has_value()) return nullptr;
|
|
||||||
const auto &volumes = m_volume->get_object()->volumes;
|
|
||||||
// no other volume in object
|
|
||||||
if (volumes.size() <= 1) return nullptr;
|
|
||||||
|
|
||||||
// Improve create object from part or use gl_volume
|
|
||||||
// Get first model part in object
|
|
||||||
for (const ModelVolume *v : volumes) {
|
|
||||||
if (v->id() == m_volume->id()) continue;
|
|
||||||
if (!v->is_model_part()) continue;
|
|
||||||
const TriangleMesh &tm = v->mesh();
|
|
||||||
if (tm.empty()) continue;
|
|
||||||
if (tm.its.empty()) continue;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No valid source volume in objct volumes
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_window()
|
void GLGizmoEmboss::draw_window()
|
||||||
{
|
{
|
||||||
#ifdef ALLOW_DEBUG_MODE
|
#ifdef ALLOW_DEBUG_MODE
|
||||||
|
@ -116,12 +116,6 @@ private:
|
|||||||
void do_translate(const Vec3d& relative_move);
|
void do_translate(const Vec3d& relative_move);
|
||||||
void do_rotate(float relative_z_angle);
|
void do_rotate(float relative_z_angle);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Choose valid source Volume to project on(cut surface from).
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>ModelVolume to project on</returns>
|
|
||||||
const ModelVolume *get_volume_to_cut_surface_from();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reversible input float with option to restor default value
|
/// Reversible input float with option to restor default value
|
||||||
/// TODO: make more general, static and move to ImGuiWrapper
|
/// TODO: make more general, static and move to ImGuiWrapper
|
||||||
|
@ -22,20 +22,35 @@ using namespace GUI;
|
|||||||
|
|
||||||
// private namespace
|
// private namespace
|
||||||
namespace priv{
|
namespace priv{
|
||||||
// <summary>
|
/// <summary>
|
||||||
/// Create mesh from text
|
/// Assert check of inputs data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">Text to convert on mesh</param>
|
/// <param name="input"></param>
|
||||||
/// <param name="font">Define shape of characters.
|
/// <returns></returns>
|
||||||
/// NOTE: Can't be const cache glyphs</param>
|
bool check(const EmbossDataBase &input, bool check_fontfile = true);
|
||||||
/// <param name="font_prop">Property of font</param>
|
bool check(const EmbossDataCreateVolume &input, bool is_main_thread = false);
|
||||||
/// <param name="was_canceled">Lambda returning bool to check if process was canceled</param>
|
bool check(const EmbossDataCreateObject &input);
|
||||||
|
bool check(const EmbossDataUpdate &input, bool is_main_thread = false);
|
||||||
|
bool check(const UseSurfaceData &input, bool is_main_thread = false);
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
/// Try to create mesh from text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Text to convert on mesh
|
||||||
|
/// + Shape of characters + Property of font</param>
|
||||||
|
/// <param name="font">Font file with cache
|
||||||
|
/// NOTE: Cache glyphs is changed</param>
|
||||||
|
/// <param name="was_canceled">To check if process was canceled</param>
|
||||||
/// <returns>Triangle mesh model</returns>
|
/// <returns>Triangle mesh model</returns>
|
||||||
template<typename Fnc>
|
template<typename Fnc>
|
||||||
static TriangleMesh create_mesh(const char *text,
|
static TriangleMesh try_create_mesh(const EmbossDataBase &input,
|
||||||
Emboss::FontFileWithCache &font,
|
Emboss::FontFileWithCache &font,
|
||||||
const FontProp &font_prop,
|
Fnc was_canceled);
|
||||||
Fnc was_canceled);
|
template<typename Fnc>
|
||||||
|
static TriangleMesh create_mesh(EmbossDataBase &input,
|
||||||
|
Fnc was_canceled,
|
||||||
|
Job::Ctl &ctl);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create default mesh for embossed text
|
/// Create default mesh for embossed text
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -49,6 +64,14 @@ static TriangleMesh create_default_mesh();
|
|||||||
/// <param name="data">Text configuration, ...</param>
|
/// <param name="data">Text configuration, ...</param>
|
||||||
static void update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data);
|
static void update_volume(TriangleMesh &&mesh, const EmbossDataUpdate &data);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Select Volume from objects
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objects">All objects in scene</param>
|
||||||
|
/// <param name="volume_id">Identifier of volume in object</param>
|
||||||
|
/// <returns>Pointer to volume when exist otherwise nullptr</returns>
|
||||||
|
static ModelVolume *get_volume(ModelObjectPtrs &objects,
|
||||||
|
const ObjectID &volume_id);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// extract scale in 2d
|
/// extract scale in 2d
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,7 +88,7 @@ static double get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff);
|
|||||||
/// <param name="shape_bb">Bounding box 2d of shape to center result</param>
|
/// <param name="shape_bb">Bounding box 2d of shape to center result</param>
|
||||||
/// <param name="z_range">Bounding box 3d of model volume for projection ranges</param>
|
/// <param name="z_range">Bounding box 3d of model volume for projection ranges</param>
|
||||||
/// <returns>Orthogonal cut_projection</returns>
|
/// <returns>Orthogonal cut_projection</returns>
|
||||||
static std::unique_ptr<Emboss::IProjection> create_projection_for_cut(
|
static Emboss::OrthoProject create_projection_for_cut(
|
||||||
Transform3d tr,
|
Transform3d tr,
|
||||||
double shape_scale,
|
double shape_scale,
|
||||||
const BoundingBox &shape_bb,
|
const BoundingBox &shape_bb,
|
||||||
@ -79,28 +102,33 @@ static std::unique_ptr<Emboss::IProjection> create_projection_for_cut(
|
|||||||
/// <param name="tr">Text voliume transformation inside object</param>
|
/// <param name="tr">Text voliume transformation inside object</param>
|
||||||
/// <param name="cut">Cutted surface from model</param>
|
/// <param name="cut">Cutted surface from model</param>
|
||||||
/// <returns>Projection</returns>
|
/// <returns>Projection</returns>
|
||||||
static std::unique_ptr<Emboss::IProject3f> create_emboss_projection(
|
static Emboss::OrthoProject3f create_emboss_projection(
|
||||||
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut);
|
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut);
|
||||||
|
|
||||||
|
static void create_message(const std::string &message); // only in finalize
|
||||||
|
static bool process(std::exception_ptr &eptr);
|
||||||
|
|
||||||
|
class EmbossJobException: public std::exception {
|
||||||
|
public: EmbossJobException(char const *const message)
|
||||||
|
: std::exception(message)
|
||||||
|
{}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
/// Create Volume
|
/// Create Volume
|
||||||
EmbossCreateVolumeJob::EmbossCreateVolumeJob(EmbossDataCreateVolume &&input)
|
EmbossCreateVolumeJob::EmbossCreateVolumeJob(EmbossDataCreateVolume &&input)
|
||||||
: m_input(std::move(input))
|
: m_input(std::move(input))
|
||||||
{}
|
{
|
||||||
|
assert(priv::check(m_input, true));
|
||||||
|
}
|
||||||
|
|
||||||
void EmbossCreateVolumeJob::process(Ctl &ctl) {
|
void EmbossCreateVolumeJob::process(Ctl &ctl) {
|
||||||
// It is neccessary to create some shape
|
if (!priv::check(m_input)) throw std::runtime_error("Bad input data for EmbossCreateVolumeJob.");
|
||||||
// Emboss text window is opened by creation new emboss text object
|
|
||||||
const char *text = m_input.text_configuration.text.c_str();
|
|
||||||
FontProp &prop = m_input.text_configuration.font_item.prop;
|
|
||||||
auto was_canceled = [&ctl]()->bool { return ctl.was_canceled(); };
|
auto was_canceled = [&ctl]()->bool { return ctl.was_canceled(); };
|
||||||
m_result = priv::create_mesh(text, m_input.font_file, prop, was_canceled);
|
m_result = priv::create_mesh(m_input, was_canceled, ctl);
|
||||||
if (m_result.its.empty()) m_result = priv::create_default_mesh();
|
|
||||||
|
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
|
|
||||||
// Create new volume inside of object
|
// Create new volume inside of object
|
||||||
const FontProp &font_prop = m_input.text_configuration.font_item.prop;
|
const FontProp &font_prop = m_input.text_configuration.font_item.prop;
|
||||||
Transform3d surface_trmat = Emboss::create_transformation_onto_surface(
|
Transform3d surface_trmat = Emboss::create_transformation_onto_surface(
|
||||||
@ -110,25 +138,36 @@ void EmbossCreateVolumeJob::process(Ctl &ctl) {
|
|||||||
m_input.hit_object_tr * surface_trmat;
|
m_input.hit_object_tr * surface_trmat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &) {
|
void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &eptr) {
|
||||||
if (canceled) return;
|
// doesn't care about exception when process was canceled by user
|
||||||
|
if (canceled) {
|
||||||
|
eptr = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priv::process(eptr)) return;
|
||||||
|
if (m_result.its.empty())
|
||||||
|
return priv::create_message(_u8L("Can't create empty volume."));
|
||||||
|
|
||||||
GUI_App &app = wxGetApp();
|
GUI_App &app = wxGetApp();
|
||||||
Plater *plater = app.plater();
|
Plater *plater = app.plater();
|
||||||
ObjectList *obj_list = app.obj_list();
|
ObjectList *obj_list = app.obj_list();
|
||||||
GLCanvas3D *canvas = plater->canvas3D();
|
GLCanvas3D *canvas = plater->canvas3D();
|
||||||
Model &model = plater->model();
|
ModelObjectPtrs &objects = plater->model().objects;
|
||||||
|
|
||||||
// create volume in object
|
// create volume in object
|
||||||
size_t object_idx = m_input.object_idx;
|
size_t object_idx = m_input.object_idx;
|
||||||
assert(model.objects.size() > object_idx);
|
|
||||||
if (model.objects.size() <= object_idx) return;
|
// Parent object for text volume was propably removed.
|
||||||
|
// Assumption: User know what he does, so text volume is no more needed.
|
||||||
|
if (objects.size() <= object_idx)
|
||||||
|
return;
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(plater, _L("Add Emboss text Volume"));
|
Plater::TakeSnapshot snapshot(plater, _L("Add Emboss text Volume"));
|
||||||
|
|
||||||
ModelObject *obj = model.objects[object_idx];
|
ModelObject *obj = objects[object_idx];
|
||||||
ModelVolumeType type = m_input.volume_type;
|
ModelVolumeType type = m_input.volume_type;
|
||||||
ModelVolume *volume = obj->add_volume(std::move(m_result), type);
|
|
||||||
|
ModelVolume *volume = obj->add_volume(std::move(m_result), type);
|
||||||
|
|
||||||
// set a default extruder value, since user can't add it manually
|
// set a default extruder value, since user can't add it manually
|
||||||
volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||||
@ -149,7 +188,7 @@ void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &) {
|
|||||||
return vol == volume;
|
return vol == volume;
|
||||||
};
|
};
|
||||||
wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(
|
wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(
|
||||||
(int) object_idx, add_to_selection);
|
m_input.object_idx, add_to_selection);
|
||||||
if (!sel.IsEmpty()) obj_list->select_item(sel.front());
|
if (!sel.IsEmpty()) obj_list->select_item(sel.front());
|
||||||
|
|
||||||
// update printable state on canvas
|
// update printable state on canvas
|
||||||
@ -172,22 +211,17 @@ void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &) {
|
|||||||
/// Create Object
|
/// Create Object
|
||||||
EmbossCreateObjectJob::EmbossCreateObjectJob(EmbossDataCreateObject &&input)
|
EmbossCreateObjectJob::EmbossCreateObjectJob(EmbossDataCreateObject &&input)
|
||||||
: m_input(std::move(input))
|
: m_input(std::move(input))
|
||||||
{}
|
{
|
||||||
|
assert(priv::check(m_input));
|
||||||
|
}
|
||||||
|
|
||||||
void EmbossCreateObjectJob::process(Ctl &ctl)
|
void EmbossCreateObjectJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
// It is neccessary to create some shape
|
if (!priv::check(m_input))
|
||||||
// Emboss text window is opened by creation new emboss text object
|
throw std::runtime_error("Bad input data for EmbossCreateObjectJob.");
|
||||||
const char *text = m_input.text_configuration.text.c_str();
|
|
||||||
FontProp &prop = m_input.text_configuration.font_item.prop;
|
|
||||||
auto was_canceled = [&ctl]()->bool { return ctl.was_canceled(); };
|
|
||||||
if (!m_input.font_file.has_value())
|
|
||||||
m_result = priv::create_default_mesh();
|
|
||||||
else
|
|
||||||
m_result = priv::create_mesh(text, m_input.font_file, prop, was_canceled);
|
|
||||||
if (m_result.its.empty())
|
|
||||||
m_result = priv::create_default_mesh();
|
|
||||||
|
|
||||||
|
auto was_canceled = [&ctl]()->bool { return ctl.was_canceled(); };
|
||||||
|
m_result = priv::create_mesh(m_input, was_canceled, ctl);
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
|
|
||||||
// Create new object
|
// Create new object
|
||||||
@ -213,9 +247,18 @@ void EmbossCreateObjectJob::process(Ctl &ctl)
|
|||||||
m_transformation = Transform3d(tt);
|
m_transformation = Transform3d(tt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &)
|
void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
if (canceled) return;
|
// doesn't care about exception when process was canceled by user
|
||||||
|
if (canceled) {
|
||||||
|
eptr = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priv::process(eptr)) return;
|
||||||
|
|
||||||
|
// only for sure
|
||||||
|
if (m_result.empty())
|
||||||
|
return priv::create_message(_u8L("Can't create empty object."));
|
||||||
|
|
||||||
GUI_App &app = wxGetApp();
|
GUI_App &app = wxGetApp();
|
||||||
Plater *plater = app.plater();
|
Plater *plater = app.plater();
|
||||||
@ -246,36 +289,38 @@ void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &)
|
|||||||
EmbossUpdateJob::EmbossUpdateJob(EmbossDataUpdate&& input)
|
EmbossUpdateJob::EmbossUpdateJob(EmbossDataUpdate&& input)
|
||||||
: m_input(std::move(input))
|
: m_input(std::move(input))
|
||||||
{
|
{
|
||||||
assert(m_input.cancel != nullptr);
|
assert(priv::check(m_input, true));
|
||||||
assert(m_input.font_file.has_value());
|
|
||||||
assert(!m_input.text_configuration.text.empty());
|
|
||||||
assert(!m_input.text_configuration.fix_3mf_tr.has_value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmbossUpdateJob::process(Ctl &ctl)
|
void EmbossUpdateJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
|
if (!priv::check(m_input))
|
||||||
|
throw std::runtime_error("Bad input data for EmbossUpdateJob.");
|
||||||
|
|
||||||
auto was_canceled = [&ctl, &cancel = m_input.cancel]()->bool {
|
auto was_canceled = [&ctl, &cancel = m_input.cancel]()->bool {
|
||||||
if (cancel->load()) return true;
|
if (cancel->load()) return true;
|
||||||
return ctl.was_canceled();
|
return ctl.was_canceled();
|
||||||
};
|
};
|
||||||
|
m_result = priv::try_create_mesh(m_input, m_input.font_file, was_canceled);
|
||||||
// check if exist valid font
|
|
||||||
if (!m_input.font_file.has_value()) return;
|
|
||||||
|
|
||||||
const TextConfiguration &cfg = m_input.text_configuration;
|
|
||||||
m_result = priv::create_mesh(cfg.text.c_str(), m_input.font_file,
|
|
||||||
cfg.font_item.prop, was_canceled);
|
|
||||||
if (m_result.its.empty()) return;
|
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
|
if (m_result.its.empty())
|
||||||
|
throw priv::EmbossJobException(
|
||||||
|
_u8L("Created text volume is empty. Change text or "
|
||||||
|
"font.").c_str());
|
||||||
|
|
||||||
// center triangle mesh
|
// center triangle mesh
|
||||||
Vec3d shift = m_result.bounding_box().center();
|
Vec3d shift = m_result.bounding_box().center();
|
||||||
m_result.translate(-shift.cast<float>());
|
m_result.translate(-shift.cast<float>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &)
|
void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
if (canceled || m_input.cancel->load()) return;
|
// doesn't care about exception when process was canceled by user
|
||||||
|
if (canceled || m_input.cancel->load()) {
|
||||||
|
eptr = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priv::process(eptr)) return;
|
||||||
priv::update_volume(std::move(m_result), m_input);
|
priv::update_volume(std::move(m_result), m_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,12 +328,14 @@ void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &)
|
|||||||
/// Cut Surface
|
/// Cut Surface
|
||||||
UseSurfaceJob::UseSurfaceJob(UseSurfaceData &&input)
|
UseSurfaceJob::UseSurfaceJob(UseSurfaceData &&input)
|
||||||
: m_input(std::move(input))
|
: m_input(std::move(input))
|
||||||
{}
|
{
|
||||||
|
assert(priv::check(m_input, true));
|
||||||
|
}
|
||||||
|
|
||||||
void UseSurfaceJob::process(Ctl &ctl) {
|
void UseSurfaceJob::process(Ctl &ctl) {
|
||||||
// font face with glyph cache
|
if (!priv::check(m_input))
|
||||||
if (!m_input.font_file.has_value()) return;
|
throw std::runtime_error("Bad input data for UseSurfaceJob.");
|
||||||
|
|
||||||
// check cancelation of process
|
// check cancelation of process
|
||||||
auto was_canceled = [&ctl, &cancel = m_input.cancel]()->bool {
|
auto was_canceled = [&ctl, &cancel = m_input.cancel]()->bool {
|
||||||
if (cancel->load()) return true;
|
if (cancel->load()) return true;
|
||||||
@ -299,73 +346,169 @@ void UseSurfaceJob::process(Ctl &ctl) {
|
|||||||
const char *text = tc.text.c_str();
|
const char *text = tc.text.c_str();
|
||||||
const FontProp &fp = tc.font_item.prop;
|
const FontProp &fp = tc.font_item.prop;
|
||||||
ExPolygons shapes = Emboss::text2shapes(m_input.font_file, text, fp);
|
ExPolygons shapes = Emboss::text2shapes(m_input.font_file, text, fp);
|
||||||
if (shapes.empty()) return;
|
if (shapes.empty() || shapes.front().contour.empty())
|
||||||
if (shapes.front().contour.empty()) return;
|
throw priv::EmbossJobException(
|
||||||
|
_u8L("Font doesn't have any shape for given text.").c_str());
|
||||||
|
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
|
|
||||||
BoundingBox bb = get_extents(shapes);
|
BoundingBox bb = get_extents(shapes);
|
||||||
|
// TODO: merge input sources somehow
|
||||||
|
const UseSurfaceData::ModelSource &source = m_input.sources[0];
|
||||||
|
|
||||||
Transform3d mesh_tr_inv = m_input.mesh_tr.inverse();
|
Transform3d mesh_tr_inv = source.tr.inverse();
|
||||||
Transform3d cut_projection_tr = mesh_tr_inv * m_input.text_tr;
|
Transform3d cut_projection_tr = mesh_tr_inv * m_input.text_tr;
|
||||||
Transform3d emboss_tr = cut_projection_tr.inverse();
|
Transform3d emboss_tr = cut_projection_tr.inverse();
|
||||||
BoundingBoxf3 mesh_bb_tr = m_input.mesh_bb.transformed(emboss_tr);
|
BoundingBoxf3 mesh_bb_tr = source.bb.transformed(emboss_tr);
|
||||||
std::pair<float, float> z_range{mesh_bb_tr.min.z(), mesh_bb_tr.max.z()};
|
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;
|
const Emboss::FontFile &ff = *m_input.font_file.font_file;
|
||||||
double shape_scale = priv::get_shape_scale(fp, ff);
|
double shape_scale = priv::get_shape_scale(fp, ff);
|
||||||
auto cut_projection = priv::create_projection_for_cut(cut_projection_tr,
|
Emboss::OrthoProject cut_projection = priv::create_projection_for_cut(
|
||||||
shape_scale, bb,
|
cut_projection_tr, shape_scale, bb, z_range);
|
||||||
z_range);
|
|
||||||
if (cut_projection == nullptr) return;
|
|
||||||
|
|
||||||
// Use CGAL to cut surface from triangle mesh
|
// Use CGAL to cut surface from triangle mesh
|
||||||
SurfaceCut cut = cut_surface(m_input.mesh_its, shapes, *cut_projection);
|
SurfaceCut cut = cut_surface(source.its, shapes, cut_projection);
|
||||||
if (cut.empty()) return;
|
if (cut.empty())
|
||||||
|
throw priv::EmbossJobException(
|
||||||
|
_u8L("There is no valid surface for text projection.").c_str());
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
|
|
||||||
// !! Projection needs to transform cut
|
// !! Projection needs to transform cut
|
||||||
auto projection = priv::create_emboss_projection(m_input.is_outside, fp.emboss, emboss_tr, cut);
|
Emboss::OrthoProject3f projection = priv::create_emboss_projection(
|
||||||
if (projection == nullptr) return;
|
m_input.is_outside, fp.emboss, emboss_tr, cut);
|
||||||
|
|
||||||
|
indexed_triangle_set new_its = cut2model(cut, projection);
|
||||||
|
assert(!new_its.empty());
|
||||||
|
|
||||||
indexed_triangle_set new_its = cut2model(cut, *projection);
|
|
||||||
if (was_canceled()) return;
|
if (was_canceled()) return;
|
||||||
//its_write_obj(new_its, "C:/data/temp/projected.obj"); // only debug
|
//its_write_obj(new_its, "C:/data/temp/projected.obj"); // only debug
|
||||||
m_result = TriangleMesh(std::move(new_its));
|
m_result = TriangleMesh(std::move(new_its));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UseSurfaceJob::finalize(bool canceled, std::exception_ptr &)
|
void UseSurfaceJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
if (canceled || m_input.cancel->load()) return;
|
// doesn't care about exception when process was canceled by user
|
||||||
|
if (canceled || m_input.cancel->load()) {
|
||||||
|
eptr = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priv::process(eptr)) return;
|
||||||
priv::update_volume(std::move(m_result), m_input);
|
priv::update_volume(std::move(m_result), m_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
/// private namespace implementation
|
/// private namespace implementation
|
||||||
|
bool priv::check(const EmbossDataBase &input, bool check_fontfile){
|
||||||
|
bool res = true;
|
||||||
|
if (check_fontfile) {
|
||||||
|
assert(input.font_file.has_value());
|
||||||
|
res &= input.font_file.has_value();
|
||||||
|
}
|
||||||
|
assert(!input.text_configuration.fix_3mf_tr.has_value());
|
||||||
|
res &= !input.text_configuration.fix_3mf_tr.has_value();
|
||||||
|
assert(!input.text_configuration.text.empty());
|
||||||
|
res &= !input.text_configuration.text.empty();
|
||||||
|
assert(!input.volume_name.empty());
|
||||||
|
res &= !input.volume_name.empty();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool priv::check(const EmbossDataCreateVolume &input, bool is_main_thread) {
|
||||||
|
bool check_fontfile = false;
|
||||||
|
bool res = check((EmbossDataBase) input, check_fontfile);
|
||||||
|
assert(input.volume_type != ModelVolumeType::INVALID);
|
||||||
|
res &= input.volume_type != ModelVolumeType::INVALID;
|
||||||
|
assert(input.object_idx >= 0);
|
||||||
|
res &= input.object_idx >= 0;
|
||||||
|
if (is_main_thread)
|
||||||
|
assert(input.object_idx < wxGetApp().model().objects.size());
|
||||||
|
assert(input.screen_coor.x() >= 0.);
|
||||||
|
res &= input.screen_coor.x() >= 0.;
|
||||||
|
assert(input.screen_coor.y() >= 0.);
|
||||||
|
res &= input.screen_coor.y() >= 0.;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool priv::check(const EmbossDataCreateObject &input) {
|
||||||
|
bool check_fontfile = false;
|
||||||
|
bool res = check((EmbossDataBase) input, check_fontfile);
|
||||||
|
assert(input.screen_coor.x() >= 0.);
|
||||||
|
res &= input.screen_coor.x() >= 0.;
|
||||||
|
assert(input.screen_coor.y() >= 0.);
|
||||||
|
res &= input.screen_coor.y() >= 0.;
|
||||||
|
assert(input.bed_shape.size() >= 3); // at least triangle
|
||||||
|
res &= input.bed_shape.size() >= 3;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool priv::check(const EmbossDataUpdate &input, bool is_main_thread){
|
||||||
|
bool res = check((EmbossDataBase) input);
|
||||||
|
assert(input.volume_id.id >= 0);
|
||||||
|
res &= input.volume_id.id >= 0;
|
||||||
|
if (is_main_thread)
|
||||||
|
assert(get_volume(wxGetApp().model().objects, input.volume_id) != nullptr);
|
||||||
|
assert(input.cancel != nullptr);
|
||||||
|
res &= input.cancel != nullptr;
|
||||||
|
if (is_main_thread)
|
||||||
|
assert(!input.cancel->load());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Fnc>
|
template<typename Fnc>
|
||||||
TriangleMesh priv::create_mesh(const char *text,
|
TriangleMesh priv::try_create_mesh(const EmbossDataBase &input, Emboss::FontFileWithCache &font, Fnc was_canceled)
|
||||||
Emboss::FontFileWithCache &font,
|
|
||||||
const FontProp &font_prop,
|
|
||||||
Fnc was_canceled)
|
|
||||||
{
|
{
|
||||||
|
const TextConfiguration &tc = input.text_configuration;
|
||||||
|
const char *text = tc.text.c_str();
|
||||||
|
const FontProp &prop = tc.font_item.prop;
|
||||||
|
|
||||||
assert(font.has_value());
|
assert(font.has_value());
|
||||||
if (!font.has_value()) return {};
|
if (!font.has_value()) return {};
|
||||||
|
|
||||||
ExPolygons shapes = Emboss::text2shapes(font, text, font_prop);
|
ExPolygons shapes = Emboss::text2shapes(font, text, prop);
|
||||||
if (shapes.empty()) return {};
|
if (shapes.empty()) return {};
|
||||||
if (was_canceled()) return {};
|
if (was_canceled()) return {};
|
||||||
|
|
||||||
const auto &cn = font_prop.collection_number;
|
const auto &cn = prop.collection_number;
|
||||||
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
||||||
assert(font_index < font.font_file->infos.size());
|
assert(font_index < font.font_file->infos.size());
|
||||||
int unit_per_em = font.font_file->infos[font_index].unit_per_em;
|
int unit_per_em = font.font_file->infos[font_index].unit_per_em;
|
||||||
float scale = font_prop.size_in_mm / unit_per_em;
|
float scale = prop.size_in_mm / unit_per_em;
|
||||||
float depth = font_prop.emboss / scale;
|
float depth = prop.emboss / scale;
|
||||||
auto projectZ = std::make_unique<Emboss::ProjectZ>(depth);
|
auto projectZ = std::make_unique<Emboss::ProjectZ>(depth);
|
||||||
Emboss::ProjectScale project(std::move(projectZ), scale);
|
Emboss::ProjectScale project(std::move(projectZ), scale);
|
||||||
if (was_canceled()) return {};
|
if (was_canceled()) return {};
|
||||||
return TriangleMesh(Emboss::polygons2model(shapes, project));
|
return TriangleMesh(Emboss::polygons2model(shapes, project));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Fnc>
|
||||||
|
TriangleMesh priv::create_mesh(EmbossDataBase &input, Fnc was_canceled, Job::Ctl& ctl)
|
||||||
|
{
|
||||||
|
// It is neccessary to create some shape
|
||||||
|
// Emboss text window is opened by creation new emboss text object
|
||||||
|
TriangleMesh result;
|
||||||
|
if (input.font_file.has_value()) {
|
||||||
|
result = try_create_mesh(input, input.font_file, was_canceled);
|
||||||
|
if (was_canceled()) return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.its.empty()) {
|
||||||
|
result = priv::create_default_mesh();
|
||||||
|
if (was_canceled()) return {};
|
||||||
|
// only info
|
||||||
|
ctl.call_on_main_thread([]() {
|
||||||
|
create_message(_u8L("It is used default volume for embossed "
|
||||||
|
"text, try to change text or font for fix it."));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!result.its.empty());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
TriangleMesh priv::create_default_mesh()
|
TriangleMesh priv::create_default_mesh()
|
||||||
{
|
{
|
||||||
// When cant load any font use default object loaded from file
|
// When cant load any font use default object loaded from file
|
||||||
@ -382,7 +525,8 @@ void priv::update_volume(TriangleMesh &&mesh,
|
|||||||
const EmbossDataUpdate &data)
|
const EmbossDataUpdate &data)
|
||||||
{
|
{
|
||||||
// for sure that some object will be created
|
// for sure that some object will be created
|
||||||
if (mesh.its.empty()) return;
|
if (mesh.its.empty())
|
||||||
|
return priv::create_message("Empty mesh can't be created.");
|
||||||
|
|
||||||
GUI_App & app = wxGetApp(); // may be move to input
|
GUI_App & app = wxGetApp(); // may be move to input
|
||||||
Plater * plater = app.plater();
|
Plater * plater = app.plater();
|
||||||
@ -394,14 +538,7 @@ void priv::update_volume(TriangleMesh &&mesh,
|
|||||||
|
|
||||||
std::string snap_name = GUI::format(_L("Text: %1%"), data.text_configuration.text);
|
std::string snap_name = GUI::format(_L("Text: %1%"), data.text_configuration.text);
|
||||||
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
Plater::TakeSnapshot snapshot(plater, snap_name, UndoRedo::SnapshotType::GizmoAction);
|
||||||
|
ModelVolume *volume = get_volume(plater->model().objects, data.volume_id);
|
||||||
auto get_volume = [&model = plater->model()](const ObjectID &volume_id)->ModelVolume *{
|
|
||||||
for (ModelObject* obj : model.objects)
|
|
||||||
for (ModelVolume* vol : obj->volumes)
|
|
||||||
if (vol->id() == volume_id) return vol;
|
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
ModelVolume *volume = get_volume(data.volume_id);
|
|
||||||
// could appear when user delete edited volume
|
// could appear when user delete edited volume
|
||||||
if (volume == nullptr)
|
if (volume == nullptr)
|
||||||
return;
|
return;
|
||||||
@ -446,7 +583,17 @@ void priv::update_volume(TriangleMesh &&mesh,
|
|||||||
canvas->reload_scene(refresh_immediately);
|
canvas->reload_scene(refresh_immediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double priv::get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff)
|
ModelVolume *priv::get_volume(ModelObjectPtrs &objects,
|
||||||
|
const ObjectID &volume_id)
|
||||||
|
{
|
||||||
|
for (ModelObject *obj : objects)
|
||||||
|
for (ModelVolume *vol : obj->volumes)
|
||||||
|
if (vol->id() == volume_id) return vol;
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
double priv::get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff)
|
||||||
{
|
{
|
||||||
const auto &cn = fp.collection_number;
|
const auto &cn = fp.collection_number;
|
||||||
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
unsigned int font_index = (cn.has_value()) ? *cn : 0;
|
||||||
@ -456,7 +603,7 @@ static double priv::get_shape_scale(const FontProp &fp, const Emboss::FontFile &
|
|||||||
return scale * Emboss::SHAPE_SCALE;
|
return scale * Emboss::SHAPE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Emboss::IProjection> priv::create_projection_for_cut(
|
Emboss::OrthoProject priv::create_projection_for_cut(
|
||||||
Transform3d tr,
|
Transform3d tr,
|
||||||
double shape_scale,
|
double shape_scale,
|
||||||
const BoundingBox &shape_bb,
|
const BoundingBox &shape_bb,
|
||||||
@ -487,10 +634,10 @@ std::unique_ptr<Emboss::IProjection> priv::create_projection_for_cut(
|
|||||||
Vec2d move = -(shape_bb.max + shape_bb.min).cast<double>() / 2.;
|
Vec2d move = -(shape_bb.max + shape_bb.min).cast<double>() / 2.;
|
||||||
//Vec2d move = -shape_bb.center().cast<double>(); // not precisse
|
//Vec2d move = -shape_bb.center().cast<double>(); // not precisse
|
||||||
tr.translate(Vec3d(move.x(), move.y(), 0.));
|
tr.translate(Vec3d(move.x(), move.y(), 0.));
|
||||||
return std::make_unique<Emboss::OrthoProject>(tr, project_direction);
|
return Emboss::OrthoProject(tr, project_direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Emboss::IProject3f> priv::create_emboss_projection(
|
Emboss::OrthoProject3f priv::create_emboss_projection(
|
||||||
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
|
bool is_outside, float emboss, Transform3d tr, SurfaceCut &cut)
|
||||||
{
|
{
|
||||||
// Offset of clossed side to model
|
// Offset of clossed side to model
|
||||||
@ -500,5 +647,23 @@ std::unique_ptr<Emboss::IProject3f> priv::create_emboss_projection(
|
|||||||
back_move = -((is_outside) ? surface_offset : emboss);
|
back_move = -((is_outside) ? surface_offset : emboss);
|
||||||
its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move)));
|
its_transform(cut, tr.pretranslate(Vec3d(0., 0., front_move)));
|
||||||
Vec3f from_front_to_back(0.f, 0.f, back_move - front_move);
|
Vec3f from_front_to_back(0.f, 0.f, back_move - front_move);
|
||||||
return std::make_unique<Emboss::OrthoProject3f>(from_front_to_back);
|
return Emboss::OrthoProject3f(from_front_to_back);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool priv::process(std::exception_ptr &eptr) {
|
||||||
|
if (!eptr) return false;
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(eptr);
|
||||||
|
} catch (priv::EmbossJobException &e) {
|
||||||
|
create_message(e.what());
|
||||||
|
eptr = nullptr;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
|
void priv::create_message(const std::string &message) {
|
||||||
|
wxMessageBox(wxString(message), _L("Issue during embossing the text."),
|
||||||
|
wxOK | wxICON_WARNING);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ struct EmbossDataBase
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hold neccessary data to create ModelVolume in job
|
/// Hold neccessary data to create ModelVolume in job
|
||||||
/// Volume is created on the surface of existing volume in object.
|
/// Volume is created on the surface of existing volume in object.
|
||||||
|
/// NOTE: EmbossDataBase::font_file doesn't have to be valid !!!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct EmbossDataCreateVolume : public EmbossDataBase
|
struct EmbossDataCreateVolume : public EmbossDataBase
|
||||||
{
|
{
|
||||||
@ -57,6 +58,7 @@ struct EmbossDataCreateVolume : public EmbossDataBase
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create new TextVolume on the surface of ModelObject
|
/// Create new TextVolume on the surface of ModelObject
|
||||||
/// Should not be stopped
|
/// Should not be stopped
|
||||||
|
/// NOTE: EmbossDataBase::font_file doesn't have to be valid !!!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class EmbossCreateVolumeJob : public Job
|
class EmbossCreateVolumeJob : public Job
|
||||||
{
|
{
|
||||||
@ -67,7 +69,7 @@ class EmbossCreateVolumeJob : public Job
|
|||||||
public:
|
public:
|
||||||
EmbossCreateVolumeJob(EmbossDataCreateVolume&& input);
|
EmbossCreateVolumeJob(EmbossDataCreateVolume&& input);
|
||||||
void process(Ctl &ctl) override;
|
void process(Ctl &ctl) override;
|
||||||
void finalize(bool canceled, std::exception_ptr &) override;
|
void finalize(bool canceled, std::exception_ptr &eptr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -99,7 +101,7 @@ class EmbossCreateObjectJob : public Job
|
|||||||
public:
|
public:
|
||||||
EmbossCreateObjectJob(EmbossDataCreateObject&& input);
|
EmbossCreateObjectJob(EmbossDataCreateObject&& input);
|
||||||
void process(Ctl &ctl) override;
|
void process(Ctl &ctl) override;
|
||||||
void finalize(bool canceled, std::exception_ptr &) override;
|
void finalize(bool canceled, std::exception_ptr &eptr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -141,7 +143,7 @@ public:
|
|||||||
/// NOTE: Be carefull it doesn't care about
|
/// NOTE: Be carefull it doesn't care about
|
||||||
/// time between finished process and started finalize part.</param>
|
/// time between finished process and started finalize part.</param>
|
||||||
/// <param name="">unused</param>
|
/// <param name="">unused</param>
|
||||||
void finalize(bool canceled, std::exception_ptr &) override;
|
void finalize(bool canceled, std::exception_ptr &eptr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -157,13 +159,28 @@ struct UseSurfaceData : public EmbossDataUpdate
|
|||||||
// False (engraved).. move into object
|
// False (engraved).. move into object
|
||||||
bool is_outside;
|
bool is_outside;
|
||||||
|
|
||||||
// IMPROVE: copy of source mesh tringles
|
struct ModelSource
|
||||||
// copy could slow down on big meshes
|
{
|
||||||
indexed_triangle_set mesh_its;
|
// IMPROVE: copy of source mesh tringles
|
||||||
// Transformation of volume inside of object
|
// copy could slow down on big meshes
|
||||||
Transform3d mesh_tr;
|
// but proccessing on thread need it
|
||||||
// extract bounds for projection
|
indexed_triangle_set its;
|
||||||
BoundingBoxf3 mesh_bb;
|
// Transformation of volume inside of object
|
||||||
|
Transform3d tr;
|
||||||
|
// extract bounds for projection
|
||||||
|
BoundingBoxf3 bb;
|
||||||
|
};
|
||||||
|
using ModelSources = std::vector<ModelSource>;
|
||||||
|
ModelSources sources;
|
||||||
|
|
||||||
|
//// IMPROVE: copy of source mesh tringles
|
||||||
|
//// copy could slow down on big meshes
|
||||||
|
//// but proccess on thread need it
|
||||||
|
//indexed_triangle_set object_volumes;
|
||||||
|
//// Transformation of volume inside of object
|
||||||
|
//Transform3d mesh_tr;
|
||||||
|
//// extract bounds for projection
|
||||||
|
//BoundingBoxf3 mesh_bb;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -178,7 +195,7 @@ public:
|
|||||||
// move params to private variable
|
// move params to private variable
|
||||||
UseSurfaceJob(UseSurfaceData &&input);
|
UseSurfaceJob(UseSurfaceData &&input);
|
||||||
void process(Ctl &ctl) override;
|
void process(Ctl &ctl) override;
|
||||||
void finalize(bool canceled, std::exception_ptr &) override;
|
void finalize(bool canceled, std::exception_ptr &eptr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::GUI
|
} // namespace Slic3r::GUI
|
||||||
|
Loading…
Reference in New Issue
Block a user