mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-13 03:31:52 +08:00
separate calculation of rotation
This commit is contained in:
parent
040f721873
commit
fc9bae667d
@ -467,6 +467,41 @@ Vec2d priv::calc_mouse_to_center_text_offset(const Vec2d& mouse, const ModelVolu
|
|||||||
}
|
}
|
||||||
return nearest_offset;
|
return nearest_offset;
|
||||||
}
|
}
|
||||||
|
namespace priv {
|
||||||
|
|
||||||
|
static bool allign_z(const Vec3d &z_t, Transform3d &rotate)
|
||||||
|
{
|
||||||
|
// Transformed unit vector Z direction (f)rom, (t)o
|
||||||
|
const Vec3d& z_f = Vec3d::UnitZ();
|
||||||
|
Vec3d z_t_norm = z_t.normalized();
|
||||||
|
double cos_angle = z_t_norm.dot(z_f);
|
||||||
|
|
||||||
|
// Calculate rotation of Z-vectors from current to wanted position
|
||||||
|
rotate = Transform3d::Identity();
|
||||||
|
|
||||||
|
if (cos_angle == 0.) {
|
||||||
|
// check that direction is not same
|
||||||
|
if (z_t_norm.z() > 0.)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// opposit direction of z_t and z_f (a.k.a. angle 180 DEG)
|
||||||
|
rotate = Eigen::AngleAxis(M_PI, Vec3d::UnitX());
|
||||||
|
return true;
|
||||||
|
} else if (cos_angle >= 1. || cos_angle <= -1.) {
|
||||||
|
// bad cas angle value almost zero angle so no rotation
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate only when angle is not zero
|
||||||
|
// Calculate rotation axe from current to wanted inside instance
|
||||||
|
Vec3d axe = z_t_norm.cross(z_f);
|
||||||
|
axe.normalize();
|
||||||
|
double angle = acos(cos_angle);
|
||||||
|
rotate = Eigen::AngleAxis(-angle, axe);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
||||||
{
|
{
|
||||||
@ -544,6 +579,11 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
Vec2d mouse_offset = priv::calc_mouse_to_center_text_offset(mouse_pos, *m_volume);
|
Vec2d mouse_offset = priv::calc_mouse_to_center_text_offset(mouse_pos, *m_volume);
|
||||||
Transform3d instance_inv = gl_volume->get_instance_transformation().get_matrix().inverse();
|
Transform3d instance_inv = gl_volume->get_instance_transformation().get_matrix().inverse();
|
||||||
Transform3d volume_tr = gl_volume->get_volume_transformation().get_matrix();
|
Transform3d volume_tr = gl_volume->get_volume_transformation().get_matrix();
|
||||||
|
TextConfiguration &tc = *m_volume->text_configuration;
|
||||||
|
// fix baked transformation from .3mf store process
|
||||||
|
if (tc.fix_3mf_tr.has_value())
|
||||||
|
volume_tr = volume_tr * tc.fix_3mf_tr->inverse();
|
||||||
|
|
||||||
m_surface_drag = SurfaceDrag{mouse_offset, instance_inv, volume_tr, gl_volume, condition};
|
m_surface_drag = SurfaceDrag{mouse_offset, instance_inv, volume_tr, gl_volume, condition};
|
||||||
|
|
||||||
// Cancel job to prevent interuption of dragging (duplicit result)
|
// Cancel job to prevent interuption of dragging (duplicit result)
|
||||||
@ -566,76 +606,38 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
Vec2d offseted_mouse = mouse_pos + m_surface_drag->mouse_offset;
|
Vec2d offseted_mouse = mouse_pos + m_surface_drag->mouse_offset;
|
||||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||||
auto hit = m_raycast_manager.unproject(offseted_mouse, camera, &m_surface_drag->condition);
|
auto hit = m_raycast_manager.unproject(offseted_mouse, camera, &m_surface_drag->condition);
|
||||||
|
m_surface_drag->exist_hit = hit.has_value();
|
||||||
if (!hit.has_value()) {
|
if (!hit.has_value()) {
|
||||||
// cross hair need redraw
|
// cross hair need redraw
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate temporary position
|
// Calculate offset: transformation to wanted position
|
||||||
Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key);
|
Transform3d object_trmat = m_raycast_manager.get_transformation(hit->tr_key);
|
||||||
Transform3d trmat = create_transformation_onto_surface(hit->position, hit->normal);
|
|
||||||
|
|
||||||
// !!!!!!!!!!!!!!!! USE DIRECT hit position and normal
|
|
||||||
|
|
||||||
//TextConfiguration &tc = *m_volume->text_configuration;
|
|
||||||
//const FontProp& font_prop = tc.style.prop;
|
|
||||||
//apply_transformation(font_prop, trmat);
|
|
||||||
|
|
||||||
//// fix baked transformation from .3mf store process
|
|
||||||
//if (tc.fix_3mf_tr.has_value())
|
|
||||||
// trmat = trmat * (*tc.fix_3mf_tr);
|
|
||||||
|
|
||||||
// volume transfomration in world coor
|
|
||||||
Transform3d wanted_world = object_trmat * trmat;
|
|
||||||
Transform3d wanted_volume = m_surface_drag->instance_inv * wanted_world;
|
|
||||||
|
|
||||||
// Calculate offset inside instance:
|
|
||||||
// transformation from curret to wanted position
|
|
||||||
Vec3d from_position = m_surface_drag->volume_tr * Vec3d::Zero();
|
|
||||||
Vec3d to_position = wanted_volume * Vec3d::Zero();
|
|
||||||
|
|
||||||
Transform3d hit_to_instance = object_trmat * m_surface_drag->instance_inv;
|
Transform3d hit_to_instance = object_trmat * m_surface_drag->instance_inv;
|
||||||
Vec3d to_position2 = hit_to_instance * hit->position.cast<double>();
|
Transform3d hit_to_volume = hit_to_instance * m_surface_drag->volume_tr.inverse();
|
||||||
Vec3d z_t2 = hit_to_instance.linear() * hit->normal.cast<double>();
|
Vec3d offset_volume = hit_to_volume * hit->position.cast<double>();
|
||||||
|
Transform3d translate{Eigen::Translation<double, 3>(offset_volume)};
|
||||||
|
|
||||||
Vec3d offset_instance = to_position - from_position;
|
Transform3d rotate;
|
||||||
Transform3d trnsl{Eigen::Translation<double, 3>(offset_instance)};
|
// normal transformed to volume
|
||||||
|
Vec3d z_t = hit_to_volume.linear() * hit->normal.cast<double>();
|
||||||
|
bool exist_rotate = priv::allign_z(z_t, rotate);
|
||||||
|
|
||||||
|
Transform3d volume_tr = m_surface_drag->volume_tr * translate * rotate;
|
||||||
|
assert(volume_tr.matrix()(0, 0) == volume_tr.matrix()(0, 0)); // Check valid transformation not a NAN
|
||||||
|
if (volume_tr.matrix()(0, 0) != volume_tr.matrix()(0, 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check scale in world
|
||||||
|
|
||||||
// current transformation from volume to world
|
// current transformation from volume to world
|
||||||
Transform3d current_world = m_surface_drag->instance_inv.inverse() * m_surface_drag->volume_tr;
|
Transform3d current_world = m_surface_drag->instance_inv.inverse() * m_surface_drag->volume_tr;
|
||||||
|
|
||||||
auto current_world_linear = current_world.linear();
|
auto current_world_linear = current_world.linear();
|
||||||
auto wanted_world_linear = wanted_world.linear();
|
|
||||||
|
|
||||||
// Calculate rotation of Z-vectors from current to wanted position
|
Transform3d wanted_world = m_surface_drag->instance_inv.inverse() * volume_tr;
|
||||||
Transform3d rot = Transform3d::Identity();
|
auto wanted_world_linear = wanted_world.linear();
|
||||||
// Transformed unit vector Z direction (f)rom, (t)o
|
|
||||||
Vec3d z_f = m_surface_drag->volume_tr.linear() * Vec3d::UnitZ();
|
|
||||||
Vec3d z_t = wanted_volume.linear() * Vec3d::UnitZ();
|
|
||||||
z_f.normalize();
|
|
||||||
z_t.normalize();
|
|
||||||
double cos_angle = z_t.dot(z_f);
|
|
||||||
|
|
||||||
// Calculate only when angle is not zero
|
|
||||||
if (cos_angle < 1. && cos_angle > -1.) {
|
|
||||||
m_surface_drag->from = from_position;
|
|
||||||
m_surface_drag->to = to_position;
|
|
||||||
m_surface_drag->from_dir = z_f;
|
|
||||||
m_surface_drag->to_dir = z_t;
|
|
||||||
|
|
||||||
m_surface_drag->f_tr = current_world;
|
|
||||||
m_surface_drag->t_tr = wanted_world;
|
|
||||||
|
|
||||||
// TODO: solve opposit direction of z_t and z_f (a.k.a. angle 180 DEG)
|
|
||||||
// if (cos_angle == 0.) {}
|
|
||||||
|
|
||||||
// Calculate rotation axe from current to wanted inside instance
|
|
||||||
Vec3d axe = z_t.cross(z_f);
|
|
||||||
axe.normalize();
|
|
||||||
double angle = acos(cos_angle);
|
|
||||||
rot = Eigen::AngleAxis(-angle, axe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate scale in world
|
// Calculate scale in world
|
||||||
auto calc_scale = [¤t_world_linear, wanted_world_linear](const Vec3d &dir) -> double {
|
auto calc_scale = [¤t_world_linear, wanted_world_linear](const Vec3d &dir) -> double {
|
||||||
@ -643,18 +645,32 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
Vec3d wanted = wanted_world_linear * dir;
|
Vec3d wanted = wanted_world_linear * dir;
|
||||||
double current_sq = current.squaredNorm();
|
double current_sq = current.squaredNorm();
|
||||||
double wanted_sq = wanted.squaredNorm();
|
double wanted_sq = wanted.squaredNorm();
|
||||||
return sqrt(wanted_sq / current_sq);
|
return sqrt(current_sq / wanted_sq);
|
||||||
};
|
};
|
||||||
double y_scale = calc_scale(Vec3d::UnitY());
|
double y_scale = calc_scale(Vec3d::UnitY());
|
||||||
double z_scale = calc_scale(Vec3d::UnitZ());
|
double z_scale = calc_scale(Vec3d::UnitZ());
|
||||||
Transform3d scale(Eigen::Scaling(1., y_scale, z_scale));
|
Transform3d scale(Eigen::Scaling(1., y_scale, z_scale));
|
||||||
|
volume_tr = volume_tr * scale;
|
||||||
|
|
||||||
Transform3d volume_tr = trnsl * m_surface_drag->volume_tr * rot;
|
// recalculate rotation for scaled volume
|
||||||
|
//Transform3d hit_to_volume2 = hit_to_instance * (m_surface_drag->volume_tr*scale).inverse();
|
||||||
|
//z_t = hit_to_volume2.linear() * hit->normal.cast<double>();
|
||||||
|
//bool exist_rotate2 = priv::allign_z(z_t, rotate);
|
||||||
|
//volume_tr = m_surface_drag->volume_tr * translate * rotate * scale;
|
||||||
|
|
||||||
assert(volume_tr.matrix()(0,0) == volume_tr.matrix()(0,0)); // Check valid transformation not a NAN
|
const TextConfiguration &tc = *m_volume->text_configuration;
|
||||||
Transform3d volume_tr2 = m_surface_drag->instance_inv * wanted_world;
|
// fix baked transformation from .3mf store process
|
||||||
|
if (tc.fix_3mf_tr.has_value())
|
||||||
|
volume_tr = volume_tr * (*tc.fix_3mf_tr);
|
||||||
|
|
||||||
// Update transformation inside of instances
|
// apply move in Z direction for move with flat surface above texture
|
||||||
|
const FontProp &prop = tc.style.prop;
|
||||||
|
if (!prop.use_surface && prop.distance.has_value()) {
|
||||||
|
Vec3d translate = Vec3d::UnitZ() * (*prop.distance);
|
||||||
|
volume_tr.translate(translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update transformation forf all instances
|
||||||
for (GLVolume *vol : m_parent.get_volumes().volumes) {
|
for (GLVolume *vol : m_parent.get_volumes().volumes) {
|
||||||
if (vol->object_idx() != m_surface_drag->gl_volume->object_idx() ||
|
if (vol->object_idx() != m_surface_drag->gl_volume->object_idx() ||
|
||||||
vol->volume_idx() != m_surface_drag->gl_volume->volume_idx())
|
vol->volume_idx() != m_surface_drag->gl_volume->volume_idx())
|
||||||
@ -662,7 +678,7 @@ bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
|
|||||||
vol->set_volume_transformation(volume_tr);
|
vol->set_volume_transformation(volume_tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate scale
|
// update scale of selected volume --> should be approx the same
|
||||||
calculate_scale();
|
calculate_scale();
|
||||||
|
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
@ -862,7 +878,13 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||||||
ImVec2 center(
|
ImVec2 center(
|
||||||
mouse_pos.x + m_surface_drag->mouse_offset.x(),
|
mouse_pos.x + m_surface_drag->mouse_offset.x(),
|
||||||
mouse_pos.y + m_surface_drag->mouse_offset.y());
|
mouse_pos.y + m_surface_drag->mouse_offset.y());
|
||||||
priv::draw_cross_hair(center);
|
ImU32 color = ImGui::GetColorU32(
|
||||||
|
m_surface_drag->exist_hit ?
|
||||||
|
ImVec4(1.f, 1.f, 1.f, .75f) : // transparent white
|
||||||
|
ImVec4(1.f, .3f, .3f, .75f)
|
||||||
|
); // Warning color
|
||||||
|
const float radius = 16.f;
|
||||||
|
priv::draw_cross_hair(center, radius, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHOW_FINE_POSITION
|
#ifdef SHOW_FINE_POSITION
|
||||||
@ -1115,18 +1137,22 @@ GLGizmoEmboss::GuiCfg GLGizmoEmboss::create_gui_configuration()
|
|||||||
EmbossStyles GLGizmoEmboss::create_default_styles()
|
EmbossStyles GLGizmoEmboss::create_default_styles()
|
||||||
{
|
{
|
||||||
wxFont wx_font_normal = *wxNORMAL_FONT;
|
wxFont wx_font_normal = *wxNORMAL_FONT;
|
||||||
wxFont wx_font_small = *wxSMALL_FONT;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
wx_font_normal.SetFaceName("Helvetica");
|
// Set normal font to helvetica when possible
|
||||||
wx_font_small.SetFaceName("Helvetica");
|
wxArrayString facenames = wxFontEnumerator::GetFacenames(Facenames::encoding);
|
||||||
|
for (const wxString &facename : facenames) {
|
||||||
|
if (facename.IsSameAs("Helvetica")) {
|
||||||
|
wx_font_normal = wxFont(wxFontInfo().FaceName(facename).Encoding(Facenames::encoding));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
// https://docs.wxwidgets.org/3.0/classwx_font.html
|
// https://docs.wxwidgets.org/3.0/classwx_font.html
|
||||||
// Predefined objects/pointers: wxNullFont, wxNORMAL_FONT, wxSMALL_FONT, wxITALIC_FONT, wxSWISS_FONT
|
// Predefined objects/pointers: wxNullFont, wxNORMAL_FONT, wxSMALL_FONT, wxITALIC_FONT, wxSWISS_FONT
|
||||||
EmbossStyles styles = {
|
EmbossStyles styles = {
|
||||||
WxFontUtils::create_emboss_style(wx_font_normal, _u8L("NORMAL")), // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)
|
WxFontUtils::create_emboss_style(wx_font_normal, _u8L("NORMAL")), // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)
|
||||||
WxFontUtils::create_emboss_style(wx_font_normal, _u8L("SMALL")), // A font using the wxFONTFAMILY_SWISS family and 2 points smaller than wxNORMAL_FONT.
|
WxFontUtils::create_emboss_style(*wxSMALL_FONT, _u8L("SMALL")), // A font using the wxFONTFAMILY_SWISS family and 2 points smaller than wxNORMAL_FONT.
|
||||||
WxFontUtils::create_emboss_style(*wxITALIC_FONT, _u8L("ITALIC")), // A font using the wxFONTFAMILY_ROMAN family and wxFONTSTYLE_ITALIC style and of the same size of wxNORMAL_FONT.
|
WxFontUtils::create_emboss_style(*wxITALIC_FONT, _u8L("ITALIC")), // A font using the wxFONTFAMILY_ROMAN family and wxFONTSTYLE_ITALIC style and of the same size of wxNORMAL_FONT.
|
||||||
WxFontUtils::create_emboss_style(*wxSWISS_FONT, _u8L("SWISS")), // A font identic to wxNORMAL_FONT except for the family used which is wxFONTFAMILY_SWISS.
|
WxFontUtils::create_emboss_style(*wxSWISS_FONT, _u8L("SWISS")), // A font identic to wxNORMAL_FONT except for the family used which is wxFONTFAMILY_SWISS.
|
||||||
WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("MODERN")),
|
WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("MODERN")),
|
||||||
|
@ -255,7 +255,7 @@ private:
|
|||||||
std::vector<wxString> bad = {};
|
std::vector<wxString> bad = {};
|
||||||
|
|
||||||
// Configuration of font encoding
|
// Configuration of font encoding
|
||||||
const wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
static const wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
||||||
|
|
||||||
// Identify if preview texture exists
|
// Identify if preview texture exists
|
||||||
GLuint texture_id = 0;
|
GLuint texture_id = 0;
|
||||||
@ -325,6 +325,8 @@ private:
|
|||||||
// condition for raycaster
|
// condition for raycaster
|
||||||
RaycastManager::AllowVolumes condition;
|
RaycastManager::AllowVolumes condition;
|
||||||
|
|
||||||
|
bool exist_hit = true;
|
||||||
|
|
||||||
// Visuzalization
|
// Visuzalization
|
||||||
Vec3d from = Vec3d::Zero();
|
Vec3d from = Vec3d::Zero();
|
||||||
Vec3d to = Vec3d::Zero();
|
Vec3d to = Vec3d::Zero();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user