transformation of object

This commit is contained in:
Filip Sykala 2021-12-01 13:56:52 +01:00
parent d4744954cb
commit ef1bdf60ee
3 changed files with 151 additions and 24 deletions

View File

@ -189,7 +189,6 @@ public:
}; };
#endif // __linux__ #endif // __linux__
} // namespace Slic3r } // namespace Slic3r
using namespace Slic3r; using namespace Slic3r;
@ -200,6 +199,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
, m_font_selected(0) , m_font_selected(0)
, m_font(nullptr) , m_font(nullptr)
, m_volume(nullptr) , m_volume(nullptr)
, m_drag(false)
, m_exist_notification(false) , m_exist_notification(false)
, m_is_initialized(false) // initialize on first opening gizmo , m_is_initialized(false) // initialize on first opening gizmo
, m_job(std::make_unique<EmbossJob>()) , m_job(std::make_unique<EmbossJob>())
@ -261,7 +261,7 @@ static void draw_fine_position(const Selection &selection)
} }
#endif // ALLOW_DEBUG_MODE #endif // ALLOW_DEBUG_MODE
void GLGizmoEmboss::create_volume(ModelVolumeType volume_type) void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mouse_pos)
{ {
if (!m_is_initialized) initialize(); if (!m_is_initialized) initialize();
const Selection &selection = m_parent.get_selection(); const Selection &selection = m_parent.get_selection();
@ -269,6 +269,13 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type)
set_default_configuration(); set_default_configuration();
TriangleMesh tm = m_default_mesh; // copy TriangleMesh tm = m_default_mesh; // copy
// By position of cursor create transformation to put text on surface of model
if (mouse_pos.x() >= 0 && mouse_pos.y() >= 0) {
std::optional<Transform3d> tr = transform_on_surface(mouse_pos);
if (tr.has_value()) tm.transform(*tr);
}
create_emboss_volume(std::move(tm), create_volume_name(), create_emboss_volume(std::move(tm), create_volume_name(),
create_configuration(), volume_type, create_configuration(), volume_type,
selection.get_object_idx()); selection.get_object_idx());
@ -376,16 +383,20 @@ void GLGizmoEmboss::on_set_state()
// when open by hyperlink it needs to show up // when open by hyperlink it needs to show up
m_parent.reload_scene(true); m_parent.reload_scene(true);
// TODO: after key T windows doesn't appear
} }
} }
void GLGizmoEmboss::on_start_dragging() {
CommonGizmosDataID GLGizmoEmboss::on_get_requirements() const
{
return CommonGizmosDataID((int) CommonGizmosDataID::Raycaster |
(int) CommonGizmosDataID::SelectionInfo);
} }
void GLGizmoEmboss::on_stop_dragging() { void GLGizmoEmboss::on_start_dragging() { m_drag = true; }
} void GLGizmoEmboss::on_stop_dragging() { m_drag = false; }
void GLGizmoEmboss::initialize() void GLGizmoEmboss::initialize()
{ {
@ -535,7 +546,9 @@ ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
bool GLGizmoEmboss::process() bool GLGizmoEmboss::process()
{ {
assert(m_volume != nullptr); // no volume is selected -> selection from right panel
if (m_volume == nullptr) return false;
// exist loaded font? // exist loaded font?
if (m_font == nullptr) return false; if (m_font == nullptr) return false;
auto data = std::make_unique<EmbossData>( auto data = std::make_unique<EmbossData>(
@ -600,16 +613,124 @@ void GLGizmoEmboss::draw_window()
} }
} }
m_imgui->disabled_end(); m_imgui->disabled_end();
ImGui::SameLine();
ImGui::Checkbox("drag", &m_drag);
ImGui::SameLine();
ImGui::Checkbox("dragging", &m_dragging);
static bool change_position = true; static bool change_position = true;
ImGui::Checkbox("change position", &change_position); ImGui::SameLine();
ImGui::Checkbox("position", &change_position);
if (change_position) { if (change_position) {
// draw text on coordinate of mouse // draw text on coordinate of mouse
preview_positon(); preview_positon();
} }
} }
Transform3d 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(
const Vec2d &mouse_pos)
{
auto rc = m_c->raycaster();
if (rc == nullptr || !rc->is_valid()) return {};
const std::vector<const MeshRaycaster *> &raycasters = rc->raycasters();
Selection &selection = m_parent.get_selection();
// check selection has volume
if (selection.volumes_count() < 0) return {};
assert(selection.volumes_count() == (int)raycasters.size());
const Camera &camera = wxGetApp().plater()->get_camera();
// in object coordinate
struct Hit
{
Vec3f position = Vec3f::Zero();
Vec3f normal = Vec3f::Zero();
double squared_distance = std::numeric_limits<double>::max();
Hit()=default;
};
std::optional<Hit> closest;
const ModelObject * mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
// Cast a ray on all meshes, pick the closest hit and save it for the
// respective mesh
int count_mesh = raycasters.size();
auto volume_ids = selection.get_volume_idxs();
for (int volume_in_object = 0; volume_in_object < count_mesh; ++volume_in_object) {
const MeshRaycaster *raycaster = raycasters[volume_in_object];
const ModelVolume * mv = mo->volumes[volume_in_object];
Transform3d trafo = instance_trafo * mv->get_matrix();
Hit act_hit;
if (!raycaster->unproject_on_mesh(mouse_pos, trafo, camera, act_hit.position, act_hit.normal))
continue;
Vec3d act_hit_tr = trafo * act_hit.position.cast<double>();
act_hit.squared_distance = (camera.get_position() - act_hit_tr).squaredNorm();
if (closest.has_value() &&
closest->squared_distance < act_hit.squared_distance)
continue;
closest = act_hit;
}
// check exist hit
if (!closest.has_value()) return {};
return get_emboss_transformation(closest->position, closest->normal);
}
void GLGizmoEmboss::preview_positon() { void GLGizmoEmboss::preview_positon() {
Vec2d mouse_pos = m_parent.get_local_mouse_position();
auto rc = m_c->raycaster();
//auto rc2 = rc->raycaster();
static std::unique_ptr<MeshRaycaster> mrc; static std::unique_ptr<MeshRaycaster> mrc;
if (m_volume == nullptr) return; if (m_volume == nullptr) return;
@ -647,17 +768,13 @@ void GLGizmoEmboss::preview_positon() {
} }
if (gl_volume == nullptr) return; if (gl_volume == nullptr) return;
Transform3d trafo = gl_volume->world_matrix();
Vec2d mouse_pos = m_parent.get_local_mouse_position();
Transform3d trafo = (gl_volume->get_volume_transformation() *
gl_volume->get_instance_transformation())
.get_matrix();
const Camera &camera = wxGetApp().plater()->get_camera(); const Camera &camera = wxGetApp().plater()->get_camera();
Vec3f position; Vec3f position;
Vec3f normal; Vec3f normal;
size_t face_id; size_t face_id;
if (mrc->unproject_on_mesh(mouse_pos, trafo, camera, position, normal,nullptr,&face_id)) { if (mrc->unproject_on_mesh(mouse_pos, trafo, camera, position, normal, nullptr, &face_id)) {
// draw triangle // draw triangle
auto &its =volume->mesh().its; auto &its =volume->mesh().its;
auto &triangle = its.indices[face_id]; auto &triangle = its.indices[face_id];
@ -672,17 +789,21 @@ void GLGizmoEmboss::preview_positon() {
m_preview.init_from(m_volume->mesh().its); m_preview.init_from(m_volume->mesh().its);
// up and emboss direction for generated model
Vec3d text_up = Vec3d::UnitY(); Vec3d text_up = Vec3d::UnitY();
Vec3d text_view = Vec3d::UnitZ(); Vec3d text_view = Vec3d::UnitZ();
// wanted up direction of result
Vec3d normal_up_dir = Vec3d::UnitZ(); Vec3d normal_up_dir = Vec3d::UnitZ();
if (abs(normal.z()) > 0.9) normal_up_dir = Vec3d::UnitY(); if (abs(normal.z()) > 0.9) normal_up_dir = Vec3d::UnitY();
// create perpendicular unit vector to surface triangle normal vector
// define up vector for text
Vec3d normal3d = normal.cast<double>(); Vec3d normal3d = normal.cast<double>();
normal3d.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 normal_up = normal3d.cross(normal_up_dir).cross(normal3d); Vec3d normal_up = normal3d.cross(normal_up_dir).cross(normal3d);
normal_up.normalize(); normal_up.normalize(); // normal3d is NOT perpendicular to normal_up_dir
// perpendicular to emboss vector of text and normal // perpendicular to emboss vector of text and normal
Vec3d axis_view = text_view.cross(normal3d); Vec3d axis_view = text_view.cross(normal3d);
@ -707,6 +828,8 @@ void GLGizmoEmboss::preview_positon() {
transform.rotate(view_rot); transform.rotate(view_rot);
transform.rotate(up_rot); transform.rotate(up_rot);
transform = get_emboss_transformation(position, normal);
//Transform3d rot = Transform3d::Identity(); //Transform3d rot = Transform3d::Identity();
//rot.rotate(Eigen::AngleAxis(angle, axis)); //rot.rotate(Eigen::AngleAxis(angle, axis));

View File

@ -29,7 +29,7 @@ class GLGizmoEmboss : public GLGizmoBase
public: public:
GLGizmoEmboss(GLCanvas3D& parent); GLGizmoEmboss(GLCanvas3D& parent);
void create_volume(ModelVolumeType volume_type); void create_volume(ModelVolumeType volume_type, const Vec2d &mouse_pos = Vec2d(-1,-1));
void set_fine_position(); void set_fine_position();
protected: protected:
bool on_init() override; bool on_init() override;
@ -41,6 +41,7 @@ protected:
bool on_is_selectable() const override { return false; } bool on_is_selectable() const override { return false; }
void on_set_state() override; void on_set_state() override;
CommonGizmosDataID on_get_requirements() const override;
void on_start_dragging() override; void on_start_dragging() override;
void on_stop_dragging() override; void on_stop_dragging() override;
@ -83,6 +84,8 @@ private:
std::string create_volume_name(); std::string create_volume_name();
std::optional<Transform3d> transform_on_surface(const Vec2d &mouse_pos);
// This configs holds GUI layout size given by translated texts. // This configs holds GUI layout size given by translated texts.
// etc. When language changes, GUI is recreated and this class constructed again, // etc. When language changes, GUI is recreated and this class constructed again,
// so the change takes effect. (info by GLGizmoFdmSupports.hpp) // so the change takes effect. (info by GLGizmoFdmSupports.hpp)
@ -130,6 +133,7 @@ private:
// actual volume // actual volume
ModelVolume *m_volume; ModelVolume *m_volume;
bool m_drag;
// preview position // preview position
GLModel m_preview; GLModel m_preview;
Transform3d m_preview_trmat; Transform3d m_preview_trmat;

View File

@ -656,13 +656,13 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) { if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) {
// mouse is outside the toolbar // mouse is outside the toolbar
m_tooltip.clear(); m_tooltip.clear();
bool exist_mouse_grabber = grabber_contains_mouse();
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) { if (evt.LeftDown() && (!control_down || exist_mouse_grabber)) {
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation)
&& gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown())) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown()))
// the gizmo got the event and took some action, there is no need to do anything more // the gizmo got the event and took some action, there is no need to do anything more
processed = true; processed = true;
else if (!selection.is_empty() && grabber_contains_mouse()) { else if (!selection.is_empty() && exist_mouse_grabber) {
update_data(); update_data();
selection.start_dragging(); selection.start_dragging();
start_dragging(); start_dragging();