Initial shape for emboss is not cached any more
This commit is contained in:
parent
0a3fc00851
commit
5869f86d97
@ -642,3 +642,54 @@ std::pair<Vec3f, Vec3f> Emboss::ProjectZ::project(const Point &p) const
|
|||||||
back.z() = m_depth;
|
back.z() = m_depth;
|
||||||
return std::make_pair(front, back);
|
return std::make_pair(front, back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position,
|
||||||
|
const Vec3f &normal,
|
||||||
|
float up_limit)
|
||||||
|
{
|
||||||
|
// up and emboss direction for generated model
|
||||||
|
Vec3d text_up_dir = Vec3d::UnitY();
|
||||||
|
Vec3d text_emboss_dir = Vec3d::UnitZ();
|
||||||
|
|
||||||
|
// wanted up direction of result
|
||||||
|
Vec3d wanted_up_side = Vec3d::UnitZ();
|
||||||
|
if (std::fabs(normal.z()) > up_limit) wanted_up_side = Vec3d::UnitY();
|
||||||
|
|
||||||
|
Vec3d wanted_emboss_dir = normal.cast<double>();
|
||||||
|
// after cast from float it needs to be normalized again
|
||||||
|
wanted_emboss_dir.normalize();
|
||||||
|
|
||||||
|
// create perpendicular unit vector to surface triangle normal vector
|
||||||
|
// lay on surface of triangle and define up vector for text
|
||||||
|
Vec3d wanted_up_dir = wanted_emboss_dir
|
||||||
|
.cross(wanted_up_side)
|
||||||
|
.cross(wanted_emboss_dir);
|
||||||
|
// normal3d is NOT perpendicular to normal_up_dir
|
||||||
|
wanted_up_dir.normalize();
|
||||||
|
|
||||||
|
// perpendicular to emboss vector of text and normal
|
||||||
|
Vec3d axis_view = text_emboss_dir.cross(wanted_emboss_dir);
|
||||||
|
double angle_view = std::acos(text_emboss_dir.dot(wanted_emboss_dir)); // in rad
|
||||||
|
axis_view.normalize();
|
||||||
|
|
||||||
|
Eigen::AngleAxis view_rot(angle_view, axis_view);
|
||||||
|
Vec3d wanterd_up_rotated = view_rot.matrix().inverse() * wanted_up_dir;
|
||||||
|
wanterd_up_rotated.normalize();
|
||||||
|
double angle_up = std::acos(text_up_dir.dot(wanterd_up_rotated));
|
||||||
|
|
||||||
|
// text_view and text_view2 should have same direction
|
||||||
|
Vec3d text_view2 = text_up_dir.cross(wanterd_up_rotated);
|
||||||
|
Vec3d diff_view = text_emboss_dir - text_view2;
|
||||||
|
if (std::fabs(diff_view.x()) > 1. ||
|
||||||
|
std::fabs(diff_view.y()) > 1. ||
|
||||||
|
std::fabs(diff_view.z()) > 1.) // oposit direction
|
||||||
|
angle_up *= -1.;
|
||||||
|
|
||||||
|
Eigen::AngleAxis up_rot(angle_up, text_emboss_dir);
|
||||||
|
|
||||||
|
Transform3d transform = Transform3d::Identity();
|
||||||
|
transform.translate(position.cast<double>());
|
||||||
|
transform.rotate(view_rot);
|
||||||
|
transform.rotate(up_rot);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
@ -129,6 +129,16 @@ public:
|
|||||||
/// <returns>Projected shape into space</returns>
|
/// <returns>Projected shape into space</returns>
|
||||||
static indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProject& projection);
|
static indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProject& projection);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create transformation for emboss text object to lay on surface point
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of surface point</param>
|
||||||
|
/// <param name="normal">Normal of surface point</param>
|
||||||
|
/// <param name="up_limit">Is compared with normal.z to suggest up direction</param>
|
||||||
|
/// <returns>Transformation onto surface point</returns>
|
||||||
|
static Transform3d create_transformation_onto_surface(
|
||||||
|
const Vec3f &position, const Vec3f &normal, float up_limit = 0.9f);
|
||||||
|
|
||||||
class ProjectZ : public IProject
|
class ProjectZ : public IProject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -110,16 +110,19 @@ static void draw_fine_position(const Selection &selection)
|
|||||||
|
|
||||||
void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
|
void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
|
||||||
{
|
{
|
||||||
|
assert(volume_type == ModelVolumeType::MODEL_PART ||
|
||||||
|
volume_type == ModelVolumeType::NEGATIVE_VOLUME ||
|
||||||
|
volume_type == ModelVolumeType::PARAMETER_MODIFIER);
|
||||||
|
|
||||||
if (!m_is_initialized) initialize();
|
if (!m_is_initialized) initialize();
|
||||||
const Selection &selection = m_parent.get_selection();
|
const Selection &selection = m_parent.get_selection();
|
||||||
if(selection.is_empty()) return;
|
if(selection.is_empty()) return;
|
||||||
|
|
||||||
set_default_configuration();
|
set_default_configuration();
|
||||||
TriangleMesh tm = m_default_mesh; // copy
|
|
||||||
|
|
||||||
// By position of cursor create transformation to put text on surface of model
|
// By position of cursor create transformation to put text on surface of model
|
||||||
Transform3d transformation = Transform3d::Identity();
|
Transform3d transformation = Transform3d::Identity();
|
||||||
|
// TODO: calculate X,Y offset position for lay on platter by mouse position
|
||||||
|
|
||||||
CommonGizmosDataObjects::Raycaster *raycaster = m_c->raycaster();
|
CommonGizmosDataObjects::Raycaster *raycaster = m_c->raycaster();
|
||||||
if (raycaster == nullptr) return;
|
if (raycaster == nullptr) return;
|
||||||
@ -143,7 +146,7 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous
|
|||||||
std::optional<Transform3d> tr = transform_on_surface(mouse_pos, raycasters, raycasters_tr);
|
std::optional<Transform3d> tr = transform_on_surface(mouse_pos, raycasters, raycasters_tr);
|
||||||
if (tr.has_value()) transformation = *tr;
|
if (tr.has_value()) transformation = *tr;
|
||||||
|
|
||||||
create_emboss_volume(std::move(tm), transformation, create_volume_name(),
|
create_emboss_volume(create_mesh(), transformation, create_volume_name(),
|
||||||
create_configuration(), volume_type,
|
create_configuration(), volume_type,
|
||||||
selection.get_object_idx());
|
selection.get_object_idx());
|
||||||
}
|
}
|
||||||
@ -211,7 +214,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key);
|
Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key);
|
||||||
Transform3d trmat = get_emboss_transformation(hit->position, hit->normal);
|
Transform3d trmat = Emboss::create_transformation_onto_surface(hit->position, hit->normal);
|
||||||
if (mouse_event.Dragging()) {
|
if (mouse_event.Dragging()) {
|
||||||
// hide common dragging of object
|
// hide common dragging of object
|
||||||
m_parent.toggle_model_objects_visibility(false, m_volume->get_object(), gl_volume->instance_idx(), m_volume);
|
m_parent.toggle_model_objects_visibility(false, m_volume->get_object(), gl_volume->instance_idx(), m_volume);
|
||||||
@ -367,8 +370,7 @@ void GLGizmoEmboss::on_set_state()
|
|||||||
// When add Text on empty plate, Create new object with volume
|
// When add Text on empty plate, Create new object with volume
|
||||||
if (create_new_object) {
|
if (create_new_object) {
|
||||||
set_default_configuration();
|
set_default_configuration();
|
||||||
TriangleMesh tm = m_default_mesh; // copy
|
create_emboss_object(create_mesh(), create_volume_name(), create_configuration());
|
||||||
create_emboss_object(std::move(tm), create_volume_name(), create_configuration());
|
|
||||||
|
|
||||||
// gizmo will open when successfuly create new object
|
// gizmo will open when successfuly create new object
|
||||||
GLGizmoBase::m_state = GLGizmoBase::Off;
|
GLGizmoBase::m_state = GLGizmoBase::Off;
|
||||||
@ -449,7 +451,6 @@ void GLGizmoEmboss::initialize()
|
|||||||
assert(success);
|
assert(success);
|
||||||
load_font_list();
|
load_font_list();
|
||||||
|
|
||||||
|
|
||||||
// try to load valid font
|
// try to load valid font
|
||||||
m_font_selected = 0;
|
m_font_selected = 0;
|
||||||
bool is_font_loaded = load_font();
|
bool is_font_loaded = load_font();
|
||||||
@ -458,28 +459,7 @@ void GLGizmoEmboss::initialize()
|
|||||||
m_font_list.erase(m_font_list.begin());
|
m_font_list.erase(m_font_list.begin());
|
||||||
is_font_loaded = load_font();
|
is_font_loaded = load_font();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_default_configuration();
|
set_default_configuration();
|
||||||
|
|
||||||
// create default mesh to faster add new volume
|
|
||||||
// solve state when no font loaded
|
|
||||||
if (is_font_loaded) {
|
|
||||||
// create default
|
|
||||||
ExPolygons shapes = Emboss::text2shapes(*m_font, m_text.c_str(), m_font_prop);
|
|
||||||
float scale = m_font_prop.size_in_mm / m_font->ascent;
|
|
||||||
float depth = m_font_prop.emboss / scale;
|
|
||||||
auto projectZ = std::make_unique<Emboss::ProjectZ>(depth);
|
|
||||||
Emboss::ProjectScale project(std::move(projectZ), scale);
|
|
||||||
m_default_mesh = TriangleMesh(Emboss::polygons2model(shapes, project));
|
|
||||||
} else {
|
|
||||||
// When cant load any font use default object loaded from file
|
|
||||||
std::string path = Slic3r::resources_dir() +
|
|
||||||
"/data/embossed_text.stl";
|
|
||||||
if (!load_obj(path.c_str(), &m_default_mesh)) {
|
|
||||||
// when can't load mesh use cube
|
|
||||||
m_default_mesh = TriangleMesh(its_make_cube(36., 4., 2.5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FontList GLGizmoEmboss::create_default_font_list() {
|
FontList GLGizmoEmboss::create_default_font_list() {
|
||||||
@ -497,6 +477,41 @@ void GLGizmoEmboss::set_default_configuration()
|
|||||||
load_font(); // reload actual font - because of font size
|
load_font(); // reload actual font - because of font size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slic3r::TriangleMesh GLGizmoEmboss::create_default_mesh()
|
||||||
|
{
|
||||||
|
// When cant load any font use default object loaded from file
|
||||||
|
std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl";
|
||||||
|
TriangleMesh triangle_mesh;
|
||||||
|
if (!load_obj(path.c_str(), &triangle_mesh)) {
|
||||||
|
// when can't load mesh use cube
|
||||||
|
return TriangleMesh(its_make_cube(36., 4., 2.5));
|
||||||
|
}
|
||||||
|
return triangle_mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slic3r::TriangleMesh GLGizmoEmboss::create_mesh()
|
||||||
|
{
|
||||||
|
// It is neccessary to create some shape
|
||||||
|
// Emboss text window is opened by creation new embosstext object
|
||||||
|
if (m_font == nullptr) return create_default_mesh();
|
||||||
|
|
||||||
|
TriangleMesh result = create_mesh(m_text.c_str(), *m_font, m_font_prop);
|
||||||
|
if (result.its.empty()) return create_default_mesh();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slic3r::TriangleMesh GLGizmoEmboss::create_mesh(const char * text,
|
||||||
|
Emboss::Font &font,
|
||||||
|
const FontProp& font_prop)
|
||||||
|
{
|
||||||
|
ExPolygons shapes = Emboss::text2shapes(font, text, font_prop);
|
||||||
|
float scale = font_prop.size_in_mm / font.ascent;
|
||||||
|
float depth = font_prop.emboss / scale;
|
||||||
|
auto projectZ = std::make_unique<Emboss::ProjectZ>(depth);
|
||||||
|
Emboss::ProjectScale project(std::move(projectZ), scale);
|
||||||
|
return TriangleMesh(Emboss::polygons2model(shapes, project));
|
||||||
|
}
|
||||||
|
|
||||||
#include "imgui/imgui_internal.h" // to unfocus input --> ClearActiveID
|
#include "imgui/imgui_internal.h" // to unfocus input --> ClearActiveID
|
||||||
void GLGizmoEmboss::check_selection()
|
void GLGizmoEmboss::check_selection()
|
||||||
{
|
{
|
||||||
@ -618,9 +633,8 @@ void GLGizmoEmboss::draw_window()
|
|||||||
if (ImGui::Button(_u8L("Generate preview").c_str())) {
|
if (ImGui::Button(_u8L("Generate preview").c_str())) {
|
||||||
const Selection &s = m_parent.get_selection();
|
const Selection &s = m_parent.get_selection();
|
||||||
auto selected_indices = s.get_instance_idxs();
|
auto selected_indices = s.get_instance_idxs();
|
||||||
TriangleMesh mesh = m_default_mesh; // copy
|
|
||||||
if (selected_indices.empty()) {
|
if (selected_indices.empty()) {
|
||||||
create_emboss_object(std::move(mesh), create_volume_name(), create_configuration());
|
create_emboss_object(create_mesh(), create_volume_name(), create_configuration());
|
||||||
} else {
|
} else {
|
||||||
create_volume(ModelVolumeType::MODEL_PART);
|
create_volume(ModelVolumeType::MODEL_PART);
|
||||||
}
|
}
|
||||||
@ -629,51 +643,6 @@ void GLGizmoEmboss::draw_window()
|
|||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform3d GLGizmoEmboss::get_emboss_transformation(const Vec3f &position,
|
|
||||||
const Vec3f &emboss_dir)
|
|
||||||
{
|
|
||||||
// up and emboss direction for generated model
|
|
||||||
Vec3d text_up_dir = Vec3d::UnitY();
|
|
||||||
Vec3d text_emboss_dir = Vec3d::UnitZ();
|
|
||||||
|
|
||||||
// wanted up direction of result
|
|
||||||
Vec3d wanted_up_side = Vec3d::UnitZ();
|
|
||||||
if (std::fabs(emboss_dir.z()) > 0.9) wanted_up_side = Vec3d::UnitY();
|
|
||||||
|
|
||||||
Vec3d wanted_emboss_dir = emboss_dir.cast<double>();
|
|
||||||
wanted_emboss_dir.normalize(); // after cast from float it needs to be normalized again
|
|
||||||
|
|
||||||
// create perpendicular unit vector to surface triangle normal vector
|
|
||||||
// lay on surface of triangle and define up vector for text
|
|
||||||
Vec3d wanted_up_dir = wanted_emboss_dir.cross(wanted_up_side).cross(wanted_emboss_dir);
|
|
||||||
wanted_up_dir.normalize(); // normal3d is NOT perpendicular to normal_up_dir
|
|
||||||
|
|
||||||
// perpendicular to emboss vector of text and normal
|
|
||||||
Vec3d axis_view = text_emboss_dir.cross(wanted_emboss_dir);
|
|
||||||
double angle_view = std::acos(text_emboss_dir.dot(wanted_emboss_dir)); // in rad
|
|
||||||
axis_view.normalize();
|
|
||||||
|
|
||||||
Eigen::AngleAxis view_rot(angle_view, axis_view);
|
|
||||||
Vec3d wanterd_up_rotated = view_rot.matrix().inverse() * wanted_up_dir;
|
|
||||||
wanterd_up_rotated.normalize();
|
|
||||||
double angle_up = std::acos(text_up_dir.dot(wanterd_up_rotated));
|
|
||||||
|
|
||||||
// text_view and text_view2 should have same direction
|
|
||||||
Vec3d text_view2 = text_up_dir.cross(wanterd_up_rotated);
|
|
||||||
Vec3d diff_view = text_emboss_dir - text_view2;
|
|
||||||
if (std::fabs(diff_view.x()) > 1. || std::fabs(diff_view.y()) > 1. ||
|
|
||||||
std::fabs(diff_view.z()) > 1.) // oposit direction
|
|
||||||
angle_up *= -1.;
|
|
||||||
|
|
||||||
Eigen::AngleAxis up_rot(angle_up, text_emboss_dir);
|
|
||||||
|
|
||||||
Transform3d transform = Transform3d::Identity();
|
|
||||||
transform.translate(position.cast<double>());
|
|
||||||
transform.rotate(view_rot);
|
|
||||||
transform.rotate(up_rot);
|
|
||||||
return transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Transform3d> GLGizmoEmboss::transform_on_surface(
|
std::optional<Transform3d> GLGizmoEmboss::transform_on_surface(
|
||||||
const Vec2d &mouse_pos,
|
const Vec2d &mouse_pos,
|
||||||
const std::vector<const MeshRaycaster *> &raycasters,
|
const std::vector<const MeshRaycaster *> &raycasters,
|
||||||
@ -712,7 +681,7 @@ std::optional<Transform3d> GLGizmoEmboss::transform_on_surface(
|
|||||||
|
|
||||||
// check exist hit
|
// check exist hit
|
||||||
if (!closest.has_value()) return {};
|
if (!closest.has_value()) return {};
|
||||||
return get_emboss_transformation(closest->position, closest->normal);
|
return Emboss::create_transformation_onto_surface(closest->position, closest->normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_font_list()
|
void GLGizmoEmboss::draw_font_list()
|
||||||
|
@ -36,7 +36,17 @@ class GLGizmoEmboss : public GLGizmoBase
|
|||||||
public:
|
public:
|
||||||
GLGizmoEmboss(GLCanvas3D& parent);
|
GLGizmoEmboss(GLCanvas3D& parent);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create new embossed text volume by type on position of mouse
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
|
||||||
|
/// <param name="mouse_pos">Define position of new volume</param>
|
||||||
void create_volume(ModelVolumeType volume_type, const Vec2d &mouse_pos = Vec2d(-1,-1));
|
void create_volume(ModelVolumeType volume_type, const Vec2d &mouse_pos = Vec2d(-1,-1));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move window for edit emboss text near to embossed object
|
||||||
|
/// NOTE: embossed object must be selected
|
||||||
|
/// </summary>
|
||||||
void set_fine_position();
|
void set_fine_position();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -67,6 +77,21 @@ private:
|
|||||||
void initialize();
|
void initialize();
|
||||||
static FontList create_default_font_list();
|
static FontList create_default_font_list();
|
||||||
void set_default_configuration();
|
void set_default_configuration();
|
||||||
|
TriangleMesh create_default_mesh();
|
||||||
|
TriangleMesh create_mesh();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create mesh from text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">Text to convert on mesh</param>
|
||||||
|
/// <param name="font">Define shape of characters.
|
||||||
|
/// NOTE: Can't be const cache glyphs</param>
|
||||||
|
/// <param name="font_prop">Property of font</param>
|
||||||
|
/// <returns>Triangle mesh model</returns>
|
||||||
|
static TriangleMesh create_mesh(const char * text,
|
||||||
|
Emboss::Font & font,
|
||||||
|
const FontProp &font_prop);
|
||||||
|
|
||||||
void check_selection();
|
void check_selection();
|
||||||
// more general function --> move to select
|
// more general function --> move to select
|
||||||
ModelVolume *get_selected_volume();
|
ModelVolume *get_selected_volume();
|
||||||
@ -79,7 +104,7 @@ private:
|
|||||||
void draw_font_list();
|
void draw_font_list();
|
||||||
void draw_text_input();
|
void draw_text_input();
|
||||||
void draw_advanced();
|
void draw_advanced();
|
||||||
|
// process mouse event
|
||||||
bool on_mouse_for_rotation(const wxMouseEvent &mouse_event);
|
bool on_mouse_for_rotation(const wxMouseEvent &mouse_event);
|
||||||
bool on_mouse_for_translate(const wxMouseEvent &mouse_event);
|
bool on_mouse_for_translate(const wxMouseEvent &mouse_event);
|
||||||
|
|
||||||
@ -105,8 +130,6 @@ private:
|
|||||||
|
|
||||||
std::string create_volume_name();
|
std::string create_volume_name();
|
||||||
|
|
||||||
static Transform3d get_emboss_transformation(const Vec3f &position,
|
|
||||||
const Vec3f &emboss_dir);
|
|
||||||
std::optional<Transform3d> transform_on_surface(const Vec2d &mouse_pos,
|
std::optional<Transform3d> transform_on_surface(const Vec2d &mouse_pos,
|
||||||
const std::vector<const MeshRaycaster *> &raycasters,
|
const std::vector<const MeshRaycaster *> &raycasters,
|
||||||
const std::vector<Transform3d> & raycasters_tr
|
const std::vector<Transform3d> & raycasters_tr
|
||||||
@ -151,7 +174,6 @@ private:
|
|||||||
std::shared_ptr<Emboss::Font> m_font;
|
std::shared_ptr<Emboss::Font> m_font;
|
||||||
std::string m_text;
|
std::string m_text;
|
||||||
FontProp m_font_prop;
|
FontProp m_font_prop;
|
||||||
TriangleMesh m_default_mesh; // when add new text this shape is used
|
|
||||||
|
|
||||||
// actual volume
|
// actual volume
|
||||||
ModelVolume *m_volume;
|
ModelVolume *m_volume;
|
||||||
|
Loading…
Reference in New Issue
Block a user