mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 12:15:53 +08:00
Merge remote-tracking branch 'origin/et_trafo_matrix_rebase'
This commit is contained in:
commit
db8a120953
@ -313,9 +313,60 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assemble_transform(Transform3d& transform, const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror)
|
||||||
|
{
|
||||||
|
transform = translation * rotation * scale * mirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d assemble_transform(const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror)
|
||||||
|
{
|
||||||
|
Transform3d transform;
|
||||||
|
assemble_transform(transform, translation, rotation, scale, mirror);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translation_transform(Transform3d& transform, const Vec3d& translation)
|
||||||
|
{
|
||||||
|
transform = Transform3d::Identity();
|
||||||
|
transform.translate(translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d translation_transform(const Vec3d& translation)
|
||||||
|
{
|
||||||
|
Transform3d transform;
|
||||||
|
translation_transform(transform, translation);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotation_transform(Transform3d& transform, const Vec3d& rotation)
|
||||||
|
{
|
||||||
|
transform = Transform3d::Identity();
|
||||||
|
transform.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()) * Eigen::AngleAxisd(rotation.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(rotation.x(), Vec3d::UnitX()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d rotation_transform(const Vec3d& rotation)
|
||||||
|
{
|
||||||
|
Transform3d transform;
|
||||||
|
rotation_transform(transform, rotation);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scale_transform(Transform3d& transform, const Vec3d& scale)
|
||||||
|
{
|
||||||
|
transform = Transform3d::Identity();
|
||||||
|
transform.scale(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d scale_transform(const Vec3d& scale)
|
||||||
|
{
|
||||||
|
Transform3d transform;
|
||||||
|
scale_transform(transform, scale);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
|
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
|
||||||
{
|
{
|
||||||
// reference: http://www.gregslabaugh.net/publications/euler.pdf
|
// reference: http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf
|
||||||
Vec3d angles1 = Vec3d::Zero();
|
Vec3d angles1 = Vec3d::Zero();
|
||||||
Vec3d angles2 = Vec3d::Zero();
|
Vec3d angles2 = Vec3d::Zero();
|
||||||
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5) {
|
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5) {
|
||||||
@ -363,6 +414,54 @@ Vec3d extract_euler_angles(const Transform3d& transform)
|
|||||||
return extract_euler_angles(m);
|
return extract_euler_angles(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Transform3d Transformation::get_offset_matrix() const
|
||||||
|
{
|
||||||
|
return assemble_transform(get_offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform3d extract_rotation(const Transform3d& trafo)
|
||||||
|
{
|
||||||
|
Matrix3d rotation;
|
||||||
|
Matrix3d scale;
|
||||||
|
trafo.computeRotationScaling(&rotation, &scale);
|
||||||
|
return Transform3d(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Transform3d extract_scale(const Transform3d& trafo)
|
||||||
|
{
|
||||||
|
Matrix3d rotation;
|
||||||
|
Matrix3d scale;
|
||||||
|
trafo.computeRotationScaling(&rotation, &scale);
|
||||||
|
return Transform3d(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::pair<Transform3d, Transform3d> extract_rotation_scale(const Transform3d& trafo)
|
||||||
|
{
|
||||||
|
Matrix3d rotation;
|
||||||
|
Matrix3d scale;
|
||||||
|
trafo.computeRotationScaling(&rotation, &scale);
|
||||||
|
return { Transform3d(rotation), Transform3d(scale) };
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool contains_skew(const Transform3d& trafo)
|
||||||
|
{
|
||||||
|
Matrix3d rotation;
|
||||||
|
Matrix3d scale;
|
||||||
|
trafo.computeRotationScaling(&rotation, &scale);
|
||||||
|
return !scale.isDiagonal();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d Transformation::get_rotation() const
|
||||||
|
{
|
||||||
|
return extract_euler_angles(extract_rotation(m_matrix));
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_rotation_matrix() const
|
||||||
|
{
|
||||||
|
return extract_rotation(m_matrix);
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
|
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
|
||||||
{
|
{
|
||||||
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror);
|
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror);
|
||||||
@ -400,12 +499,19 @@ void Transformation::set_offset(Axis axis, double offset)
|
|||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void Transformation::set_rotation(const Vec3d& rotation)
|
void Transformation::set_rotation(const Vec3d& rotation)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation_transform(rotation) * extract_scale(m_matrix);
|
||||||
|
m_matrix.translation() = offset;
|
||||||
|
#else
|
||||||
set_rotation(X, rotation.x());
|
set_rotation(X, rotation.x());
|
||||||
set_rotation(Y, rotation.y());
|
set_rotation(Y, rotation.y());
|
||||||
set_rotation(Z, rotation.z());
|
set_rotation(Z, rotation.z());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transformation::set_rotation(Axis axis, double rotation)
|
void Transformation::set_rotation(Axis axis, double rotation)
|
||||||
@ -414,32 +520,106 @@ void Transformation::set_rotation(Axis axis, double rotation)
|
|||||||
if (is_approx(std::abs(rotation), 2.0 * double(PI)))
|
if (is_approx(std::abs(rotation), 2.0 * double(PI)))
|
||||||
rotation = 0.0;
|
rotation = 0.0;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
auto [curr_rotation, scale] = extract_rotation_scale(m_matrix);
|
||||||
|
Vec3d angles = extract_euler_angles(curr_rotation);
|
||||||
|
angles[axis] = rotation;
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation_transform(angles) * scale;
|
||||||
|
m_matrix.translation() = offset;
|
||||||
|
#else
|
||||||
if (m_rotation(axis) != rotation) {
|
if (m_rotation(axis) != rotation) {
|
||||||
m_rotation(axis) = rotation;
|
m_rotation(axis) = rotation;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d Transformation::get_scaling_factor() const
|
||||||
|
{
|
||||||
|
const Transform3d scale = extract_scale(m_matrix);
|
||||||
|
return { scale(0, 0), scale(1, 1), scale(2, 2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_scaling_factor_matrix() const
|
||||||
|
{
|
||||||
|
return extract_scale(m_matrix);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
assert(scaling_factor.x() > 0.0 && scaling_factor.y() > 0.0 && scaling_factor.z() > 0.0);
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = extract_rotation(m_matrix) * scale_transform(scaling_factor);
|
||||||
|
m_matrix.translation() = offset;
|
||||||
|
#else
|
||||||
set_scaling_factor(X, scaling_factor.x());
|
set_scaling_factor(X, scaling_factor.x());
|
||||||
set_scaling_factor(Y, scaling_factor.y());
|
set_scaling_factor(Y, scaling_factor.y());
|
||||||
set_scaling_factor(Z, scaling_factor.z());
|
set_scaling_factor(Z, scaling_factor.z());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
assert(scaling_factor > 0.0);
|
||||||
|
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||||
|
scale(axis, axis) = scaling_factor;
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation * scale;
|
||||||
|
m_matrix.translation() = offset;
|
||||||
|
#else
|
||||||
if (m_scaling_factor(axis) != std::abs(scaling_factor)) {
|
if (m_scaling_factor(axis) != std::abs(scaling_factor)) {
|
||||||
m_scaling_factor(axis) = std::abs(scaling_factor);
|
m_scaling_factor(axis) = std::abs(scaling_factor);
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d Transformation::get_mirror() const
|
||||||
|
{
|
||||||
|
const Transform3d scale = extract_scale(m_matrix);
|
||||||
|
return { scale(0, 0) / std::abs(scale(0, 0)), scale(1, 1) / std::abs(scale(1, 1)), scale(2, 2) / std::abs(scale(2, 2)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_mirror_matrix() const
|
||||||
|
{
|
||||||
|
const Vec3d scale = get_scaling_factor();
|
||||||
|
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void Transformation::set_mirror(const Vec3d& mirror)
|
void Transformation::set_mirror(const Vec3d& mirror)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d copy(mirror);
|
||||||
|
const Vec3d abs_mirror = copy.cwiseAbs();
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
if (abs_mirror(i) == 0.0)
|
||||||
|
copy(i) = 1.0;
|
||||||
|
else if (abs_mirror(i) != 1.0)
|
||||||
|
copy(i) /= abs_mirror(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3d curr_scale = get_scaling_factor();
|
||||||
|
const Vec3d signs = curr_scale.cwiseProduct(copy);
|
||||||
|
set_scaling_factor({
|
||||||
|
signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(),
|
||||||
|
signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(),
|
||||||
|
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
|
||||||
|
});
|
||||||
|
#else
|
||||||
set_mirror(X, mirror.x());
|
set_mirror(X, mirror.x());
|
||||||
set_mirror(Y, mirror.y());
|
set_mirror(Y, mirror.y());
|
||||||
set_mirror(Z, mirror.z());
|
set_mirror(Z, mirror.z());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transformation::set_mirror(Axis axis, double mirror)
|
void Transformation::set_mirror(Axis axis, double mirror)
|
||||||
@ -450,12 +630,24 @@ void Transformation::set_mirror(Axis axis, double mirror)
|
|||||||
else if (abs_mirror != 1.0)
|
else if (abs_mirror != 1.0)
|
||||||
mirror /= abs_mirror;
|
mirror /= abs_mirror;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const double curr_scale = get_scaling_factor(axis);
|
||||||
|
const double sign = curr_scale * mirror;
|
||||||
|
set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale);
|
||||||
|
#else
|
||||||
if (m_mirror(axis) != mirror) {
|
if (m_mirror(axis) != mirror) {
|
||||||
m_mirror(axis) = mirror;
|
m_mirror(axis) = mirror;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
bool Transformation::has_skew() const
|
||||||
|
{
|
||||||
|
return contains_skew(m_matrix);
|
||||||
|
}
|
||||||
|
#else
|
||||||
void Transformation::set_from_transform(const Transform3d& transform)
|
void Transformation::set_from_transform(const Transform3d& transform)
|
||||||
{
|
{
|
||||||
// offset
|
// offset
|
||||||
@ -493,17 +685,62 @@ void Transformation::set_from_transform(const Transform3d& transform)
|
|||||||
// if (!m_matrix.isApprox(transform))
|
// if (!m_matrix.isApprox(transform))
|
||||||
// std::cout << "something went wrong in extracting data from matrix" << std::endl;
|
// std::cout << "something went wrong in extracting data from matrix" << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void Transformation::reset()
|
void Transformation::reset()
|
||||||
{
|
{
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
m_offset = Vec3d::Zero();
|
m_offset = Vec3d::Zero();
|
||||||
m_rotation = Vec3d::Zero();
|
m_rotation = Vec3d::Zero();
|
||||||
m_scaling_factor = Vec3d::Ones();
|
m_scaling_factor = Vec3d::Ones();
|
||||||
m_mirror = Vec3d::Ones();
|
m_mirror = Vec3d::Ones();
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
m_matrix = Transform3d::Identity();
|
m_matrix = Transform3d::Identity();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void Transformation::reset_skew()
|
||||||
|
{
|
||||||
|
Matrix3d rotation;
|
||||||
|
Matrix3d scale;
|
||||||
|
m_matrix.computeRotationScaling(&rotation, &scale);
|
||||||
|
|
||||||
|
const double average_scale = std::cbrt(scale(0, 0) * scale(1, 1) * scale(2, 2));
|
||||||
|
|
||||||
|
scale(0, 0) = average_scale;
|
||||||
|
scale(1, 1) = average_scale;
|
||||||
|
scale(2, 2) = average_scale;
|
||||||
|
|
||||||
|
scale(0, 1) = 0.0;
|
||||||
|
scale(0, 2) = 0.0;
|
||||||
|
scale(1, 0) = 0.0;
|
||||||
|
scale(1, 2) = 0.0;
|
||||||
|
scale(2, 0) = 0.0;
|
||||||
|
scale(2, 1) = 0.0;
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation * scale;
|
||||||
|
m_matrix.translation() = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_matrix_no_offset() const
|
||||||
|
{
|
||||||
|
Transformation copy(*this);
|
||||||
|
copy.reset_offset();
|
||||||
|
return copy.get_matrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_matrix_no_scaling_factor() const
|
||||||
|
{
|
||||||
|
Transformation copy(*this);
|
||||||
|
copy.reset_scaling_factor();
|
||||||
|
copy.reset_mirror();
|
||||||
|
return copy.get_matrix();
|
||||||
|
}
|
||||||
|
#else
|
||||||
const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
|
const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
|
||||||
{
|
{
|
||||||
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) {
|
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) {
|
||||||
@ -520,12 +757,14 @@ const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rot
|
|||||||
|
|
||||||
return m_matrix;
|
return m_matrix;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
Transformation Transformation::operator * (const Transformation& other) const
|
Transformation Transformation::operator * (const Transformation& other) const
|
||||||
{
|
{
|
||||||
return Transformation(get_matrix() * other.get_matrix());
|
return Transformation(get_matrix() * other.get_matrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
Transformation Transformation::volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox)
|
Transformation Transformation::volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox)
|
||||||
{
|
{
|
||||||
Transformation out;
|
Transformation out;
|
||||||
@ -571,8 +810,7 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
|
|||||||
out.set_scaling_factor(Vec3d(std::abs(scale.x()), std::abs(scale.y()), std::abs(scale.z())));
|
out.set_scaling_factor(Vec3d(std::abs(scale.x()), std::abs(scale.y()), std::abs(scale.z())));
|
||||||
out.set_mirror(Vec3d(scale.x() > 0 ? 1. : -1, scale.y() > 0 ? 1. : -1, scale.z() > 0 ? 1. : -1));
|
out.set_mirror(Vec3d(scale.x() > 0 ? 1. : -1, scale.y() > 0 ? 1. : -1, scale.z() > 0 ? 1. : -1));
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// General anisotropic scaling, general rotation.
|
// General anisotropic scaling, general rotation.
|
||||||
// Keep the modifier mesh in the instance coordinate system, so the modifier mesh will not be aligned with the world.
|
// Keep the modifier mesh in the instance coordinate system, so the modifier mesh will not be aligned with the world.
|
||||||
// Scale it to get the required size.
|
// Scale it to get the required size.
|
||||||
@ -581,6 +819,7 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// For parsing a transformation matrix from 3MF / AMF.
|
// For parsing a transformation matrix from 3MF / AMF.
|
||||||
Transform3d transform3d_from_string(const std::string& transform_str)
|
Transform3d transform3d_from_string(const std::string& transform_str)
|
||||||
@ -619,7 +858,7 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
|
|||||||
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||||
{
|
{
|
||||||
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||||
const Vec3d axis = angle_axis.axis();
|
const Vec3d& axis = angle_axis.axis();
|
||||||
const double angle = angle_axis.angle();
|
const double angle = angle_axis.angle();
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (std::abs(angle) > 1e-8) {
|
if (std::abs(angle) > 1e-8) {
|
||||||
|
@ -323,7 +323,8 @@ bool arrange(
|
|||||||
// 4) rotate Y
|
// 4) rotate Y
|
||||||
// 5) rotate Z
|
// 5) rotate Z
|
||||||
// 6) translate
|
// 6) translate
|
||||||
void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
|
void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(),
|
||||||
|
const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
|
||||||
|
|
||||||
// Returns the transform obtained by assembling the given transformations in the following order:
|
// Returns the transform obtained by assembling the given transformations in the following order:
|
||||||
// 1) mirror
|
// 1) mirror
|
||||||
@ -332,7 +333,43 @@ void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d
|
|||||||
// 4) rotate Y
|
// 4) rotate Y
|
||||||
// 5) rotate Z
|
// 5) rotate Z
|
||||||
// 6) translate
|
// 6) translate
|
||||||
Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
|
Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(),
|
||||||
|
const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
|
||||||
|
|
||||||
|
// Sets the given transform by multiplying the given transformations in the following order:
|
||||||
|
// T = translation * rotation * scale * mirror
|
||||||
|
void assemble_transform(Transform3d& transform, const Transform3d& translation = Transform3d::Identity(),
|
||||||
|
const Transform3d& rotation = Transform3d::Identity(), const Transform3d& scale = Transform3d::Identity(),
|
||||||
|
const Transform3d& mirror = Transform3d::Identity());
|
||||||
|
|
||||||
|
// Returns the transform obtained by multiplying the given transformations in the following order:
|
||||||
|
// T = translation * rotation * scale * mirror
|
||||||
|
Transform3d assemble_transform(const Transform3d& translation = Transform3d::Identity(), const Transform3d& rotation = Transform3d::Identity(),
|
||||||
|
const Transform3d& scale = Transform3d::Identity(), const Transform3d& mirror = Transform3d::Identity());
|
||||||
|
|
||||||
|
// Sets the given transform by assembling the given translation
|
||||||
|
void translation_transform(Transform3d& transform, const Vec3d& translation);
|
||||||
|
|
||||||
|
// Returns the transform obtained by assembling the given translation
|
||||||
|
Transform3d translation_transform(const Vec3d& translation);
|
||||||
|
|
||||||
|
// Sets the given transform by assembling the given rotations in the following order:
|
||||||
|
// 1) rotate X
|
||||||
|
// 2) rotate Y
|
||||||
|
// 3) rotate Z
|
||||||
|
void rotation_transform(Transform3d& transform, const Vec3d& rotation);
|
||||||
|
|
||||||
|
// Returns the transform obtained by assembling the given rotations in the following order:
|
||||||
|
// 1) rotate X
|
||||||
|
// 2) rotate Y
|
||||||
|
// 3) rotate Z
|
||||||
|
Transform3d rotation_transform(const Vec3d& rotation);
|
||||||
|
|
||||||
|
// Sets the given transform by assembling the given scale factors
|
||||||
|
void scale_transform(Transform3d& transform, const Vec3d& scale);
|
||||||
|
|
||||||
|
// Returns the transform obtained by assembling the given scale factors
|
||||||
|
Transform3d scale_transform(const Vec3d& scale);
|
||||||
|
|
||||||
// Returns the euler angles extracted from the given rotation matrix
|
// Returns the euler angles extracted from the given rotation matrix
|
||||||
// Warning -> The matrix should not contain any scale or shear !!!
|
// Warning -> The matrix should not contain any scale or shear !!!
|
||||||
@ -344,6 +381,9 @@ Vec3d extract_euler_angles(const Transform3d& transform);
|
|||||||
|
|
||||||
class Transformation
|
class Transformation
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Transform3d m_matrix{ Transform3d::Identity() };
|
||||||
|
#else
|
||||||
struct Flags
|
struct Flags
|
||||||
{
|
{
|
||||||
bool dont_translate{ true };
|
bool dont_translate{ true };
|
||||||
@ -363,8 +403,26 @@ class Transformation
|
|||||||
mutable Transform3d m_matrix{ Transform3d::Identity() };
|
mutable Transform3d m_matrix{ Transform3d::Identity() };
|
||||||
mutable Flags m_flags;
|
mutable Flags m_flags;
|
||||||
mutable bool m_dirty{ false };
|
mutable bool m_dirty{ false };
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Transformation() = default;
|
||||||
|
explicit Transformation(const Transform3d& transform) : m_matrix(transform) {}
|
||||||
|
|
||||||
|
Vec3d get_offset() const { return m_matrix.translation(); }
|
||||||
|
double get_offset(Axis axis) const { return get_offset()[axis]; }
|
||||||
|
|
||||||
|
Transform3d get_offset_matrix() const;
|
||||||
|
|
||||||
|
void set_offset(const Vec3d& offset) { m_matrix.translation() = offset; }
|
||||||
|
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
|
||||||
|
|
||||||
|
Vec3d get_rotation() const;
|
||||||
|
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
|
||||||
|
|
||||||
|
Transform3d get_rotation_matrix() const;
|
||||||
|
#else
|
||||||
Transformation();
|
Transformation();
|
||||||
explicit Transformation(const Transform3d& transform);
|
explicit Transformation(const Transform3d& transform);
|
||||||
|
|
||||||
@ -376,47 +434,103 @@ public:
|
|||||||
|
|
||||||
const Vec3d& get_rotation() const { return m_rotation; }
|
const Vec3d& get_rotation() const { return m_rotation; }
|
||||||
double get_rotation(Axis axis) const { return m_rotation(axis); }
|
double get_rotation(Axis axis) const { return m_rotation(axis); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void set_rotation(const Vec3d& rotation);
|
void set_rotation(const Vec3d& rotation);
|
||||||
void set_rotation(Axis axis, double rotation);
|
void set_rotation(Axis axis, double rotation);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_scaling_factor() const;
|
||||||
|
double get_scaling_factor(Axis axis) const { return get_scaling_factor()[axis]; }
|
||||||
|
|
||||||
|
Transform3d get_scaling_factor_matrix() const;
|
||||||
|
|
||||||
|
bool is_scaling_uniform() const {
|
||||||
|
const Vec3d scale = get_scaling_factor();
|
||||||
|
return std::abs(scale.x() - scale.y()) < 1e-8 && std::abs(scale.x() - scale.z()) < 1e-8;
|
||||||
|
}
|
||||||
|
#else
|
||||||
const Vec3d& get_scaling_factor() const { return m_scaling_factor; }
|
const Vec3d& get_scaling_factor() const { return m_scaling_factor; }
|
||||||
double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); }
|
double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void set_scaling_factor(const Vec3d& scaling_factor);
|
void set_scaling_factor(const Vec3d& scaling_factor);
|
||||||
void set_scaling_factor(Axis axis, double scaling_factor);
|
void set_scaling_factor(Axis axis, double scaling_factor);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_mirror() const;
|
||||||
|
double get_mirror(Axis axis) const { return get_mirror()[axis]; }
|
||||||
|
|
||||||
|
Transform3d get_mirror_matrix() const;
|
||||||
|
|
||||||
|
bool is_left_handed() const {
|
||||||
|
const Vec3d mirror = get_mirror();
|
||||||
|
return mirror.x() * mirror.y() * mirror.z() < 0.0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
|
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
|
||||||
|
|
||||||
const Vec3d& get_mirror() const { return m_mirror; }
|
const Vec3d& get_mirror() const { return m_mirror; }
|
||||||
double get_mirror(Axis axis) const { return m_mirror(axis); }
|
double get_mirror(Axis axis) const { return m_mirror(axis); }
|
||||||
bool is_left_handed() const { return m_mirror.x() * m_mirror.y() * m_mirror.z() < 0.; }
|
bool is_left_handed() const { return m_mirror.x() * m_mirror.y() * m_mirror.z() < 0.; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void set_mirror(const Vec3d& mirror);
|
void set_mirror(const Vec3d& mirror);
|
||||||
void set_mirror(Axis axis, double mirror);
|
void set_mirror(Axis axis, double mirror);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
bool has_skew() const;
|
||||||
|
#else
|
||||||
void set_from_transform(const Transform3d& transform);
|
void set_from_transform(const Transform3d& transform);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void reset_offset() { set_offset(Vec3d::Zero()); }
|
||||||
|
void reset_rotation() { set_rotation(Vec3d::Zero()); }
|
||||||
|
void reset_scaling_factor() { set_scaling_factor(Vec3d::Ones()); }
|
||||||
|
void reset_mirror() { set_mirror(Vec3d::Ones()); }
|
||||||
|
void reset_skew();
|
||||||
|
|
||||||
|
const Transform3d& get_matrix() const { return m_matrix; }
|
||||||
|
Transform3d get_matrix_no_offset() const;
|
||||||
|
Transform3d get_matrix_no_scaling_factor() const;
|
||||||
|
|
||||||
|
void set_matrix(const Transform3d& transform) { m_matrix = transform; }
|
||||||
|
#else
|
||||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
|
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
Transformation operator * (const Transformation& other) const;
|
Transformation operator * (const Transformation& other) const;
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
// Find volume transformation, so that the chained (instance_trafo * volume_trafo) will be as close to identity
|
// Find volume transformation, so that the chained (instance_trafo * volume_trafo) will be as close to identity
|
||||||
// as possible in least squares norm in regard to the 8 corners of bbox.
|
// as possible in least squares norm in regard to the 8 corners of bbox.
|
||||||
// Bounding box is expected to be centered around zero in all axes.
|
// Bounding box is expected to be centered around zero in all axes.
|
||||||
static Transformation volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox);
|
static Transformation volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox);
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class cereal::access;
|
friend class cereal::access;
|
||||||
template<class Archive> void serialize(Archive & ar) { ar(m_offset, m_rotation, m_scaling_factor, m_mirror); }
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
template<class Archive> void serialize(Archive& ar) { ar(m_matrix); }
|
||||||
|
explicit Transformation(int) {}
|
||||||
|
template <class Archive> static void load_and_construct(Archive& ar, cereal::construct<Transformation>& construct)
|
||||||
|
{
|
||||||
|
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
|
||||||
|
construct(1);
|
||||||
|
ar(construct.ptr()->m_matrix);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class Archive> void serialize(Archive& ar) { ar(m_offset, m_rotation, m_scaling_factor, m_mirror); }
|
||||||
explicit Transformation(int) : m_dirty(true) {}
|
explicit Transformation(int) : m_dirty(true) {}
|
||||||
template <class Archive> static void load_and_construct(Archive &ar, cereal::construct<Transformation> &construct)
|
template <class Archive> static void load_and_construct(Archive& ar, cereal::construct<Transformation>& construct)
|
||||||
{
|
{
|
||||||
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
|
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
|
||||||
construct(1);
|
construct(1);
|
||||||
ar(construct.ptr()->m_offset, construct.ptr()->m_rotation, construct.ptr()->m_scaling_factor, construct.ptr()->m_mirror);
|
ar(construct.ptr()->m_offset, construct.ptr()->m_rotation, construct.ptr()->m_scaling_factor, construct.ptr()->m_mirror);
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
// For parsing a transformation matrix from 3MF / AMF.
|
// For parsing a transformation matrix from 3MF / AMF.
|
||||||
|
@ -945,7 +945,11 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
|
|||||||
if (this->instances.empty())
|
if (this->instances.empty())
|
||||||
throw Slic3r::InvalidArgument("Can't call raw_bounding_box() with no instances");
|
throw Slic3r::InvalidArgument("Can't call raw_bounding_box() with no instances");
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d inst_matrix = this->instances.front()->get_transformation().get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
|
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
for (const ModelVolume *v : this->volumes)
|
for (const ModelVolume *v : this->volumes)
|
||||||
if (v->is_model_part())
|
if (v->is_model_part())
|
||||||
m_raw_bounding_box.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
|
m_raw_bounding_box.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||||
@ -957,9 +961,15 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
|
|||||||
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
|
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
|
||||||
{
|
{
|
||||||
BoundingBoxf3 bb;
|
BoundingBoxf3 bb;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d inst_matrix = dont_translate ?
|
||||||
|
this->instances[instance_idx]->get_transformation().get_matrix_no_offset() :
|
||||||
|
this->instances[instance_idx]->get_transformation().get_matrix();
|
||||||
|
|
||||||
|
#else
|
||||||
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
|
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
|
||||||
for (ModelVolume *v : this->volumes)
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
{
|
for (ModelVolume *v : this->volumes) {
|
||||||
if (v->is_model_part())
|
if (v->is_model_part())
|
||||||
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
|
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||||
}
|
}
|
||||||
@ -1368,9 +1378,12 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||||||
new_object->add_instance(*model_instance);
|
new_object->add_instance(*model_instance);
|
||||||
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(mesh));
|
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(mesh));
|
||||||
|
|
||||||
for (ModelInstance* model_instance : new_object->instances)
|
for (ModelInstance* model_instance : new_object->instances) {
|
||||||
{
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d shift = model_instance->get_transformation().get_matrix_no_offset() * new_vol->get_offset();
|
||||||
|
#else
|
||||||
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
|
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
model_instance->set_offset(model_instance->get_offset() + shift);
|
model_instance->set_offset(model_instance->get_offset() + shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1412,9 +1425,11 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
|
|||||||
assert(instance_idx < this->instances.size());
|
assert(instance_idx < this->instances.size());
|
||||||
|
|
||||||
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
|
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
|
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
|
||||||
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
|
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
|
||||||
return;
|
return;
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
bool left_handed = reference_trafo.is_left_handed();
|
bool left_handed = reference_trafo.is_left_handed();
|
||||||
bool has_mirrorring = ! reference_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.));
|
bool has_mirrorring = ! reference_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.));
|
||||||
@ -1432,7 +1447,17 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
|
|||||||
|
|
||||||
// Adjust the meshes.
|
// Adjust the meshes.
|
||||||
// Transformation to be applied to the meshes.
|
// Transformation to be applied to the meshes.
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Geometry::Transformation reference_trafo_mod = reference_trafo;
|
||||||
|
reference_trafo_mod.reset_offset();
|
||||||
|
if (uniform_scaling)
|
||||||
|
reference_trafo_mod.reset_scaling_factor();
|
||||||
|
if (!has_mirrorring)
|
||||||
|
reference_trafo_mod.reset_mirror();
|
||||||
|
Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo_mod.get_matrix().matrix().block<3, 3>(0, 0);
|
||||||
|
#else
|
||||||
Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo.get_matrix(true, false, uniform_scaling, ! has_mirrorring).matrix().block<3, 3>(0, 0);
|
Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo.get_matrix(true, false, uniform_scaling, ! has_mirrorring).matrix().block<3, 3>(0, 0);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
Transform3d volume_offset_correction = this->instances[instance_idx]->get_transformation().get_matrix().inverse() * reference_trafo.get_matrix();
|
Transform3d volume_offset_correction = this->instances[instance_idx]->get_transformation().get_matrix().inverse() * reference_trafo.get_matrix();
|
||||||
for (ModelVolume *model_volume : this->volumes) {
|
for (ModelVolume *model_volume : this->volumes) {
|
||||||
const Geometry::Transformation volume_trafo = model_volume->get_transformation();
|
const Geometry::Transformation volume_trafo = model_volume->get_transformation();
|
||||||
@ -1442,7 +1467,17 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
|
|||||||
std::abs(volume_trafo.get_scaling_factor().x() - volume_trafo.get_scaling_factor().z()) < EPSILON;
|
std::abs(volume_trafo.get_scaling_factor().x() - volume_trafo.get_scaling_factor().z()) < EPSILON;
|
||||||
double volume_new_scaling_factor = volume_uniform_scaling ? volume_trafo.get_scaling_factor().x() : 1.;
|
double volume_new_scaling_factor = volume_uniform_scaling ? volume_trafo.get_scaling_factor().x() : 1.;
|
||||||
// Transform the mesh.
|
// Transform the mesh.
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Geometry::Transformation volume_trafo_mod = volume_trafo;
|
||||||
|
volume_trafo_mod.reset_offset();
|
||||||
|
if (volume_uniform_scaling)
|
||||||
|
volume_trafo_mod.reset_scaling_factor();
|
||||||
|
if (!volume_has_mirrorring)
|
||||||
|
volume_trafo_mod.reset_mirror();
|
||||||
|
Eigen::Matrix3d volume_trafo_3x3 = volume_trafo_mod.get_matrix().matrix().block<3, 3>(0, 0);
|
||||||
|
#else
|
||||||
Matrix3d volume_trafo_3x3 = volume_trafo.get_matrix(true, false, volume_uniform_scaling, !volume_has_mirrorring).matrix().block<3, 3>(0, 0);
|
Matrix3d volume_trafo_3x3 = volume_trafo.get_matrix(true, false, volume_uniform_scaling, !volume_has_mirrorring).matrix().block<3, 3>(0, 0);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// Following method creates a new shared_ptr<TriangleMesh>
|
// Following method creates a new shared_ptr<TriangleMesh>
|
||||||
model_volume->transform_this_mesh(mesh_trafo_3x3 * volume_trafo_3x3, left_handed != volume_left_handed);
|
model_volume->transform_this_mesh(mesh_trafo_3x3 * volume_trafo_3x3, left_handed != volume_left_handed);
|
||||||
// Reset the rotation, scaling and mirroring.
|
// Reset the rotation, scaling and mirroring.
|
||||||
@ -1489,7 +1524,11 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
|
|||||||
double min_z = DBL_MAX;
|
double min_z = DBL_MAX;
|
||||||
|
|
||||||
const ModelInstance* inst = instances[instance_idx];
|
const ModelInstance* inst = instances[instance_idx];
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d mi = inst->get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d& mi = inst->get_matrix(true);
|
const Transform3d& mi = inst->get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
for (const ModelVolume* v : volumes) {
|
for (const ModelVolume* v : volumes) {
|
||||||
if (!v->is_model_part())
|
if (!v->is_model_part())
|
||||||
@ -1510,7 +1549,11 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
|
|||||||
double max_z = -DBL_MAX;
|
double max_z = -DBL_MAX;
|
||||||
|
|
||||||
const ModelInstance* inst = instances[instance_idx];
|
const ModelInstance* inst = instances[instance_idx];
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d mi = inst->get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d& mi = inst->get_matrix(true);
|
const Transform3d& mi = inst->get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
for (const ModelVolume* v : volumes) {
|
for (const ModelVolume* v : volumes) {
|
||||||
if (!v->is_model_part())
|
if (!v->is_model_part())
|
||||||
@ -1936,14 +1979,22 @@ void ModelVolume::convert_from_meters()
|
|||||||
|
|
||||||
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
mesh->transform(dont_translate ? get_matrix_no_offset() : get_matrix());
|
||||||
|
#else
|
||||||
mesh->transform(get_matrix(dont_translate));
|
mesh->transform(get_matrix(dont_translate));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate) const
|
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate) const
|
||||||
{
|
{
|
||||||
// Rotate around mesh origin.
|
// Rotate around mesh origin.
|
||||||
TriangleMesh copy(mesh);
|
TriangleMesh copy(mesh);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
copy.transform(get_transformation().get_rotation_matrix());
|
||||||
|
#else
|
||||||
copy.transform(get_matrix(true, false, true, true));
|
copy.transform(get_matrix(true, false, true, true));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
BoundingBoxf3 bbox = copy.bounding_box();
|
BoundingBoxf3 bbox = copy.bounding_box();
|
||||||
|
|
||||||
if (!empty(bbox)) {
|
if (!empty(bbox)) {
|
||||||
@ -1968,12 +2019,20 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mes
|
|||||||
|
|
||||||
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
|
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
return bbox.transformed(dont_translate ? get_matrix_no_offset() : get_matrix());
|
||||||
|
#else
|
||||||
return bbox.transformed(get_matrix(dont_translate));
|
return bbox.transformed(get_matrix(dont_translate));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const
|
Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
return dont_translate ? get_matrix_no_offset() * v : get_matrix() * v;
|
||||||
|
#else
|
||||||
return get_matrix(dont_translate) * v;
|
return get_matrix(dont_translate) * v;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelInstance::transform_polygon(Polygon* polygon) const
|
void ModelInstance::transform_polygon(Polygon* polygon) const
|
||||||
|
@ -691,15 +691,26 @@ public:
|
|||||||
|
|
||||||
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
||||||
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_transformation(const Transform3d& trafo) { m_transformation.set_matrix(trafo); }
|
||||||
|
|
||||||
|
Vec3d get_offset() const { return m_transformation.get_offset(); }
|
||||||
|
#else
|
||||||
void set_transformation(const Transform3d &trafo) { m_transformation.set_from_transform(trafo); }
|
void set_transformation(const Transform3d &trafo) { m_transformation.set_from_transform(trafo); }
|
||||||
|
|
||||||
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
||||||
|
|
||||||
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
||||||
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
||||||
|
|
||||||
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
||||||
@ -711,7 +722,11 @@ public:
|
|||||||
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
||||||
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||||
|
|
||||||
@ -720,7 +735,12 @@ public:
|
|||||||
void convert_from_imperial_units();
|
void convert_from_imperial_units();
|
||||||
void convert_from_meters();
|
void convert_from_meters();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
||||||
|
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
||||||
|
#else
|
||||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void set_new_unique_id() {
|
void set_new_unique_id() {
|
||||||
ObjectBase::set_new_unique_id();
|
ObjectBase::set_new_unique_id();
|
||||||
@ -923,25 +943,41 @@ public:
|
|||||||
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
||||||
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_offset() const { return m_transformation.get_offset(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
||||||
|
|
||||||
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
||||||
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
||||||
|
|
||||||
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
||||||
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); }
|
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
const Vec3d& get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
|
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
|
||||||
|
|
||||||
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
||||||
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||||
|
|
||||||
@ -959,7 +995,12 @@ public:
|
|||||||
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
|
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
|
||||||
void transform_polygon(Polygon* polygon) const;
|
void transform_polygon(Polygon* polygon) const;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
||||||
|
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
||||||
|
#else
|
||||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
||||||
|
|
||||||
|
@ -545,6 +545,10 @@ namespace cereal {
|
|||||||
|
|
||||||
template<class Archive> void load(Archive& archive, Slic3r::Matrix2f &m) { archive.loadBinary((char*)m.data(), sizeof(float) * 4); }
|
template<class Archive> void load(Archive& archive, Slic3r::Matrix2f &m) { archive.loadBinary((char*)m.data(), sizeof(float) * 4); }
|
||||||
template<class Archive> void save(Archive& archive, Slic3r::Matrix2f &m) { archive.saveBinary((char*)m.data(), sizeof(float) * 4); }
|
template<class Archive> void save(Archive& archive, Slic3r::Matrix2f &m) { archive.saveBinary((char*)m.data(), sizeof(float) * 4); }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
template<class Archive> void load(Archive& archive, Slic3r::Transform3d& m) { archive.loadBinary((char*)m.data(), sizeof(double) * 16); }
|
||||||
|
template<class Archive> void save(Archive& archive, const Slic3r::Transform3d& m) { archive.saveBinary((char*)m.data(), sizeof(double) * 16); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be able to use Vec<> and Mat<> in range based for loops:
|
// To be able to use Vec<> and Mat<> in range based for loops:
|
||||||
|
@ -790,8 +790,13 @@ void update_volume_bboxes(
|
|||||||
if (it != volumes_old.end() && it->volume_id == model_volume->id())
|
if (it != volumes_old.end() && it->volume_id == model_volume->id())
|
||||||
layer_range.volumes.emplace_back(*it);
|
layer_range.volumes.emplace_back(*it);
|
||||||
} else
|
} else
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
layer_range.volumes.push_back({ model_volume->id(),
|
||||||
|
transformed_its_bbox2d(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix()), offset) });
|
||||||
|
#else
|
||||||
layer_range.volumes.push_back({ model_volume->id(),
|
layer_range.volumes.push_back({ model_volume->id(),
|
||||||
transformed_its_bbox2d(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), offset) });
|
transformed_its_bbox2d(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), offset) });
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::vector<std::vector<PrintObjectRegions::VolumeExtents>> volumes_old;
|
std::vector<std::vector<PrintObjectRegions::VolumeExtents>> volumes_old;
|
||||||
@ -823,7 +828,11 @@ void update_volume_bboxes(
|
|||||||
layer_range.volumes.emplace_back(*it);
|
layer_range.volumes.emplace_back(*it);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
transformed_its_bboxes_in_z_ranges(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix()), ranges, bboxes, offset);
|
||||||
|
#else
|
||||||
transformed_its_bboxes_in_z_ranges(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), ranges, bboxes, offset);
|
transformed_its_bboxes_in_z_ranges(model_volume->mesh().its, trafo_for_bbox(object_trafo, model_volume->get_matrix(false)), ranges, bboxes, offset);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges)
|
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges)
|
||||||
if (auto &bbox = bboxes[&layer_range - layer_ranges.data()]; bbox.second)
|
if (auto &bbox = bboxes[&layer_range - layer_ranges.data()]; bbox.second)
|
||||||
layer_range.volumes.push_back({ model_volume->id(), bbox.first });
|
layer_range.volumes.push_back({ model_volume->id(), bbox.first });
|
||||||
|
@ -69,6 +69,8 @@
|
|||||||
#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
// Enable recalculating toolpaths when switching to/from volumetric rate visualization
|
// Enable recalculating toolpaths when switching to/from volumetric rate visualization
|
||||||
#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
// Enable editing volumes transformation in world coordinates and instances in local coordinates
|
||||||
|
#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
// Enable modified camera control using mouse
|
// Enable modified camera control using mouse
|
||||||
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
// Enable modified rectangle selection
|
// Enable modified rectangle selection
|
||||||
|
@ -85,6 +85,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/GUI_App.hpp
|
GUI/GUI_App.hpp
|
||||||
GUI/GUI_Utils.cpp
|
GUI/GUI_Utils.cpp
|
||||||
GUI/GUI_Utils.hpp
|
GUI/GUI_Utils.hpp
|
||||||
|
GUI/GUI_Geometry.cpp
|
||||||
|
GUI/GUI_Geometry.hpp
|
||||||
GUI/I18N.cpp
|
GUI/I18N.cpp
|
||||||
GUI/I18N.hpp
|
GUI/I18N.hpp
|
||||||
GUI/MainFrame.cpp
|
GUI/MainFrame.cpp
|
||||||
@ -129,6 +131,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/2DBed.hpp
|
GUI/2DBed.hpp
|
||||||
GUI/3DBed.cpp
|
GUI/3DBed.cpp
|
||||||
GUI/3DBed.hpp
|
GUI/3DBed.hpp
|
||||||
|
GUI/CoordAxes.cpp
|
||||||
|
GUI/CoordAxes.hpp
|
||||||
GUI/Camera.cpp
|
GUI/Camera.cpp
|
||||||
GUI/Camera.hpp
|
GUI/Camera.hpp
|
||||||
GUI/wxExtensions.cpp
|
GUI/wxExtensions.cpp
|
||||||
|
@ -102,6 +102,7 @@ const float* GeometryBuffer::get_vertices_data() const
|
|||||||
}
|
}
|
||||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
|
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
|
||||||
const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
||||||
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
|
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
|
||||||
@ -179,6 +180,7 @@ void Bed3D::Axes::render()
|
|||||||
|
|
||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom)
|
bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom)
|
||||||
{
|
{
|
||||||
@ -341,7 +343,11 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box() const
|
|||||||
out.max.z() = 0.0;
|
out.max.z() = 0.0;
|
||||||
// extend to contain axes
|
// extend to contain axes
|
||||||
out.merge(m_axes.get_origin() + m_axes.get_total_length() * Vec3d::Ones());
|
out.merge(m_axes.get_origin() + m_axes.get_total_length() * Vec3d::Ones());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
out.merge(out.min + Vec3d(-m_axes.get_tip_radius(), -m_axes.get_tip_radius(), out.max.z()));
|
||||||
|
#else
|
||||||
out.merge(out.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, out.max.z()));
|
out.merge(out.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, out.max.z()));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// extend to contain model, if any
|
// extend to contain model, if any
|
||||||
BoundingBoxf3 model_bb = m_model.get_bounding_box();
|
BoundingBoxf3 model_bb = m_model.get_bounding_box();
|
||||||
if (model_bb.defined) {
|
if (model_bb.defined) {
|
||||||
@ -539,7 +545,15 @@ std::tuple<Bed3D::Type, std::string, std::string> Bed3D::detect_type(const Point
|
|||||||
void Bed3D::render_axes()
|
void Bed3D::render_axes()
|
||||||
{
|
{
|
||||||
if (m_build_volume.valid())
|
if (m_build_volume.valid())
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
m_axes.render(Transform3d::Identity(), 0.25f);
|
||||||
|
#else
|
||||||
|
m_axes.render(0.25f);
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#else
|
||||||
m_axes.render();
|
m_axes.render();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
#include "GLTexture.hpp"
|
#include "GLTexture.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "CoordAxes.hpp"
|
||||||
|
#else
|
||||||
#include "GLModel.hpp"
|
#include "GLModel.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#include "libslic3r/BuildVolume.hpp"
|
#include "libslic3r/BuildVolume.hpp"
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
@ -44,6 +48,7 @@ public:
|
|||||||
|
|
||||||
class Bed3D
|
class Bed3D
|
||||||
{
|
{
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
class Axes
|
class Axes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -67,6 +72,7 @@ class Bed3D
|
|||||||
float get_total_length() const { return m_stem_length + DefaultTipLength; }
|
float get_total_length() const { return m_stem_length + DefaultTipLength; }
|
||||||
void render();
|
void render();
|
||||||
};
|
};
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Type : unsigned char
|
enum class Type : unsigned char
|
||||||
@ -107,7 +113,11 @@ private:
|
|||||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
unsigned int m_vbo_id{ 0 };
|
unsigned int m_vbo_id{ 0 };
|
||||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
CoordAxes m_axes;
|
||||||
|
#else
|
||||||
Axes m_axes;
|
Axes m_axes;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
float m_scale_factor{ 1.0f };
|
float m_scale_factor{ 1.0f };
|
||||||
|
|
||||||
|
@ -432,14 +432,23 @@ public:
|
|||||||
|
|
||||||
const Geometry::Transformation& get_instance_transformation() const { return m_instance_transformation; }
|
const Geometry::Transformation& get_instance_transformation() const { return m_instance_transformation; }
|
||||||
void set_instance_transformation(const Geometry::Transformation& transformation) { m_instance_transformation = transformation; set_bounding_boxes_as_dirty(); }
|
void set_instance_transformation(const Geometry::Transformation& transformation) { m_instance_transformation = transformation; set_bounding_boxes_as_dirty(); }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_instance_transformation(const Transform3d& transform) { m_instance_transformation.set_matrix(transform); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
Vec3d get_instance_offset() const { return m_instance_transformation.get_offset(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_instance_offset() const { return m_instance_transformation.get_offset(); }
|
const Vec3d& get_instance_offset() const { return m_instance_transformation.get_offset(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_instance_offset(Axis axis) const { return m_instance_transformation.get_offset(axis); }
|
double get_instance_offset(Axis axis) const { return m_instance_transformation.get_offset(axis); }
|
||||||
|
|
||||||
void set_instance_offset(const Vec3d& offset) { m_instance_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); }
|
void set_instance_offset(const Vec3d& offset) { m_instance_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); }
|
||||||
void set_instance_offset(Axis axis, double offset) { m_instance_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); }
|
void set_instance_offset(Axis axis, double offset) { m_instance_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_instance_rotation() const { return m_instance_transformation.get_rotation(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_instance_rotation() const { return m_instance_transformation.get_rotation(); }
|
const Vec3d& get_instance_rotation() const { return m_instance_transformation.get_rotation(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_instance_rotation(Axis axis) const { return m_instance_transformation.get_rotation(axis); }
|
double get_instance_rotation(Axis axis) const { return m_instance_transformation.get_rotation(axis); }
|
||||||
|
|
||||||
void set_instance_rotation(const Vec3d& rotation) { m_instance_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
|
void set_instance_rotation(const Vec3d& rotation) { m_instance_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
|
||||||
@ -451,7 +460,11 @@ public:
|
|||||||
void set_instance_scaling_factor(const Vec3d& scaling_factor) { m_instance_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }
|
void set_instance_scaling_factor(const Vec3d& scaling_factor) { m_instance_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }
|
||||||
void set_instance_scaling_factor(Axis axis, double scaling_factor) { m_instance_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); }
|
void set_instance_scaling_factor(Axis axis, double scaling_factor) { m_instance_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_instance_mirror() const { return m_instance_transformation.get_mirror(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_instance_mirror() const { return m_instance_transformation.get_mirror(); }
|
const Vec3d& get_instance_mirror() const { return m_instance_transformation.get_mirror(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_instance_mirror(Axis axis) const { return m_instance_transformation.get_mirror(axis); }
|
double get_instance_mirror(Axis axis) const { return m_instance_transformation.get_mirror(axis); }
|
||||||
|
|
||||||
void set_instance_mirror(const Vec3d& mirror) { m_instance_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); }
|
void set_instance_mirror(const Vec3d& mirror) { m_instance_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); }
|
||||||
@ -459,26 +472,43 @@ public:
|
|||||||
|
|
||||||
const Geometry::Transformation& get_volume_transformation() const { return m_volume_transformation; }
|
const Geometry::Transformation& get_volume_transformation() const { return m_volume_transformation; }
|
||||||
void set_volume_transformation(const Geometry::Transformation& transformation) { m_volume_transformation = transformation; set_bounding_boxes_as_dirty(); }
|
void set_volume_transformation(const Geometry::Transformation& transformation) { m_volume_transformation = transformation; set_bounding_boxes_as_dirty(); }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_volume_transformation(const Transform3d& transform) { m_volume_transformation.set_matrix(transform); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
Vec3d get_volume_offset() const { return m_volume_transformation.get_offset(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_volume_offset() const { return m_volume_transformation.get_offset(); }
|
const Vec3d& get_volume_offset() const { return m_volume_transformation.get_offset(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_volume_offset(Axis axis) const { return m_volume_transformation.get_offset(axis); }
|
double get_volume_offset(Axis axis) const { return m_volume_transformation.get_offset(axis); }
|
||||||
|
|
||||||
void set_volume_offset(const Vec3d& offset) { m_volume_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); }
|
void set_volume_offset(const Vec3d& offset) { m_volume_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); }
|
||||||
void set_volume_offset(Axis axis, double offset) { m_volume_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); }
|
void set_volume_offset(Axis axis, double offset) { m_volume_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_volume_rotation() const { return m_volume_transformation.get_rotation(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_volume_rotation() const { return m_volume_transformation.get_rotation(); }
|
const Vec3d& get_volume_rotation() const { return m_volume_transformation.get_rotation(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_volume_rotation(Axis axis) const { return m_volume_transformation.get_rotation(axis); }
|
double get_volume_rotation(Axis axis) const { return m_volume_transformation.get_rotation(axis); }
|
||||||
|
|
||||||
void set_volume_rotation(const Vec3d& rotation) { m_volume_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
|
void set_volume_rotation(const Vec3d& rotation) { m_volume_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
|
||||||
void set_volume_rotation(Axis axis, double rotation) { m_volume_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); }
|
void set_volume_rotation(Axis axis, double rotation) { m_volume_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); }
|
const Vec3d& get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_volume_scaling_factor(Axis axis) const { return m_volume_transformation.get_scaling_factor(axis); }
|
double get_volume_scaling_factor(Axis axis) const { return m_volume_transformation.get_scaling_factor(axis); }
|
||||||
|
|
||||||
void set_volume_scaling_factor(const Vec3d& scaling_factor) { m_volume_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }
|
void set_volume_scaling_factor(const Vec3d& scaling_factor) { m_volume_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }
|
||||||
void set_volume_scaling_factor(Axis axis, double scaling_factor) { m_volume_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); }
|
void set_volume_scaling_factor(Axis axis, double scaling_factor) { m_volume_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d get_volume_mirror() const { return m_volume_transformation.get_mirror(); }
|
||||||
|
#else
|
||||||
const Vec3d& get_volume_mirror() const { return m_volume_transformation.get_mirror(); }
|
const Vec3d& get_volume_mirror() const { return m_volume_transformation.get_mirror(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double get_volume_mirror(Axis axis) const { return m_volume_transformation.get_mirror(axis); }
|
double get_volume_mirror(Axis axis) const { return m_volume_transformation.get_mirror(axis); }
|
||||||
|
|
||||||
void set_volume_mirror(const Vec3d& mirror) { m_volume_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); }
|
void set_volume_mirror(const Vec3d& mirror) { m_volume_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); }
|
||||||
|
104
src/slic3r/GUI/CoordAxes.cpp
Normal file
104
src/slic3r/GUI/CoordAxes.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
|
#include "CoordAxes.hpp"
|
||||||
|
#include "GUI_App.hpp"
|
||||||
|
#include "3DScene.hpp"
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#include "Plater.hpp"
|
||||||
|
#include "Camera.hpp"
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
const float CoordAxes::DefaultStemRadius = 0.5f;
|
||||||
|
const float CoordAxes::DefaultStemLength = 25.0f;
|
||||||
|
const float CoordAxes::DefaultTipRadius = 2.5f * CoordAxes::DefaultStemRadius;
|
||||||
|
const float CoordAxes::DefaultTipLength = 5.0f;
|
||||||
|
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
void CoordAxes::render(const Transform3d& trafo, float emission_factor)
|
||||||
|
#else
|
||||||
|
void CoordAxes::render(float emission_factor)
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
{
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
auto render_axis = [this](GLShaderProgram& shader, const Transform3d& transform) {
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
const Transform3d matrix = camera.get_view_matrix() * transform;
|
||||||
|
shader.set_uniform("view_model_matrix", matrix);
|
||||||
|
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
|
shader.set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
|
||||||
|
m_arrow.render();
|
||||||
|
#else
|
||||||
|
auto render_axis = [this](const Transform3f& transform) {
|
||||||
|
glsafe(::glPushMatrix());
|
||||||
|
glsafe(::glMultMatrixf(transform.data()));
|
||||||
|
m_arrow.render();
|
||||||
|
glsafe(::glPopMatrix());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!m_arrow.is_initialized())
|
||||||
|
m_arrow.init_from(stilized_arrow(16, m_tip_radius, m_tip_length, m_stem_radius, m_stem_length));
|
||||||
|
|
||||||
|
GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
|
||||||
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||||
|
if (shader == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curr_shader != nullptr)
|
||||||
|
curr_shader->stop_using();
|
||||||
|
|
||||||
|
shader->start_using();
|
||||||
|
shader->set_uniform("emission_factor", emission_factor);
|
||||||
|
|
||||||
|
// x axis
|
||||||
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
m_arrow.set_color(ColorRGBA::X());
|
||||||
|
#else
|
||||||
|
m_arrow.set_color(-1, ColorRGBA::X());
|
||||||
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }));
|
||||||
|
#else
|
||||||
|
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
// y axis
|
||||||
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
m_arrow.set_color(ColorRGBA::Y());
|
||||||
|
#else
|
||||||
|
m_arrow.set_color(-1, ColorRGBA::Y());
|
||||||
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }));
|
||||||
|
#else
|
||||||
|
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
// z axis
|
||||||
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
m_arrow.set_color(ColorRGBA::Z());
|
||||||
|
#else
|
||||||
|
m_arrow.set_color(-1, ColorRGBA::Z());
|
||||||
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin));
|
||||||
|
#else
|
||||||
|
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
shader->stop_using();
|
||||||
|
if (curr_shader != nullptr)
|
||||||
|
curr_shader->start_using();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // GUI
|
||||||
|
} // Slic3r
|
||||||
|
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
64
src/slic3r/GUI/CoordAxes.hpp
Normal file
64
src/slic3r/GUI/CoordAxes.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef slic3r_CoordAxes_hpp_
|
||||||
|
#define slic3r_CoordAxes_hpp_
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "GLModel.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
class CoordAxes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const float DefaultStemRadius;
|
||||||
|
static const float DefaultStemLength;
|
||||||
|
static const float DefaultTipRadius;
|
||||||
|
static const float DefaultTipLength;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vec3d m_origin{ Vec3d::Zero() };
|
||||||
|
float m_stem_radius{ DefaultStemRadius };
|
||||||
|
float m_stem_length{ DefaultStemLength };
|
||||||
|
float m_tip_radius{ DefaultTipRadius };
|
||||||
|
float m_tip_length{ DefaultTipLength };
|
||||||
|
GLModel m_arrow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Vec3d& get_origin() const { return m_origin; }
|
||||||
|
void set_origin(const Vec3d& origin) { m_origin = origin; }
|
||||||
|
void set_stem_radius(float radius) {
|
||||||
|
m_stem_radius = radius;
|
||||||
|
m_arrow.reset();
|
||||||
|
}
|
||||||
|
void set_stem_length(float length) {
|
||||||
|
m_stem_length = length;
|
||||||
|
m_arrow.reset();
|
||||||
|
}
|
||||||
|
void set_tip_radius(float radius) {
|
||||||
|
m_tip_radius = radius;
|
||||||
|
m_arrow.reset();
|
||||||
|
}
|
||||||
|
void set_tip_length(float length) {
|
||||||
|
m_tip_length = length;
|
||||||
|
m_arrow.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_stem_radius() const { return m_stem_radius; }
|
||||||
|
float get_stem_length() const { return m_stem_length; }
|
||||||
|
float get_tip_radius() const { return m_tip_radius; }
|
||||||
|
float get_tip_length() const { return m_tip_length; }
|
||||||
|
float get_total_length() const { return m_stem_length + m_tip_length; }
|
||||||
|
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
void render(const Transform3d& trafo, float emission_factor = 0.0f);
|
||||||
|
#else
|
||||||
|
void render(float emission_factor = 0.0f);
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
};
|
||||||
|
|
||||||
|
} // GUI
|
||||||
|
} // Slic3r
|
||||||
|
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#endif // slic3r_CoordAxes_hpp_
|
@ -1101,6 +1101,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
|
|||||||
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>);
|
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
wxDEFINE_EVENT(EVT_GLCANVAS_RESET_SKEW, SimpleEvent);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
||||||
@ -2914,7 +2917,13 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
|||||||
else
|
else
|
||||||
displacement = multiplier * direction;
|
displacement = multiplier * direction;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType trafo_type;
|
||||||
|
trafo_type.set_relative();
|
||||||
|
m_selection.translate(displacement, trafo_type);
|
||||||
|
#else
|
||||||
m_selection.translate(displacement);
|
m_selection.translate(displacement);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -3579,7 +3588,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType trafo_type;
|
||||||
|
trafo_type.set_relative();
|
||||||
|
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type);
|
||||||
|
#else
|
||||||
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
|
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects)
|
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects)
|
||||||
update_sequential_clearance();
|
update_sequential_clearance();
|
||||||
wxGetApp().obj_manipul()->set_dirty();
|
wxGetApp().obj_manipul()->set_dirty();
|
||||||
@ -3825,9 +3840,17 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
|||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance)
|
if (selection_mode == Selection::Instance)
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
#else
|
||||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
else if (selection_mode == Selection::Volume)
|
else if (selection_mode == Selection::Volume)
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||||
|
#else
|
||||||
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
object_moved = true;
|
object_moved = true;
|
||||||
model_object->invalidate_bounding_box();
|
model_object->invalidate_bounding_box();
|
||||||
@ -3907,8 +3930,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||||||
int object_idx = v->object_idx();
|
int object_idx = v->object_idx();
|
||||||
if (object_idx == 1000) { // the wipe tower
|
if (object_idx == 1000) { // the wipe tower
|
||||||
#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
||||||
Vec3d offset = v->get_volume_offset();
|
const Vec3d offset = v->get_volume_offset();
|
||||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset(0), offset(1), v->get_volume_rotation()(2))));
|
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
|
||||||
}
|
}
|
||||||
#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
||||||
int object_idx = v->object_idx();
|
int object_idx = v->object_idx();
|
||||||
@ -3916,8 +3939,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||||||
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int instance_idx = v->instance_idx();
|
const int instance_idx = v->instance_idx();
|
||||||
int volume_idx = v->volume_idx();
|
const int volume_idx = v->volume_idx();
|
||||||
|
|
||||||
done.insert(std::pair<int, int>(object_idx, instance_idx));
|
done.insert(std::pair<int, int>(object_idx, instance_idx));
|
||||||
|
|
||||||
@ -3925,12 +3948,20 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
|||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance) {
|
if (selection_mode == Selection::Instance) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
#else
|
||||||
model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation());
|
model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation());
|
||||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
else if (selection_mode == Selection::Volume) {
|
else if (selection_mode == Selection::Volume) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||||
|
#else
|
||||||
model_object->volumes[volume_idx]->set_rotation(v->get_volume_rotation());
|
model_object->volumes[volume_idx]->set_rotation(v->get_volume_rotation());
|
||||||
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
model_object->invalidate_bounding_box();
|
model_object->invalidate_bounding_box();
|
||||||
}
|
}
|
||||||
@ -3980,12 +4011,12 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||||||
Selection::EMode selection_mode = m_selection.get_mode();
|
Selection::EMode selection_mode = m_selection.get_mode();
|
||||||
|
|
||||||
for (const GLVolume* v : m_volumes.volumes) {
|
for (const GLVolume* v : m_volumes.volumes) {
|
||||||
int object_idx = v->object_idx();
|
const int object_idx = v->object_idx();
|
||||||
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int instance_idx = v->instance_idx();
|
const int instance_idx = v->instance_idx();
|
||||||
int volume_idx = v->volume_idx();
|
const int volume_idx = v->volume_idx();
|
||||||
|
|
||||||
done.insert(std::pair<int, int>(object_idx, instance_idx));
|
done.insert(std::pair<int, int>(object_idx, instance_idx));
|
||||||
|
|
||||||
@ -3993,13 +4024,22 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance) {
|
if (selection_mode == Selection::Instance) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
#else
|
||||||
model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor());
|
model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor());
|
||||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
else if (selection_mode == Selection::Volume) {
|
else if (selection_mode == Selection::Volume) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||||
|
#else
|
||||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||||
model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor());
|
model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor());
|
||||||
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
model_object->invalidate_bounding_box();
|
model_object->invalidate_bounding_box();
|
||||||
}
|
}
|
||||||
@ -4008,10 +4048,10 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
|||||||
// Fixes sinking/flying instances
|
// Fixes sinking/flying instances
|
||||||
for (const std::pair<int, int>& i : done) {
|
for (const std::pair<int, int>& i : done) {
|
||||||
ModelObject* m = m_model->objects[i.first];
|
ModelObject* m = m_model->objects[i.first];
|
||||||
double shift_z = m->get_instance_min_z(i.second);
|
const double shift_z = m->get_instance_min_z(i.second);
|
||||||
// leave sinking instances as sinking
|
// leave sinking instances as sinking
|
||||||
if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) {
|
if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) {
|
||||||
Vec3d shift(0.0, 0.0, -shift_z);
|
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||||
m_selection.translate(i.first, i.second, shift);
|
m_selection.translate(i.first, i.second, shift);
|
||||||
m->translate_instance(i.second, shift);
|
m->translate_instance(i.second, shift);
|
||||||
}
|
}
|
||||||
@ -4061,9 +4101,17 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
|||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance)
|
if (selection_mode == Selection::Instance)
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
#else
|
||||||
model_object->instances[instance_idx]->set_mirror(v->get_instance_mirror());
|
model_object->instances[instance_idx]->set_mirror(v->get_instance_mirror());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
else if (selection_mode == Selection::Volume)
|
else if (selection_mode == Selection::Volume)
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||||
|
#else
|
||||||
model_object->volumes[volume_idx]->set_mirror(v->get_volume_mirror());
|
model_object->volumes[volume_idx]->set_mirror(v->get_volume_mirror());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
model_object->invalidate_bounding_box();
|
model_object->invalidate_bounding_box();
|
||||||
}
|
}
|
||||||
@ -4087,6 +4135,44 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
|||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void GLCanvas3D::do_reset_skew(const std::string& snapshot_type)
|
||||||
|
{
|
||||||
|
if (m_model == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!snapshot_type.empty())
|
||||||
|
wxGetApp().plater()->take_snapshot(_(snapshot_type));
|
||||||
|
|
||||||
|
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||||
|
|
||||||
|
const Selection::IndicesList& idxs = m_selection.get_volume_idxs();
|
||||||
|
|
||||||
|
for (unsigned int id : idxs) {
|
||||||
|
const GLVolume* v = m_volumes.volumes[id];
|
||||||
|
int object_idx = v->object_idx();
|
||||||
|
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int instance_idx = v->instance_idx();
|
||||||
|
int volume_idx = v->volume_idx();
|
||||||
|
|
||||||
|
done.insert(std::pair<int, int>(object_idx, instance_idx));
|
||||||
|
|
||||||
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
|
if (model_object != nullptr) {
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||||
|
model_object->invalidate_bounding_box();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post_event(SimpleEvent(EVT_GLCANVAS_RESET_SKEW));
|
||||||
|
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void GLCanvas3D::update_gizmos_on_off_state()
|
void GLCanvas3D::update_gizmos_on_off_state()
|
||||||
{
|
{
|
||||||
set_as_dirty();
|
set_as_dirty();
|
||||||
|
@ -156,6 +156,9 @@ wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
|
|||||||
wxDECLARE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
wxDECLARE_EVENT(EVT_GLCANVAS_RESET_SKEW, SimpleEvent);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
|
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
|
||||||
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
|
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
|
||||||
@ -739,7 +742,11 @@ public:
|
|||||||
|
|
||||||
void update_volumes_colors_by_extruder();
|
void update_volumes_colors_by_extruder();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
bool is_dragging() const { return m_gizmos.is_dragging() || (m_moving && !m_mouse.scene_position.isApprox(m_mouse.drag.start_position_3D)); }
|
||||||
|
#else
|
||||||
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
|
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
// printable_only == false -> render also non printable volumes as grayed
|
// printable_only == false -> render also non printable volumes as grayed
|
||||||
@ -807,6 +814,9 @@ public:
|
|||||||
void do_rotate(const std::string& snapshot_type);
|
void do_rotate(const std::string& snapshot_type);
|
||||||
void do_scale(const std::string& snapshot_type);
|
void do_scale(const std::string& snapshot_type);
|
||||||
void do_mirror(const std::string& snapshot_type);
|
void do_mirror(const std::string& snapshot_type);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void do_reset_skew(const std::string& snapshot_type);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void update_gizmos_on_off_state();
|
void update_gizmos_on_off_state();
|
||||||
void reset_all_gizmos() { m_gizmos.reset_all_states(); }
|
void reset_all_gizmos() { m_gizmos.reset_all_states(); }
|
||||||
|
9
src/slic3r/GUI/GUI_Geometry.cpp
Normal file
9
src/slic3r/GUI/GUI_Geometry.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
|
#include "GUI_Geometry.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
} // namespace GUI
|
81
src/slic3r/GUI/GUI_Geometry.hpp
Normal file
81
src/slic3r/GUI/GUI_Geometry.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef slic3r_GUI_Geometry_hpp_
|
||||||
|
#define slic3r_GUI_Geometry_hpp_
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
enum class ECoordinatesType : unsigned char
|
||||||
|
{
|
||||||
|
World,
|
||||||
|
Instance,
|
||||||
|
Local
|
||||||
|
};
|
||||||
|
|
||||||
|
class TransformationType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Enum {
|
||||||
|
// Transforming in a world coordinate system
|
||||||
|
World = 0,
|
||||||
|
// Transforming in a instance coordinate system
|
||||||
|
Instance = 1,
|
||||||
|
// Transforming in a local coordinate system
|
||||||
|
Local = 2,
|
||||||
|
// Absolute transformations, allowed in local coordinate system only.
|
||||||
|
Absolute = 0,
|
||||||
|
// Relative transformations, allowed in both local and world coordinate system.
|
||||||
|
Relative = 4,
|
||||||
|
// For group selection, the transformation is performed as if the group made a single solid body.
|
||||||
|
Joint = 0,
|
||||||
|
// For group selection, the transformation is performed on each object independently.
|
||||||
|
Independent = 8,
|
||||||
|
|
||||||
|
World_Relative_Joint = World | Relative | Joint,
|
||||||
|
World_Relative_Independent = World | Relative | Independent,
|
||||||
|
Instance_Absolute_Joint = Instance | Absolute | Joint,
|
||||||
|
Instance_Absolute_Independent = Instance | Absolute | Independent,
|
||||||
|
Instance_Relative_Joint = Instance | Relative | Joint,
|
||||||
|
Instance_Relative_Independent = Instance | Relative | Independent,
|
||||||
|
Local_Absolute_Joint = Local | Absolute | Joint,
|
||||||
|
Local_Absolute_Independent = Local | Absolute | Independent,
|
||||||
|
Local_Relative_Joint = Local | Relative | Joint,
|
||||||
|
Local_Relative_Independent = Local | Relative | Independent,
|
||||||
|
};
|
||||||
|
|
||||||
|
TransformationType() : m_value(World) {}
|
||||||
|
TransformationType(Enum value) : m_value(value) {}
|
||||||
|
TransformationType& operator=(Enum value) { m_value = value; return *this; }
|
||||||
|
|
||||||
|
Enum operator()() const { return m_value; }
|
||||||
|
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
|
||||||
|
|
||||||
|
void set_world() { this->remove(Instance); this->remove(Local); }
|
||||||
|
void set_instance() { this->remove(Local); this->add(Instance); }
|
||||||
|
void set_local() { this->remove(Instance); this->add(Local); }
|
||||||
|
void set_absolute() { this->remove(Relative); }
|
||||||
|
void set_relative() { this->add(Relative); }
|
||||||
|
void set_joint() { this->remove(Independent); }
|
||||||
|
void set_independent() { this->add(Independent); }
|
||||||
|
|
||||||
|
bool world() const { return !this->has(Instance) && !this->has(Local); }
|
||||||
|
bool instance() const { return this->has(Instance); }
|
||||||
|
bool local() const { return this->has(Local); }
|
||||||
|
bool absolute() const { return !this->has(Relative); }
|
||||||
|
bool relative() const { return this->has(Relative); }
|
||||||
|
bool joint() const { return !this->has(Independent); }
|
||||||
|
bool independent() const { return this->has(Independent); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
|
||||||
|
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
|
||||||
|
|
||||||
|
Enum m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
} // namespace GUI
|
||||||
|
|
||||||
|
#endif // slic3r_GUI_Geometry_hpp_
|
@ -1530,9 +1530,13 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
|
|||||||
const BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
|
const BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
|
||||||
|
|
||||||
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* v = selection.get_first_volume();
|
||||||
const Geometry::Transformation inst_transform = v->get_instance_transformation();
|
const Geometry::Transformation inst_transform = v->get_instance_transformation();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d inv_inst_transform = inst_transform.get_matrix_no_offset().inverse();
|
||||||
|
#else
|
||||||
const Transform3d inv_inst_transform = inst_transform.get_matrix(true).inverse();
|
const Transform3d inv_inst_transform = inst_transform.get_matrix(true).inverse();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
const Vec3d instance_offset = v->get_instance_offset();
|
const Vec3d instance_offset = v->get_instance_offset();
|
||||||
|
|
||||||
for (size_t i = 0; i < input_files.size(); ++i) {
|
for (size_t i = 0; i < input_files.size(); ++i) {
|
||||||
@ -1580,9 +1584,15 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
|
|||||||
new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset;
|
new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset;
|
||||||
|
|
||||||
if (from_galery) {
|
if (from_galery) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Transform the new modifier to be aligned with the print bed.
|
||||||
|
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
|
||||||
|
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||||
|
#else
|
||||||
// Transform the new modifier to be aligned with the print bed.
|
// Transform the new modifier to be aligned with the print bed.
|
||||||
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||||
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(inst_transform, mesh_bb));
|
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(inst_transform, mesh_bb));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// Set the modifier position.
|
// Set the modifier position.
|
||||||
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
|
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
|
||||||
const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset;
|
const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset;
|
||||||
@ -1650,17 +1660,27 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
|||||||
ModelVolume *new_volume = model_object.add_volume(std::move(mesh), type);
|
ModelVolume *new_volume = model_object.add_volume(std::move(mesh), type);
|
||||||
|
|
||||||
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* v = selection.get_first_volume();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Transform the new modifier to be aligned with the print bed.
|
||||||
|
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
|
||||||
|
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||||
|
#else
|
||||||
// Transform the new modifier to be aligned with the print bed.
|
// Transform the new modifier to be aligned with the print bed.
|
||||||
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||||
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
|
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// Set the modifier position.
|
// Set the modifier position.
|
||||||
auto offset = (type_name == "Slab") ?
|
auto offset = (type_name == "Slab") ?
|
||||||
// Slab: Lift to print bed
|
// Slab: Lift to print bed
|
||||||
Vec3d(0., 0., 0.5 * mesh_bb.size().z() + instance_bb.min.z() - v->get_instance_offset().z()) :
|
Vec3d(0., 0., 0.5 * mesh_bb.size().z() + instance_bb.min.z() - v->get_instance_offset().z()) :
|
||||||
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
|
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
|
||||||
Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - v->get_instance_offset();
|
Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - v->get_instance_offset();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
new_volume->set_offset(v->get_instance_transformation().get_matrix_no_offset().inverse() * offset);
|
||||||
|
#else
|
||||||
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
|
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
const wxString name = _L("Generic") + "-" + _(type_name);
|
const wxString name = _L("Generic") + "-" + _(type_name);
|
||||||
new_volume->name = into_u8(name);
|
new_volume->name = into_u8(name);
|
||||||
@ -2545,7 +2565,13 @@ void ObjectList::part_selection_changed()
|
|||||||
Sidebar& panel = wxGetApp().sidebar();
|
Sidebar& panel = wxGetApp().sidebar();
|
||||||
panel.Freeze();
|
panel.Freeze();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
|
||||||
|
const std::string opt_key = (editor != nullptr) ? editor->get_full_opt_name() : "";
|
||||||
|
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, !opt_key.empty());
|
||||||
|
#else
|
||||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
|
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
|
wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
|
||||||
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
|
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
|
||||||
wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers);
|
wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers);
|
||||||
@ -3263,8 +3289,12 @@ void ObjectList::update_selections()
|
|||||||
return;
|
return;
|
||||||
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
|
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
|
||||||
}
|
}
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
else if (selection.is_single_volume_or_modifier()) {
|
||||||
|
#else
|
||||||
else if (selection.is_single_volume() || selection.is_any_modifier()) {
|
else if (selection.is_single_volume() || selection.is_any_modifier()) {
|
||||||
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const auto gl_vol = selection.get_first_volume();
|
||||||
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
|
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,17 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent)
|
|||||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||||
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::World));
|
||||||
|
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Instance));
|
||||||
|
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Local));
|
||||||
|
temp->Select((int)ECoordinatesType::World);
|
||||||
|
#else
|
||||||
temp->Append(_L("World coordinates"));
|
temp->Append(_L("World coordinates"));
|
||||||
temp->Append(_L("Local coordinates"));
|
temp->Append(_L("Local coordinates"));
|
||||||
temp->SetSelection(0);
|
temp->SetSelection(0);
|
||||||
temp->SetValue(temp->GetString(0));
|
temp->SetValue(temp->GetString(0));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
temp->SetToolTip(_L("Select coordinate space, in which the transformation will be performed."));
|
temp->SetToolTip(_L("Select coordinate space, in which the transformation will be performed."));
|
||||||
return temp;
|
return temp;
|
||||||
@ -81,8 +88,14 @@ void msw_rescale_word_local_combo(choice_ctrl* combo)
|
|||||||
// Set rescaled size
|
// Set rescaled size
|
||||||
combo->SetSize(size);
|
combo->SetSize(size);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::World));
|
||||||
|
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Instance));
|
||||||
|
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Local));
|
||||||
|
#else
|
||||||
combo->Append(_L("World coordinates"));
|
combo->Append(_L("World coordinates"));
|
||||||
combo->Append(_L("Local coordinates"));
|
combo->Append(_L("Local coordinates"));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
combo->SetValue(selection);
|
combo->SetValue(selection);
|
||||||
#else
|
#else
|
||||||
@ -101,6 +114,7 @@ static void set_font_and_background_style(wxWindow* win, const wxFont& font)
|
|||||||
|
|
||||||
static const wxString axes_color_text[] = { "#990000", "#009900", "#000099" };
|
static const wxString axes_color_text[] = { "#990000", "#009900", "#000099" };
|
||||||
static const wxString axes_color_back[] = { "#f5dcdc", "#dcf5dc", "#dcdcf5" };
|
static const wxString axes_color_back[] = { "#f5dcdc", "#dcf5dc", "#dcdcf5" };
|
||||||
|
|
||||||
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
OG_Settings(parent, true)
|
OG_Settings(parent, true)
|
||||||
{
|
{
|
||||||
@ -157,7 +171,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
// Add world local combobox
|
// Add world local combobox
|
||||||
m_word_local_combo = create_word_local_combo(parent);
|
m_word_local_combo = create_word_local_combo(parent);
|
||||||
m_word_local_combo->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent& evt) {
|
m_word_local_combo->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent& evt) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
this->set_coordinates_type(evt.GetString());
|
||||||
|
#else
|
||||||
this->set_world_coordinates(evt.GetSelection() != 1);
|
this->set_world_coordinates(evt.GetSelection() != 1);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}), m_word_local_combo->GetId());
|
}), m_word_local_combo->GetId());
|
||||||
|
|
||||||
// Small trick to correct layouting in different view_mode :
|
// Small trick to correct layouting in different view_mode :
|
||||||
@ -264,8 +282,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (selection.is_single_volume_or_modifier()) {
|
||||||
|
#else
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
GLVolume* volume = const_cast<GLVolume*>(selection.get_first_volume());
|
||||||
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
|
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
|
||||||
}
|
}
|
||||||
else if (selection.is_single_full_instance()) {
|
else if (selection.is_single_full_instance()) {
|
||||||
@ -278,7 +300,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Update mirroring at the GLVolumes.
|
// Update mirroring at the GLVolumes.
|
||||||
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
|
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
|
||||||
selection.synchronize_unselected_volumes();
|
selection.synchronize_unselected_volumes();
|
||||||
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||||
canvas->do_mirror(L("Set Mirror"));
|
canvas->do_mirror(L("Set Mirror"));
|
||||||
@ -327,28 +349,60 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
#if ENABLE_WORLD_COORDINATE
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
if (selection.is_single_volume_or_modifier()) {
|
||||||
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
const Geometry::Transformation& instance_trafo = volume->get_instance_transformation();
|
const double min_z = get_volume_min_z(*volume);
|
||||||
const Vec3d diff = m_cache.position - instance_trafo.get_matrix(true).inverse() * Vec3d(0., 0., get_volume_min_z(*volume));
|
if (!is_world_coordinates()) {
|
||||||
|
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix_no_offset().inverse() * (min_z * Vec3d::UnitZ());
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||||
change_position_value(0, diff.x());
|
change_position_value(0, diff.x());
|
||||||
change_position_value(1, diff.y());
|
change_position_value(1, diff.y());
|
||||||
change_position_value(2, diff.z());
|
change_position_value(2, diff.z());
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||||
|
change_position_value(2, m_cache.position.z() - min_z);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||||
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
|
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix(true).inverse() * (get_volume_min_z(*volume) * Vec3d::UnitZ());
|
||||||
|
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||||
|
change_position_value(0, diff.x());
|
||||||
|
change_position_value(1, diff.y());
|
||||||
|
change_position_value(2, diff.z());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
}
|
||||||
else if (selection.is_single_full_instance()) {
|
else if (selection.is_single_full_instance()) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const double min_z = selection.get_scaled_instance_bounding_box().min.z();
|
||||||
|
if (!is_world_coordinates()) {
|
||||||
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
|
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix_no_offset().inverse() * (min_z * Vec3d::UnitZ());
|
||||||
|
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||||
|
change_position_value(0, diff.x());
|
||||||
|
change_position_value(1, diff.y());
|
||||||
|
change_position_value(2, diff.z());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#else
|
||||||
const ModelObjectPtrs& objects = wxGetApp().model().objects;
|
const ModelObjectPtrs& objects = wxGetApp().model().objects;
|
||||||
const int idx = selection.get_object_idx();
|
const int idx = selection.get_object_idx();
|
||||||
if (0 <= idx && idx < static_cast<int>(objects.size())) {
|
if (0 <= idx && idx < static_cast<int>(objects.size())) {
|
||||||
const ModelObject* mo = wxGetApp().model().objects[idx];
|
const ModelObject* mo = wxGetApp().model().objects[idx];
|
||||||
const double min_z = mo->bounding_box().min.z();
|
const double min_z = mo->bounding_box().min.z();
|
||||||
if (std::abs(min_z) > SINKING_Z_THRESHOLD) {
|
if (std::abs(min_z) > SINKING_Z_THRESHOLD) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||||
change_position_value(2, m_cache.position.z() - min_z);
|
change_position_value(2, m_cache.position.z() - min_z);
|
||||||
}
|
}
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
editors_grid_sizer->Add(m_drop_to_bed_button);
|
editors_grid_sizer->Add(m_drop_to_bed_button);
|
||||||
@ -365,21 +419,22 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
#if ENABLE_WORLD_COORDINATE
|
||||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
|
if (selection.is_single_volume_or_modifier())
|
||||||
volume->set_volume_rotation(Vec3d::Zero());
|
#else
|
||||||
}
|
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const_cast<GLVolume*>(selection.get_first_volume())->set_volume_rotation(Vec3d::Zero());
|
||||||
else if (selection.is_single_full_instance()) {
|
else if (selection.is_single_full_instance()) {
|
||||||
for (unsigned int idx : selection.get_volume_idxs()) {
|
for (unsigned int idx : selection.get_volume_idxs()) {
|
||||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(idx));
|
const_cast<GLVolume*>(selection.get_volume(idx))->set_instance_rotation(Vec3d::Zero());
|
||||||
volume->set_instance_rotation(Vec3d::Zero());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Update rotation at the GLVolumes.
|
// Update rotation at the GLVolumes.
|
||||||
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
|
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
|
||||||
selection.synchronize_unselected_volumes();
|
selection.synchronize_unselected_volumes();
|
||||||
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||||
canvas->do_rotate(L("Reset Rotation"));
|
canvas->do_rotate(L("Reset Rotation"));
|
||||||
@ -397,10 +452,28 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
m_reset_scale_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo"));
|
m_reset_scale_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo"));
|
||||||
m_reset_scale_button->SetToolTip(_L("Reset scale"));
|
m_reset_scale_button->SetToolTip(_L("Reset scale"));
|
||||||
m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
|
Selection& selection = canvas->get_selection();
|
||||||
|
if (selection.is_single_volume_or_modifier())
|
||||||
|
const_cast<GLVolume*>(selection.get_first_volume())->set_volume_scaling_factor(Vec3d::Ones());
|
||||||
|
else if (selection.is_single_full_instance()) {
|
||||||
|
for (unsigned int idx : selection.get_volume_idxs()) {
|
||||||
|
const_cast<GLVolume*>(selection.get_volume(idx))->set_instance_scaling_factor(Vec3d::Ones());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
canvas->do_scale(L("Reset scale"));
|
||||||
|
|
||||||
|
UpdateAndShow(true);
|
||||||
|
#else
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale"));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale"));
|
||||||
change_scale_value(0, 100.);
|
change_scale_value(0, 100.);
|
||||||
change_scale_value(1, 100.);
|
change_scale_value(1, 100.);
|
||||||
change_scale_value(2, 100.);
|
change_scale_value(2, 100.);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
});
|
});
|
||||||
editors_grid_sizer->Add(m_reset_scale_button);
|
editors_grid_sizer->Add(m_reset_scale_button);
|
||||||
|
|
||||||
@ -411,6 +484,25 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
|
|
||||||
m_main_grid_sizer->Add(editors_grid_sizer, 1, wxEXPAND);
|
m_main_grid_sizer->Add(editors_grid_sizer, 1, wxEXPAND);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_skew_label = new wxStaticText(parent, wxID_ANY, _L("Skew"));
|
||||||
|
m_main_grid_sizer->Add(m_skew_label, 1, wxEXPAND);
|
||||||
|
|
||||||
|
m_reset_skew_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo"));
|
||||||
|
m_reset_skew_button->SetToolTip(_L("Reset skew"));
|
||||||
|
m_reset_skew_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||||
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
|
Selection& selection = canvas->get_selection();
|
||||||
|
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||||
|
selection.setup_cache();
|
||||||
|
selection.reset_skew();
|
||||||
|
canvas->do_reset_skew(L("Reset skew"));
|
||||||
|
UpdateAndShow(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_main_grid_sizer->Add(m_reset_skew_button);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
m_check_inch = new wxCheckBox(parent, wxID_ANY, _L("Inches"));
|
m_check_inch = new wxCheckBox(parent, wxID_ANY, _L("Inches"));
|
||||||
m_check_inch->SetFont(wxGetApp().normal_font());
|
m_check_inch->SetFont(wxGetApp().normal_font());
|
||||||
|
|
||||||
@ -444,7 +536,26 @@ void ObjectManipulation::Show(const bool show)
|
|||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
// Show the "World Coordinates" / "Local Coordintes" Combo in Advanced / Expert mode only.
|
// Show the "World Coordinates" / "Local Coordintes" Combo in Advanced / Expert mode only.
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
|
||||||
|
if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) {
|
||||||
|
#ifdef __linux__
|
||||||
|
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), 1);
|
||||||
|
#else
|
||||||
|
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), wxNullBitmap, 1);
|
||||||
|
#endif // __linux__
|
||||||
|
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||||
|
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
|
||||||
|
}
|
||||||
|
else if (selection.is_single_full_instance() && m_word_local_combo->GetCount() > 2) {
|
||||||
|
m_word_local_combo->Delete(1);
|
||||||
|
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||||
|
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple;
|
bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_word_local_combo->Show(show_world_local_combo);
|
m_word_local_combo->Show(show_world_local_combo);
|
||||||
m_empty_str->Show(!show_world_local_combo);
|
m_empty_str->Show(!show_world_local_combo);
|
||||||
}
|
}
|
||||||
@ -489,8 +600,7 @@ void ObjectManipulation::update_ui_from_settings()
|
|||||||
}
|
}
|
||||||
m_check_inch->SetValue(m_imperial_units);
|
m_check_inch->SetValue(m_imperial_units);
|
||||||
|
|
||||||
if (m_use_colors != (wxGetApp().app_config->get("color_mapinulation_panel") == "1"))
|
if (m_use_colors != (wxGetApp().app_config->get("color_mapinulation_panel") == "1")) {
|
||||||
{
|
|
||||||
m_use_colors = wxGetApp().app_config->get("color_mapinulation_panel") == "1";
|
m_use_colors = wxGetApp().app_config->get("color_mapinulation_panel") == "1";
|
||||||
// update colors for edit-boxes
|
// update colors for edit-boxes
|
||||||
int axis_id = 0;
|
int axis_id = 0;
|
||||||
@ -522,13 +632,16 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
m_new_rotate_label_string = L("Rotation");
|
m_new_rotate_label_string = L("Rotation");
|
||||||
m_new_scale_label_string = L("Scale factors");
|
m_new_scale_label_string = L("Scale factors");
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
if (wxGetApp().get_mode() == comSimple)
|
if (wxGetApp().get_mode() == comSimple)
|
||||||
m_world_coordinates = true;
|
m_world_coordinates = true;
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
ObjectList* obj_list = wxGetApp().obj_list();
|
ObjectList* obj_list = wxGetApp().obj_list();
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance()) {
|
||||||
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
m_new_position = volume->get_instance_offset();
|
m_new_position = volume->get_instance_offset();
|
||||||
|
|
||||||
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
||||||
@ -538,17 +651,30 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
m_uniform_scale = true;
|
m_uniform_scale = true;
|
||||||
m_lock_bnt->SetLock(true);
|
m_lock_bnt->SetLock(true);
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (is_world_coordinates()) {
|
||||||
|
m_new_position = volume->get_instance_offset();
|
||||||
|
#else
|
||||||
if (m_world_coordinates) {
|
if (m_world_coordinates) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_new_rotate_label_string = L("Rotate");
|
m_new_rotate_label_string = L("Rotate");
|
||||||
m_new_rotation = Vec3d::Zero();
|
m_new_rotation = Vec3d::Zero();
|
||||||
m_new_size = selection.get_scaled_instance_bounding_box().size();
|
m_new_size = selection.get_scaled_instance_bounding_box().size();
|
||||||
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.;
|
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_new_move_label_string = L("Translate");
|
||||||
|
m_new_rotate_label_string = L("Rotate");
|
||||||
|
m_new_position = Vec3d::Zero();
|
||||||
|
m_new_rotation = Vec3d::Zero();
|
||||||
|
#else
|
||||||
|
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
|
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
|
||||||
m_new_scale = volume->get_instance_scaling_factor() * 100.;
|
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
@ -557,19 +683,52 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
m_new_position = box.center();
|
m_new_position = box.center();
|
||||||
m_new_rotation = Vec3d::Zero();
|
m_new_rotation = Vec3d::Zero();
|
||||||
m_new_scale = Vec3d(100., 100., 100.);
|
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||||
m_new_size = box.size();
|
m_new_size = box.size();
|
||||||
m_new_rotate_label_string = L("Rotate");
|
m_new_rotate_label_string = L("Rotate");
|
||||||
m_new_scale_label_string = L("Scale");
|
m_new_scale_label_string = L("Scale");
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
else if (selection.is_single_volume_or_modifier()) {
|
||||||
|
#else
|
||||||
else if (selection.is_single_modifier() || selection.is_single_volume()) {
|
else if (selection.is_single_modifier() || selection.is_single_volume()) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// the selection contains a single volume
|
// the selection contains a single volume
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (is_world_coordinates()) {
|
||||||
|
const Geometry::Transformation trafo(volume->world_matrix());
|
||||||
|
|
||||||
|
const Vec3d& offset = trafo.get_offset();
|
||||||
|
|
||||||
|
m_new_position = offset;
|
||||||
|
m_new_rotate_label_string = L("Rotate");
|
||||||
|
m_new_rotation = Vec3d::Zero();
|
||||||
|
m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size();
|
||||||
|
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
|
||||||
|
}
|
||||||
|
else if (is_local_coordinates()) {
|
||||||
|
m_new_move_label_string = L("Translate");
|
||||||
|
m_new_rotate_label_string = L("Rotate");
|
||||||
|
m_new_position = Vec3d::Zero();
|
||||||
|
m_new_rotation = Vec3d::Zero();
|
||||||
|
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
|
||||||
|
m_new_size = volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_new_position = volume->get_volume_offset();
|
m_new_position = volume->get_volume_offset();
|
||||||
m_new_rotation = volume->get_volume_rotation() * (180. / M_PI);
|
m_new_rotate_label_string = L("Rotate");
|
||||||
m_new_scale = volume->get_volume_scaling_factor() * 100.;
|
m_new_rotation = Vec3d::Zero();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size();
|
||||||
|
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
|
||||||
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
|
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
|
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
|
||||||
@ -635,15 +794,18 @@ void ObjectManipulation::update_if_dirty()
|
|||||||
update(m_cache.rotation, m_cache.rotation_rounded, meRotation, m_new_rotation);
|
update(m_cache.rotation, m_cache.rotation_rounded, meRotation, m_new_rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
if (selection.requires_uniform_scale()) {
|
if (selection.requires_uniform_scale()) {
|
||||||
m_lock_bnt->SetLock(true);
|
m_lock_bnt->SetLock(true);
|
||||||
m_lock_bnt->SetToolTip(_L("You cannot use non-uniform scaling mode for multiple objects/parts selection"));
|
m_lock_bnt->SetToolTip(_L("You cannot use non-uniform scaling mode for multiple objects/parts selection"));
|
||||||
m_lock_bnt->disable();
|
m_lock_bnt->disable();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
m_lock_bnt->SetLock(m_uniform_scale);
|
m_lock_bnt->SetLock(m_uniform_scale);
|
||||||
m_lock_bnt->SetToolTip(wxEmptyString);
|
m_lock_bnt->SetToolTip(wxEmptyString);
|
||||||
m_lock_bnt->enable();
|
m_lock_bnt->enable();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -651,6 +813,7 @@ void ObjectManipulation::update_if_dirty()
|
|||||||
if (m_word_local_combo->GetSelection() != new_selection)
|
if (m_word_local_combo->GetSelection() != new_selection)
|
||||||
m_word_local_combo->SetSelection(new_selection);
|
m_word_local_combo->SetSelection(new_selection);
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
if (m_new_enabled)
|
if (m_new_enabled)
|
||||||
m_og->enable();
|
m_og->enable();
|
||||||
@ -677,29 +840,75 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||||||
bool show_rotation = false;
|
bool show_rotation = false;
|
||||||
bool show_scale = false;
|
bool show_scale = false;
|
||||||
bool show_drop_to_bed = false;
|
bool show_drop_to_bed = false;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
bool show_skew = false;
|
||||||
|
|
||||||
|
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||||
|
const double min_z = selection.is_single_full_instance() ? selection.get_scaled_instance_bounding_box().min.z() :
|
||||||
|
get_volume_min_z(*selection.get_first_volume());
|
||||||
|
|
||||||
|
show_drop_to_bed = std::abs(min_z) > EPSILON;
|
||||||
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
|
Transform3d rotation = Transform3d::Identity();
|
||||||
|
Transform3d scale = Transform3d::Identity();
|
||||||
|
Geometry::Transformation skew;
|
||||||
|
#else
|
||||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
Vec3d rotation;
|
Vec3d rotation;
|
||||||
Vec3d scale;
|
Vec3d scale;
|
||||||
double min_z = 0.;
|
double min_z = 0.0;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance()) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Geometry::Transformation& trafo = volume->get_instance_transformation();
|
||||||
|
rotation = trafo.get_rotation_matrix();
|
||||||
|
scale = trafo.get_scaling_factor_matrix();
|
||||||
|
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||||
|
for (unsigned int id : idxs) {
|
||||||
|
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
|
||||||
|
if (world_trafo.has_skew()) {
|
||||||
|
skew = world_trafo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
rotation = volume->get_instance_rotation();
|
rotation = volume->get_instance_rotation();
|
||||||
scale = volume->get_instance_scaling_factor();
|
scale = volume->get_instance_scaling_factor();
|
||||||
min_z = wxGetApp().model().objects[volume->composite_id.object_id]->bounding_box().min.z();
|
min_z = selection.get_scaled_instance_bounding_box().min.z();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Geometry::Transformation& trafo = volume->get_volume_transformation();
|
||||||
|
rotation = trafo.get_rotation_matrix();
|
||||||
|
scale = trafo.get_scaling_factor_matrix();
|
||||||
|
const Geometry::Transformation world_trafo(volume->world_matrix());
|
||||||
|
if (world_trafo.has_skew())
|
||||||
|
skew = world_trafo;
|
||||||
|
#else
|
||||||
rotation = volume->get_volume_rotation();
|
rotation = volume->get_volume_rotation();
|
||||||
scale = volume->get_volume_scaling_factor();
|
scale = volume->get_volume_scaling_factor();
|
||||||
min_z = get_volume_min_z(*volume);
|
min_z = get_volume_min_z(*volume);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
show_rotation = !rotation.isApprox(Transform3d::Identity());
|
||||||
|
show_scale = !scale.isApprox(Transform3d::Identity());
|
||||||
|
show_skew = skew.has_skew();
|
||||||
|
#else
|
||||||
show_rotation = !rotation.isApprox(Vec3d::Zero());
|
show_rotation = !rotation.isApprox(Vec3d::Zero());
|
||||||
show_scale = !scale.isApprox(Vec3d::Ones());
|
show_scale = !scale.isApprox(Vec3d::Ones());
|
||||||
show_drop_to_bed = std::abs(min_z) > SINKING_Z_THRESHOLD;
|
show_drop_to_bed = std::abs(min_z) > SINKING_Z_THRESHOLD;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew] {
|
||||||
|
#else
|
||||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
|
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// There is a case (under OSX), when this function is called after the Manipulation panel is hidden
|
// There is a case (under OSX), when this function is called after the Manipulation panel is hidden
|
||||||
// So, let check if Manipulation panel is still shown for this moment
|
// So, let check if Manipulation panel is still shown for this moment
|
||||||
if (!this->IsShown())
|
if (!this->IsShown())
|
||||||
@ -707,6 +916,10 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||||||
m_reset_rotation_button->Show(show_rotation);
|
m_reset_rotation_button->Show(show_rotation);
|
||||||
m_reset_scale_button->Show(show_scale);
|
m_reset_scale_button->Show(show_scale);
|
||||||
m_drop_to_bed_button->Show(show_drop_to_bed);
|
m_drop_to_bed_button->Show(show_drop_to_bed);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_reset_skew_button->Show(show_skew);
|
||||||
|
m_skew_label->Show(show_skew);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// Because of CallAfter we need to layout sidebar after Show/hide of reset buttons one more time
|
// Because of CallAfter we need to layout sidebar after Show/hide of reset buttons one more time
|
||||||
Sidebar& panel = wxGetApp().sidebar();
|
Sidebar& panel = wxGetApp().sidebar();
|
||||||
@ -726,9 +939,17 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
|||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
|
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (is_local_coordinates()) {
|
||||||
|
#else
|
||||||
if (!m_world_coordinates) {
|
if (!m_world_coordinates) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||||
|
#else
|
||||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
Vec3d mirror;
|
Vec3d mirror;
|
||||||
|
|
||||||
if (selection.is_single_full_instance())
|
if (selection.is_single_full_instance())
|
||||||
@ -792,6 +1013,19 @@ void ObjectManipulation::update_warning_icon_state(const MeshErrorsInfo& warning
|
|||||||
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
|
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
wxString ObjectManipulation::coordinate_type_str(ECoordinatesType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ECoordinatesType::World: { return _L("World coordinates"); }
|
||||||
|
case ECoordinatesType::Instance: { return _L("Instance coordinates"); }
|
||||||
|
case ECoordinatesType::Local: { return _L("Local coordinates"); }
|
||||||
|
default: { assert(false); return _L("Unknown"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void ObjectManipulation::reset_settings_value()
|
void ObjectManipulation::reset_settings_value()
|
||||||
{
|
{
|
||||||
m_new_position = Vec3d::Zero();
|
m_new_position = Vec3d::Zero();
|
||||||
@ -815,7 +1049,19 @@ void ObjectManipulation::change_position_value(int axis, double value)
|
|||||||
auto canvas = wxGetApp().plater()->canvas3D();
|
auto canvas = wxGetApp().plater()->canvas3D();
|
||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
selection.setup_cache();
|
selection.setup_cache();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType trafo_type;
|
||||||
|
trafo_type.set_relative();
|
||||||
|
switch (get_coordinates_type())
|
||||||
|
{
|
||||||
|
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
|
||||||
|
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
selection.translate(position - m_cache.position, trafo_type);
|
||||||
|
#else
|
||||||
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
canvas->do_move(L("Set Position"));
|
canvas->do_move(L("Set Position"));
|
||||||
|
|
||||||
m_cache.position = position;
|
m_cache.position = position;
|
||||||
@ -834,6 +1080,18 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
|
|||||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType transformation_type;
|
||||||
|
transformation_type.set_relative();
|
||||||
|
if (selection.is_single_full_instance())
|
||||||
|
transformation_type.set_independent();
|
||||||
|
|
||||||
|
if (is_local_coordinates())
|
||||||
|
transformation_type.set_local();
|
||||||
|
|
||||||
|
if (is_instance_coordinates())
|
||||||
|
transformation_type.set_instance();
|
||||||
|
#else
|
||||||
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
if (selection.is_single_full_instance() || selection.requires_local_axes())
|
if (selection.is_single_full_instance() || selection.requires_local_axes())
|
||||||
transformation_type.set_independent();
|
transformation_type.set_independent();
|
||||||
@ -842,6 +1100,7 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
|
|||||||
// transformation_type.set_absolute();
|
// transformation_type.set_absolute();
|
||||||
transformation_type.set_local();
|
transformation_type.set_local();
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
selection.setup_cache();
|
selection.setup_cache();
|
||||||
selection.rotate(
|
selection.rotate(
|
||||||
@ -887,8 +1146,12 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
|
||||||
Vec3d ref_size = m_cache.size;
|
Vec3d ref_size = m_cache.size;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (selection.is_single_volume_or_modifier()) {
|
||||||
|
#else
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const GLVolume* v = selection.get_first_volume();
|
||||||
const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor());
|
const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor());
|
||||||
const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor());
|
const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor());
|
||||||
const Vec3d local_change = local_size.cwiseQuotient(local_ref_size);
|
const Vec3d local_change = local_size.cwiseQuotient(local_ref_size);
|
||||||
@ -897,11 +1160,19 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||||||
ref_size = Vec3d::Ones();
|
ref_size = Vec3d::Ones();
|
||||||
}
|
}
|
||||||
else if (selection.is_single_full_instance())
|
else if (selection.is_single_full_instance())
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ref_size = is_world_coordinates() ?
|
||||||
|
#else
|
||||||
ref_size = m_world_coordinates ?
|
ref_size = m_world_coordinates ?
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
selection.get_unscaled_instance_bounding_box().size() :
|
selection.get_unscaled_instance_bounding_box().size() :
|
||||||
wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size();
|
wxGetApp().model().objects[selection.get_first_volume()->object_idx()]->raw_mesh_bounding_box().size();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
this->do_size(axis, size.cwiseQuotient(ref_size));
|
||||||
|
#else
|
||||||
this->do_scale(axis, size.cwiseQuotient(ref_size));
|
this->do_scale(axis, size.cwiseQuotient(ref_size));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
m_cache.size = size;
|
m_cache.size = size;
|
||||||
m_cache.size_rounded(axis) = DBL_MAX;
|
m_cache.size_rounded(axis) = DBL_MAX;
|
||||||
@ -911,8 +1182,22 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||||||
void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
||||||
{
|
{
|
||||||
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
Vec3d scaling_factor = scale;
|
Vec3d scaling_factor = scale;
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType transformation_type;
|
||||||
|
if (is_local_coordinates())
|
||||||
|
transformation_type.set_local();
|
||||||
|
else if (is_instance_coordinates())
|
||||||
|
transformation_type.set_instance();
|
||||||
|
|
||||||
|
if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier())
|
||||||
|
transformation_type.set_relative();
|
||||||
|
|
||||||
|
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
|
||||||
|
#else
|
||||||
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance()) {
|
||||||
transformation_type.set_absolute();
|
transformation_type.set_absolute();
|
||||||
@ -922,12 +1207,31 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
|||||||
|
|
||||||
if (m_uniform_scale || selection.requires_uniform_scale())
|
if (m_uniform_scale || selection.requires_uniform_scale())
|
||||||
scaling_factor = scale(axis) * Vec3d::Ones();
|
scaling_factor = scale(axis) * Vec3d::Ones();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
selection.setup_cache();
|
selection.setup_cache();
|
||||||
selection.scale(scaling_factor, transformation_type);
|
selection.scale(scaling_factor, transformation_type);
|
||||||
wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
|
wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void ObjectManipulation::do_size(int axis, const Vec3d& scale) const
|
||||||
|
{
|
||||||
|
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
|
||||||
|
TransformationType transformation_type;
|
||||||
|
if (is_local_coordinates())
|
||||||
|
transformation_type.set_local();
|
||||||
|
else if (is_instance_coordinates())
|
||||||
|
transformation_type.set_instance();
|
||||||
|
|
||||||
|
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
|
||||||
|
selection.setup_cache();
|
||||||
|
selection.scale(scaling_factor, transformation_type);
|
||||||
|
wxGetApp().plater()->canvas3D()->do_scale(L("Set Size"));
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void ObjectManipulation::on_change(const std::string& opt_key, int axis, double new_value)
|
void ObjectManipulation::on_change(const std::string& opt_key, int axis, double new_value)
|
||||||
{
|
{
|
||||||
if (!m_cache.is_valid())
|
if (!m_cache.is_valid())
|
||||||
@ -962,15 +1266,24 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectManipulation::set_uniform_scaling(const bool new_value)
|
void ObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
|
||||||
{
|
{
|
||||||
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
|
if (!use_uniform_scale)
|
||||||
|
// Recalculate cached values at this panel, refresh the screen.
|
||||||
|
this->UpdateAndShow(true);
|
||||||
|
|
||||||
|
m_uniform_scale = use_uniform_scale;
|
||||||
|
|
||||||
|
set_dirty();
|
||||||
|
#else
|
||||||
|
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
if (selection.is_single_full_instance() && m_world_coordinates && !use_uniform_scale) {
|
||||||
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
||||||
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
// Is the angle close to a multiple of 90 degrees?
|
// Is the angle close to a multiple of 90 degrees?
|
||||||
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
|
if (!Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
|
||||||
// Cannot apply scaling in the world coordinate system.
|
// Cannot apply scaling in the world coordinate system.
|
||||||
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
|
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
|
||||||
MessageDialog dlg(GUI::wxGetApp().mainframe,
|
MessageDialog dlg(GUI::wxGetApp().mainframe,
|
||||||
@ -994,9 +1307,29 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
|
|||||||
this->UpdateAndShow(true);
|
this->UpdateAndShow(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_uniform_scale = new_value;
|
|
||||||
|
m_uniform_scale = use_uniform_scale;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void ObjectManipulation::set_coordinates_type(ECoordinatesType type)
|
||||||
|
{
|
||||||
|
if (wxGetApp().get_mode() == comSimple)
|
||||||
|
type = ECoordinatesType::World;
|
||||||
|
|
||||||
|
if (m_coordinates_type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_coordinates_type = type;
|
||||||
|
this->UpdateAndShow(true);
|
||||||
|
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||||
|
canvas->get_gizmos_manager().update_data();
|
||||||
|
canvas->set_as_dirty();
|
||||||
|
canvas->request_extra_frame();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void ObjectManipulation::msw_rescale()
|
void ObjectManipulation::msw_rescale()
|
||||||
{
|
{
|
||||||
const int em = wxGetApp().em_unit();
|
const int em = wxGetApp().em_unit();
|
||||||
@ -1014,6 +1347,9 @@ void ObjectManipulation::msw_rescale()
|
|||||||
m_mirror_bitmap_hidden.msw_rescale();
|
m_mirror_bitmap_hidden.msw_rescale();
|
||||||
m_reset_scale_button->msw_rescale();
|
m_reset_scale_button->msw_rescale();
|
||||||
m_reset_rotation_button->msw_rescale();
|
m_reset_rotation_button->msw_rescale();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_reset_skew_button->msw_rescale();
|
||||||
|
#endif /// ENABLE_WORLD_COORDINATE
|
||||||
m_drop_to_bed_button->msw_rescale();
|
m_drop_to_bed_button->msw_rescale();
|
||||||
m_lock_bnt->msw_rescale();
|
m_lock_bnt->msw_rescale();
|
||||||
|
|
||||||
@ -1053,6 +1389,9 @@ void ObjectManipulation::sys_color_changed()
|
|||||||
m_mirror_bitmap_hidden.msw_rescale();
|
m_mirror_bitmap_hidden.msw_rescale();
|
||||||
m_reset_scale_button->msw_rescale();
|
m_reset_scale_button->msw_rescale();
|
||||||
m_reset_rotation_button->msw_rescale();
|
m_reset_rotation_button->msw_rescale();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_reset_skew_button->msw_rescale();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_drop_to_bed_button->msw_rescale();
|
m_drop_to_bed_button->msw_rescale();
|
||||||
m_lock_bnt->msw_rescale();
|
m_lock_bnt->msw_rescale();
|
||||||
|
|
||||||
@ -1060,6 +1399,19 @@ void ObjectManipulation::sys_color_changed()
|
|||||||
m_mirror_buttons[id].first->msw_rescale();
|
m_mirror_buttons[id].first->msw_rescale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void ObjectManipulation::set_coordinates_type(const wxString& type_string)
|
||||||
|
{
|
||||||
|
ECoordinatesType type = ECoordinatesType::World;
|
||||||
|
if (type_string == coordinate_type_str(ECoordinatesType::Instance))
|
||||||
|
type = ECoordinatesType::Instance;
|
||||||
|
else if (type_string == coordinate_type_str(ECoordinatesType::Local))
|
||||||
|
type = ECoordinatesType::Local;
|
||||||
|
|
||||||
|
this->set_coordinates_type(type);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
static const char axes[] = { 'x', 'y', 'z' };
|
static const char axes[] = { 'x', 'y', 'z' };
|
||||||
ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
||||||
const std::string& opt_key,
|
const std::string& opt_key,
|
||||||
@ -1101,8 +1453,8 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
|||||||
parent->set_focused_editor(nullptr);
|
parent->set_focused_editor(nullptr);
|
||||||
|
|
||||||
#if ENABLE_OBJECT_MANIPULATOR_FOCUS
|
#if ENABLE_OBJECT_MANIPULATOR_FOCUS
|
||||||
// if the widgets exchanging focus are both manipulator fields, call kill_focus
|
// if the widgets loosing focus is a manipulator field, call kill_focus
|
||||||
if (dynamic_cast<ManipulationEditor*>(e.GetEventObject()) != nullptr && dynamic_cast<ManipulationEditor*>(e.GetWindow()) != nullptr)
|
if (dynamic_cast<ManipulationEditor*>(e.GetEventObject()) != nullptr)
|
||||||
#else
|
#else
|
||||||
if (!m_enter_pressed)
|
if (!m_enter_pressed)
|
||||||
#endif // ENABLE_OBJECT_MANIPULATOR_FOCUS
|
#endif // ENABLE_OBJECT_MANIPULATOR_FOCUS
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include "GUI_ObjectSettings.hpp"
|
#include "GUI_ObjectSettings.hpp"
|
||||||
#include "GUI_ObjectList.hpp"
|
#include "GUI_ObjectList.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "GUI_Geometry.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
@ -57,6 +60,10 @@ public:
|
|||||||
void set_value(const wxString& new_value);
|
void set_value(const wxString& new_value);
|
||||||
void kill_focus(ObjectManipulation *parent);
|
void kill_focus(ObjectManipulation *parent);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const std::string& get_full_opt_name() const { return m_full_opt_name; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double get_value();
|
double get_value();
|
||||||
};
|
};
|
||||||
@ -113,9 +120,12 @@ private:
|
|||||||
wxStaticText* m_empty_str = nullptr;
|
wxStaticText* m_empty_str = nullptr;
|
||||||
|
|
||||||
// Non-owning pointers to the reset buttons, so we can hide and show them.
|
// Non-owning pointers to the reset buttons, so we can hide and show them.
|
||||||
ScalableButton* m_reset_scale_button = nullptr;
|
ScalableButton* m_reset_scale_button{ nullptr };
|
||||||
ScalableButton* m_reset_rotation_button = nullptr;
|
ScalableButton* m_reset_rotation_button{ nullptr };
|
||||||
ScalableButton* m_drop_to_bed_button = nullptr;
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ScalableButton* m_reset_skew_button{ nullptr };
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
ScalableButton* m_drop_to_bed_button{ nullptr };
|
||||||
|
|
||||||
wxCheckBox* m_check_inch {nullptr};
|
wxCheckBox* m_check_inch {nullptr};
|
||||||
|
|
||||||
@ -144,22 +154,35 @@ private:
|
|||||||
Vec3d m_new_size;
|
Vec3d m_new_size;
|
||||||
bool m_new_enabled {true};
|
bool m_new_enabled {true};
|
||||||
bool m_uniform_scale {true};
|
bool m_uniform_scale {true};
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
|
||||||
|
#else
|
||||||
// Does the object manipulation panel work in World or Local coordinates?
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
bool m_world_coordinates = true;
|
bool m_world_coordinates = true;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
LockButton* m_lock_bnt{ nullptr };
|
LockButton* m_lock_bnt{ nullptr };
|
||||||
choice_ctrl* m_word_local_combo { nullptr };
|
choice_ctrl* m_word_local_combo { nullptr };
|
||||||
|
|
||||||
ScalableBitmap m_manifold_warning_bmp;
|
ScalableBitmap m_manifold_warning_bmp;
|
||||||
wxStaticBitmap* m_fix_throught_netfab_bitmap;
|
wxStaticBitmap* m_fix_throught_netfab_bitmap;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Currently focused editor (nullptr if none)
|
||||||
|
ManipulationEditor* m_focused_editor{ nullptr };
|
||||||
|
#else
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
// Currently focused editor (nullptr if none)
|
// Currently focused editor (nullptr if none)
|
||||||
ManipulationEditor* m_focused_editor {nullptr};
|
ManipulationEditor* m_focused_editor {nullptr};
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
wxFlexGridSizer* m_main_grid_sizer;
|
wxFlexGridSizer* m_main_grid_sizer;
|
||||||
wxFlexGridSizer* m_labels_grid_sizer;
|
wxFlexGridSizer* m_labels_grid_sizer;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
wxStaticText* m_skew_label{ nullptr };
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// sizers, used for msw_rescale
|
// sizers, used for msw_rescale
|
||||||
wxBoxSizer* m_word_local_combo_sizer;
|
wxBoxSizer* m_word_local_combo_sizer;
|
||||||
std::vector<wxBoxSizer*> m_rescalable_sizers;
|
std::vector<wxBoxSizer*> m_rescalable_sizers;
|
||||||
@ -180,11 +203,19 @@ public:
|
|||||||
// Called from the App to update the UI if dirty.
|
// Called from the App to update the UI if dirty.
|
||||||
void update_if_dirty();
|
void update_if_dirty();
|
||||||
|
|
||||||
void set_uniform_scaling(const bool uniform_scale);
|
void set_uniform_scaling(const bool use_uniform_scale);
|
||||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_coordinates_type(ECoordinatesType type);
|
||||||
|
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
|
||||||
|
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
||||||
|
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
||||||
|
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
||||||
|
#else
|
||||||
// Does the object manipulation panel work in World or Local coordinates?
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
|
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
|
||||||
bool get_world_coordinates() const { return m_world_coordinates; }
|
bool get_world_coordinates() const { return m_world_coordinates; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void reset_cache() { m_cache.reset(); }
|
void reset_cache() { m_cache.reset(); }
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
@ -200,11 +231,23 @@ public:
|
|||||||
void sys_color_changed();
|
void sys_color_changed();
|
||||||
void on_change(const std::string& opt_key, int axis, double new_value);
|
void on_change(const std::string& opt_key, int axis, double new_value);
|
||||||
void set_focused_editor(ManipulationEditor* focused_editor) {
|
void set_focused_editor(ManipulationEditor* focused_editor) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_focused_editor = focused_editor;
|
||||||
|
#else
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
m_focused_editor = focused_editor;
|
m_focused_editor = focused_editor;
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ManipulationEditor* get_focused_editor() { return m_focused_editor; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
static wxString coordinate_type_str(ECoordinatesType type);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset_settings_value();
|
void reset_settings_value();
|
||||||
void update_settings_value(const Selection& selection);
|
void update_settings_value(const Selection& selection);
|
||||||
@ -220,6 +263,11 @@ private:
|
|||||||
void change_scale_value(int axis, double value);
|
void change_scale_value(int axis, double value);
|
||||||
void change_size_value(int axis, double value);
|
void change_size_value(int axis, double value);
|
||||||
void do_scale(int axis, const Vec3d &scale) const;
|
void do_scale(int axis, const Vec3d &scale) const;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void do_size(int axis, const Vec3d& scale) const;
|
||||||
|
|
||||||
|
void set_coordinates_type(const wxString& type_string);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -333,7 +333,11 @@ bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
|
|||||||
wxGetApp().obj_manipul()->set_dirty();
|
wxGetApp().obj_manipul()->set_dirty();
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
return true;
|
return true;
|
||||||
} else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) {
|
}
|
||||||
|
else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
do_stop_dragging(is_leaving);
|
||||||
|
#else
|
||||||
for (auto &grabber : m_grabbers) grabber.dragging = false;
|
for (auto &grabber : m_grabbers) grabber.dragging = false;
|
||||||
m_dragging = false;
|
m_dragging = false;
|
||||||
|
|
||||||
@ -356,12 +360,41 @@ bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
|
|||||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||||
// updates camera target constraints
|
// updates camera target constraints
|
||||||
m_parent.refresh_camera_scene_box();
|
m_parent.refresh_camera_scene_box();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup)
|
||||||
|
{
|
||||||
|
for (auto& grabber : m_grabbers) grabber.dragging = false;
|
||||||
|
m_dragging = false;
|
||||||
|
|
||||||
|
// NOTE: This should be part of GLCanvas3D
|
||||||
|
// Reset hover_id when leave window
|
||||||
|
if (perform_mouse_cleanup) m_parent.mouse_up_cleanup();
|
||||||
|
|
||||||
|
on_stop_dragging();
|
||||||
|
|
||||||
|
// There is prediction that after draggign, data are changed
|
||||||
|
// Data are updated twice also by canvas3D::reload_scene.
|
||||||
|
// Should be fixed.
|
||||||
|
m_parent.get_gizmos_manager().update_data();
|
||||||
|
|
||||||
|
wxGetApp().obj_manipul()->set_dirty();
|
||||||
|
|
||||||
|
// Let the plater know that the dragging finished, so a delayed
|
||||||
|
// refresh of the scene with the background processing data should
|
||||||
|
// be performed.
|
||||||
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
||||||
|
// updates camera target constraints
|
||||||
|
m_parent.refresh_camera_scene_box();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
std::string GLGizmoBase::format(float value, unsigned int decimals) const
|
std::string GLGizmoBase::format(float value, unsigned int decimals) const
|
||||||
{
|
{
|
||||||
return Slic3r::string_printf("%.*f", decimals, value);
|
return Slic3r::string_printf("%.*f", decimals, value);
|
||||||
|
@ -227,6 +227,11 @@ protected:
|
|||||||
/// <param name="mouse_event">Keep information about mouse click</param>
|
/// <param name="mouse_event">Keep information about mouse click</param>
|
||||||
/// <returns>same as on_mouse</returns>
|
/// <returns>same as on_mouse</returns>
|
||||||
bool use_grabbers(const wxMouseEvent &mouse_event);
|
bool use_grabbers(const wxMouseEvent &mouse_event);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void do_stop_dragging(bool perform_mouse_cleanup);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Flag for dirty visible state of Gizmo
|
// Flag for dirty visible state of Gizmo
|
||||||
// When True then need new rendering
|
// When True then need new rendering
|
||||||
|
@ -312,7 +312,7 @@ void GLGizmoCut::perform_cut(const Selection& selection)
|
|||||||
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
|
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
|
||||||
|
|
||||||
// m_cut_z is the distance from the bed. Subtract possible SLA elevation.
|
// m_cut_z is the distance from the bed. Subtract possible SLA elevation.
|
||||||
const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* first_glvolume = selection.get_first_volume();
|
||||||
const double object_cut_z = m_cut_z - first_glvolume->get_sla_shift_z();
|
const double object_cut_z = m_cut_z - first_glvolume->get_sla_shift_z();
|
||||||
|
|
||||||
if (0.0 < object_cut_z && object_cut_z < m_max_z)
|
if (0.0 < object_cut_z && object_cut_z < m_max_z)
|
||||||
@ -365,7 +365,7 @@ BoundingBoxf3 GLGizmoCut::bounding_box() const
|
|||||||
void GLGizmoCut::update_contours()
|
void GLGizmoCut::update_contours()
|
||||||
{
|
{
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* first_glvolume = selection.get_first_volume();
|
||||||
const BoundingBoxf3& box = first_glvolume->transformed_convex_hull_bounding_box();
|
const BoundingBoxf3& box = first_glvolume->transformed_convex_hull_bounding_box();
|
||||||
|
|
||||||
const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()];
|
const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()];
|
||||||
|
@ -341,7 +341,11 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
|||||||
|
|
||||||
++mesh_id;
|
++mesh_id;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d trafo_matrix = mi->get_matrix_no_offset() * mv->get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
|
const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
Vec3f down = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
|
Vec3f down = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
|
||||||
Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();
|
Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();
|
||||||
|
|
||||||
|
@ -118,17 +118,17 @@ void GLGizmoFlatten::on_render()
|
|||||||
glsafe(::glEnable(GL_BLEND));
|
glsafe(::glEnable(GL_BLEND));
|
||||||
|
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance()) {
|
||||||
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
const Transform3d& m = selection.get_first_volume()->get_instance_transformation().get_matrix();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
||||||
|
|
||||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#else
|
#else
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()));
|
glsafe(::glTranslatef(0.f, 0.f, selection.get_first_volume()->get_sla_shift_z()));
|
||||||
glsafe(::glMultMatrixd(m.data()));
|
glsafe(::glMultMatrixd(m.data()));
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
if (this->is_plane_update_necessary())
|
if (this->is_plane_update_necessary())
|
||||||
@ -172,17 +172,17 @@ void GLGizmoFlatten::on_render_for_picking()
|
|||||||
glsafe(::glDisable(GL_BLEND));
|
glsafe(::glDisable(GL_BLEND));
|
||||||
|
|
||||||
if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) {
|
if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) {
|
||||||
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
const Transform3d& m = selection.get_first_volume()->get_instance_transformation().get_matrix();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
||||||
|
|
||||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#else
|
#else
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()));
|
glsafe(::glTranslatef(0.f, 0.f, selection.get_first_volume()->get_sla_shift_z()));
|
||||||
glsafe(::glMultMatrixd(m.data()));
|
glsafe(::glMultMatrixd(m.data()));
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
if (this->is_plane_update_necessary())
|
if (this->is_plane_update_necessary())
|
||||||
@ -228,7 +228,11 @@ void GLGizmoFlatten::update_planes()
|
|||||||
}
|
}
|
||||||
ch = ch.convex_hull_3d();
|
ch = ch.convex_hull_3d();
|
||||||
m_planes.clear();
|
m_planes.clear();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d inst_matrix = mo->instances.front()->get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d& inst_matrix = mo->instances.front()->get_matrix(true);
|
const Transform3d& inst_matrix = mo->instances.front()->get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// Following constants are used for discarding too small polygons.
|
// Following constants are used for discarding too small polygons.
|
||||||
const float minimal_area = 5.f; // in square mm (world coordinates)
|
const float minimal_area = 5.f; // in square mm (world coordinates)
|
||||||
|
@ -94,7 +94,7 @@ void GLGizmoHollow::on_render_for_picking()
|
|||||||
{
|
{
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
//#if ENABLE_RENDER_PICKING_PASS
|
//#if ENABLE_RENDER_PICKING_PASS
|
||||||
// m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z();
|
// m_z_shift = selection.get_first_volume()->get_sla_shift_z();
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
@ -117,12 +117,16 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
|||||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* vol = selection.get_first_volume();
|
||||||
Geometry::Transformation trafo = vol->get_instance_transformation() * vol->get_volume_transformation();
|
Geometry::Transformation trafo = vol->get_instance_transformation() * vol->get_volume_transformation();
|
||||||
|
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_scaling_factor_matrix().inverse();
|
||||||
|
#else
|
||||||
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
|
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
|
||||||
const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix();
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_matrix = Geometry::translation_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix();
|
||||||
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||||
@ -238,7 +242,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
|
|||||||
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
||||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#include "GLGizmoMove.hpp"
|
#include "GLGizmoMove.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
@ -21,18 +24,29 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
|
|||||||
|
|
||||||
std::string GLGizmoMove3D::get_tooltip() const
|
std::string GLGizmoMove3D::get_tooltip() const
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (m_hover_id == 0)
|
||||||
|
return "X: " + format(m_displacement.x(), 2);
|
||||||
|
else if (m_hover_id == 1)
|
||||||
|
return "Y: " + format(m_displacement.y(), 2);
|
||||||
|
else if (m_hover_id == 2)
|
||||||
|
return "Z: " + format(m_displacement.z(), 2);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
#else
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
bool show_position = selection.is_single_full_instance();
|
const bool show_position = selection.is_single_full_instance();
|
||||||
const Vec3d& position = selection.get_bounding_box().center();
|
const Vec3d& position = selection.get_bounding_box().center();
|
||||||
|
|
||||||
if (m_hover_id == 0 || m_grabbers[0].dragging)
|
if (m_hover_id == 0 || m_grabbers[0].dragging)
|
||||||
return "X: " + format(show_position ? position(0) : m_displacement(0), 2);
|
return "X: " + format(show_position ? position.x() : m_displacement.x(), 2);
|
||||||
else if (m_hover_id == 1 || m_grabbers[1].dragging)
|
else if (m_hover_id == 1 || m_grabbers[1].dragging)
|
||||||
return "Y: " + format(show_position ? position(1) : m_displacement(1), 2);
|
return "Y: " + format(show_position ? position.y() : m_displacement.y(), 2);
|
||||||
else if (m_hover_id == 2 || m_grabbers[2].dragging)
|
else if (m_hover_id == 2 || m_grabbers[2].dragging)
|
||||||
return "Z: " + format(show_position ? position(2) : m_displacement(2), 2);
|
return "Z: " + format(show_position ? position.z() : m_displacement.z(), 2);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
|
bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
|
||||||
@ -40,9 +54,7 @@ bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::data_changed() {
|
void GLGizmoMove3D::data_changed() {
|
||||||
const Selection &selection = m_parent.get_selection();
|
m_grabbers[2].enabled = !m_parent.get_selection().is_wipe_tower();
|
||||||
bool is_wipe_tower = selection.is_wipe_tower();
|
|
||||||
m_grabbers[2].enabled = !is_wipe_tower;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoMove3D::on_init()
|
bool GLGizmoMove3D::on_init()
|
||||||
@ -79,11 +91,29 @@ void GLGizmoMove3D::on_start_dragging()
|
|||||||
assert(m_hover_id != -1);
|
assert(m_hover_id != -1);
|
||||||
|
|
||||||
m_displacement = Vec3d::Zero();
|
m_displacement = Vec3d::Zero();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
|
if (coordinates_type == ECoordinatesType::World)
|
||||||
|
m_starting_drag_position = m_center + m_grabbers[m_hover_id].center;
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_starting_drag_position = m_center + v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix() * m_grabbers[m_hover_id].center;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_starting_drag_position = m_center + v.get_instance_transformation().get_rotation_matrix() * m_grabbers[m_hover_id].center;
|
||||||
|
}
|
||||||
|
m_starting_box_center = m_center;
|
||||||
|
m_starting_box_bottom_center = m_center;
|
||||||
|
m_starting_box_bottom_center.z() = m_bounding_box.min.z();
|
||||||
|
#else
|
||||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||||
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
||||||
m_starting_box_center = box.center();
|
m_starting_box_center = box.center();
|
||||||
m_starting_box_bottom_center = box.center();
|
m_starting_box_bottom_center = box.center();
|
||||||
m_starting_box_bottom_center(2) = box.min(2);
|
m_starting_box_bottom_center.z() = box.min.z();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::on_stop_dragging()
|
void GLGizmoMove3D::on_stop_dragging()
|
||||||
@ -102,7 +132,19 @@ void GLGizmoMove3D::on_dragging(const UpdateData& data)
|
|||||||
m_displacement.z() = calc_projection(data);
|
m_displacement.z() = calc_projection(data);
|
||||||
|
|
||||||
Selection &selection = m_parent.get_selection();
|
Selection &selection = m_parent.get_selection();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
TransformationType trafo_type;
|
||||||
|
trafo_type.set_relative();
|
||||||
|
switch (wxGetApp().obj_manipul()->get_coordinates_type())
|
||||||
|
{
|
||||||
|
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
|
||||||
|
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
selection.translate(m_displacement, trafo_type);
|
||||||
|
#else
|
||||||
selection.translate(m_displacement);
|
selection.translate(m_displacement);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::on_render()
|
void GLGizmoMove3D::on_render()
|
||||||
@ -112,11 +154,39 @@ void GLGizmoMove3D::on_render()
|
|||||||
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
|
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
|
||||||
|
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
glsafe(::glPushMatrix());
|
||||||
|
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
calc_selection_box_and_center();
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
const Transform3d base_matrix = local_transform(m_parent.get_selection());
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
m_grabbers[i].matrix = base_matrix;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
transform_to_local(m_parent.get_selection());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
const Vec3d zero = Vec3d::Zero();
|
||||||
|
const Vec3d half_box_size = 0.5 * m_bounding_box.size();
|
||||||
|
|
||||||
|
// x axis
|
||||||
|
m_grabbers[0].center = { half_box_size.x() + Offset, 0.0, 0.0 };
|
||||||
|
m_grabbers[0].color = AXES_COLOR[0];
|
||||||
|
|
||||||
|
// y axis
|
||||||
|
m_grabbers[1].center = { 0.0, half_box_size.y() + Offset, 0.0 };
|
||||||
|
m_grabbers[1].color = AXES_COLOR[1];
|
||||||
|
|
||||||
|
// z axis
|
||||||
|
m_grabbers[2].center = { 0.0, 0.0, half_box_size.z() + Offset };
|
||||||
|
m_grabbers[2].color = AXES_COLOR[2];
|
||||||
|
#else
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
const Vec3d& center = box.center();
|
const Vec3d& center = box.center();
|
||||||
|
|
||||||
@ -131,14 +201,24 @@ void GLGizmoMove3D::on_render()
|
|||||||
// z axis
|
// z axis
|
||||||
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
|
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
|
||||||
m_grabbers[2].color = AXES_COLOR[2];
|
m_grabbers[2].color = AXES_COLOR[2];
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||||
|
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
auto render_grabber_connection = [this, &zero](unsigned int id) {
|
||||||
|
#else
|
||||||
auto render_grabber_connection = [this, ¢er](unsigned int id) {
|
auto render_grabber_connection = [this, ¢er](unsigned int id) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
if (m_grabbers[id].enabled) {
|
if (m_grabbers[id].enabled) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(m_grabbers[id].center)) {
|
||||||
|
m_grabber_connections[id].old_center = m_grabbers[id].center;
|
||||||
|
#else
|
||||||
if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
|
if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
|
||||||
m_grabber_connections[id].old_center = center;
|
m_grabber_connections[id].old_center = center;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_grabber_connections[id].model.reset();
|
m_grabber_connections[id].model.reset();
|
||||||
|
|
||||||
GLModel::Geometry init_data;
|
GLModel::Geometry init_data;
|
||||||
@ -148,7 +228,11 @@ void GLGizmoMove3D::on_render()
|
|||||||
init_data.reserve_indices(2);
|
init_data.reserve_indices(2);
|
||||||
|
|
||||||
// vertices
|
// vertices
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
init_data.add_vertex((Vec3f)zero.cast<float>());
|
||||||
|
#else
|
||||||
init_data.add_vertex((Vec3f)center.cast<float>());
|
init_data.add_vertex((Vec3f)center.cast<float>());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
|
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
|
||||||
|
|
||||||
// indices
|
// indices
|
||||||
@ -171,7 +255,11 @@ void GLGizmoMove3D::on_render()
|
|||||||
|
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
@ -183,7 +271,11 @@ void GLGizmoMove3D::on_render()
|
|||||||
if (m_grabbers[i].enabled) {
|
if (m_grabbers[i].enabled) {
|
||||||
glsafe(::glColor4fv(AXES_COLOR[i].data()));
|
glsafe(::glColor4fv(AXES_COLOR[i].data()));
|
||||||
::glBegin(GL_LINES);
|
::glBegin(GL_LINES);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
::glVertex3dv(zero.data());
|
||||||
|
#else
|
||||||
::glVertex3dv(center.data());
|
::glVertex3dv(center.data());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
::glVertex3dv(m_grabbers[i].center.data());
|
::glVertex3dv(m_grabbers[i].center.data());
|
||||||
glsafe(::glEnd());
|
glsafe(::glEnd());
|
||||||
}
|
}
|
||||||
@ -196,6 +288,19 @@ void GLGizmoMove3D::on_render()
|
|||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
// draw grabbers
|
// draw grabbers
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
render_grabbers(m_bounding_box);
|
||||||
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
|
if (m_grabbers[i].enabled)
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_grabber_extension((Axis)i, base_matrix, m_bounding_box, false);
|
||||||
|
#else
|
||||||
|
render_grabber_extension((Axis)i, m_bounding_box, false);
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
}
|
||||||
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#else
|
||||||
render_grabbers(box);
|
render_grabbers(box);
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
for (unsigned int i = 0; i < 3; ++i) {
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
@ -203,6 +308,7 @@ void GLGizmoMove3D::on_render()
|
|||||||
render_grabber_extension((Axis)i, box, false);
|
render_grabber_extension((Axis)i, box, false);
|
||||||
}
|
}
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// draw axis
|
// draw axis
|
||||||
@ -213,7 +319,11 @@ void GLGizmoMove3D::on_render()
|
|||||||
|
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix()* base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
@ -225,7 +335,11 @@ void GLGizmoMove3D::on_render()
|
|||||||
#else
|
#else
|
||||||
glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data()));
|
glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data()));
|
||||||
::glBegin(GL_LINES);
|
::glBegin(GL_LINES);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
::glVertex3dv(zero.data());
|
||||||
|
#else
|
||||||
::glVertex3dv(center.data());
|
::glVertex3dv(center.data());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
::glVertex3dv(m_grabbers[m_hover_id].center.data());
|
::glVertex3dv(m_grabbers[m_hover_id].center.data());
|
||||||
glsafe(::glEnd());
|
glsafe(::glEnd());
|
||||||
|
|
||||||
@ -235,20 +349,65 @@ void GLGizmoMove3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.1f);
|
shader->set_uniform("emission_factor", 0.1f);
|
||||||
// draw grabber
|
// draw grabber
|
||||||
const float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Vec3d box_size = m_bounding_box.size();
|
||||||
|
#else
|
||||||
|
const Vec3d box_size = box.size();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
const float mean_size = (float)((box_size.x() + box_size.y() + box_size.z()) / 3.0);
|
||||||
m_grabbers[m_hover_id].render(true, mean_size);
|
m_grabbers[m_hover_id].render(true, mean_size);
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
}
|
}
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_grabber_extension((Axis)m_hover_id, base_matrix, m_bounding_box, false);
|
||||||
|
#else
|
||||||
|
render_grabber_extension((Axis)m_hover_id, m_bounding_box, false);
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#else
|
||||||
render_grabber_extension((Axis)m_hover_id, box, false);
|
render_grabber_extension((Axis)m_hover_id, box, false);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
glsafe(::glPopMatrix());
|
||||||
|
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::on_render_for_picking()
|
void GLGizmoMove3D::on_render_for_picking()
|
||||||
{
|
{
|
||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
const Transform3d base_matrix = local_transform(m_parent.get_selection());
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
m_grabbers[i].matrix = base_matrix;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
glsafe(::glPushMatrix());
|
||||||
|
transform_to_local(m_parent.get_selection());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_grabbers_for_picking(m_bounding_box);
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
render_grabber_extension(X, base_matrix, m_bounding_box, true);
|
||||||
|
render_grabber_extension(Y, base_matrix, m_bounding_box, true);
|
||||||
|
render_grabber_extension(Z, base_matrix, m_bounding_box, true);
|
||||||
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#else
|
||||||
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
render_grabber_extension(X, m_bounding_box, true);
|
||||||
|
render_grabber_extension(Y, m_bounding_box, true);
|
||||||
|
render_grabber_extension(Z, m_bounding_box, true);
|
||||||
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
glsafe(::glPopMatrix());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#else
|
||||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||||
render_grabbers_for_picking(box);
|
render_grabbers_for_picking(box);
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
@ -256,23 +415,24 @@ void GLGizmoMove3D::on_render_for_picking()
|
|||||||
render_grabber_extension(Y, box, true);
|
render_grabber_extension(Y, box, true);
|
||||||
render_grabber_extension(Z, box, true);
|
render_grabber_extension(Z, box, true);
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
||||||
{
|
{
|
||||||
double projection = 0.0;
|
double projection = 0.0;
|
||||||
|
|
||||||
Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
|
const Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
|
||||||
double len_starting_vec = starting_vec.norm();
|
const double len_starting_vec = starting_vec.norm();
|
||||||
if (len_starting_vec != 0.0) {
|
if (len_starting_vec != 0.0) {
|
||||||
Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
const Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
||||||
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
||||||
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
|
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
|
||||||
// in our case plane normal and ray direction are the same (orthogonal view)
|
// in our case plane normal and ray direction are the same (orthogonal view)
|
||||||
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
|
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
|
||||||
Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
|
const Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
|
||||||
// vector from the starting position to the found intersection
|
// vector from the starting position to the found intersection
|
||||||
Vec3d inters_vec = inters - m_starting_drag_position;
|
const Vec3d inters_vec = inters - m_starting_drag_position;
|
||||||
|
|
||||||
// finds projection of the vector along the staring direction
|
// finds projection of the vector along the staring direction
|
||||||
projection = inters_vec.dot(starting_vec.normalized());
|
projection = inters_vec.dot(starting_vec.normalized());
|
||||||
@ -285,9 +445,14 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#if ENABLE_WORLD_COORDINATE && ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
void GLGizmoMove3D::render_grabber_extension(Axis axis, const Transform3d& base_matrix, const BoundingBoxf3& box, bool picking)
|
||||||
|
#else
|
||||||
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking)
|
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking)
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE && ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
{
|
{
|
||||||
const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
|
const Vec3d box_size = box.size();
|
||||||
|
const float mean_size = float((box_size.x() + box_size.y() + box_size.z()) / 3.0);
|
||||||
const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
|
const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
|
||||||
|
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
@ -312,7 +477,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
|||||||
|
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_grabbers[axis].center);
|
Transform3d view_model_matrix = camera.get_view_matrix() * base_matrix * Geometry::assemble_transform(m_grabbers[axis].center);
|
||||||
if (axis == X)
|
if (axis == X)
|
||||||
view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
|
view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
|
||||||
else if (axis == Y)
|
else if (axis == Y)
|
||||||
@ -345,5 +510,62 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
|||||||
}
|
}
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
Transform3d GLGizmoMove3D::local_transform(const Selection& selection) const
|
||||||
|
{
|
||||||
|
Transform3d ret = Geometry::assemble_transform(m_center);
|
||||||
|
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
Transform3d orient_matrix = v.get_instance_transformation().get_rotation_matrix();
|
||||||
|
if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
|
orient_matrix = orient_matrix * v.get_volume_transformation().get_rotation_matrix();
|
||||||
|
ret = ret * orient_matrix;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void GLGizmoMove3D::transform_to_local(const Selection& selection) const
|
||||||
|
{
|
||||||
|
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||||
|
|
||||||
|
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
Transform3d orient_matrix = v.get_instance_transformation().get_matrix(true, false, true, true);
|
||||||
|
if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
|
orient_matrix = orient_matrix * v.get_volume_transformation().get_matrix(true, false, true, true);
|
||||||
|
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
void GLGizmoMove3D::calc_selection_box_and_center()
|
||||||
|
{
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
|
if (coordinates_type == ECoordinatesType::World) {
|
||||||
|
m_bounding_box = selection.get_bounding_box();
|
||||||
|
m_center = m_bounding_box.center();
|
||||||
|
}
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_bounding_box = v.transformed_convex_hull_bounding_box(
|
||||||
|
v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix());
|
||||||
|
m_center = v.world_matrix() * m_bounding_box.center();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_bounding_box.reset();
|
||||||
|
const Selection::IndicesList& ids = selection.get_volume_idxs();
|
||||||
|
for (unsigned int id : ids) {
|
||||||
|
const GLVolume& v = *selection.get_volume(id);
|
||||||
|
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||||
|
}
|
||||||
|
const Geometry::Transformation inst_trafo = selection.get_first_volume()->get_instance_transformation();
|
||||||
|
m_bounding_box = m_bounding_box.transformed(inst_trafo.get_scaling_factor_matrix());
|
||||||
|
m_center = inst_trafo.get_matrix_no_scaling_factor() * m_bounding_box.center();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -7,11 +7,19 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
class Selection;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
class GLGizmoMove3D : public GLGizmoBase
|
class GLGizmoMove3D : public GLGizmoBase
|
||||||
{
|
{
|
||||||
static const double Offset;
|
static const double Offset;
|
||||||
|
|
||||||
Vec3d m_displacement{ Vec3d::Zero() };
|
Vec3d m_displacement{ Vec3d::Zero() };
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d m_center{ Vec3d::Zero() };
|
||||||
|
BoundingBoxf3 m_bounding_box;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
double m_snap_step{ 1.0 };
|
double m_snap_step{ 1.0 };
|
||||||
Vec3d m_starting_drag_position{ Vec3d::Zero() };
|
Vec3d m_starting_drag_position{ Vec3d::Zero() };
|
||||||
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
||||||
@ -49,7 +57,6 @@ public:
|
|||||||
/// Detect reduction of move for wipetover on selection change
|
/// Detect reduction of move for wipetover on selection change
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void data_changed() override;
|
void data_changed() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool on_init() override;
|
bool on_init() override;
|
||||||
std::string on_get_name() const override;
|
std::string on_get_name() const override;
|
||||||
@ -62,11 +69,25 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
double calc_projection(const UpdateData& data) const;
|
double calc_projection(const UpdateData& data) const;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
Transform3d local_transform(const Selection& selection) const;
|
||||||
|
#else
|
||||||
|
void transform_to_local(const Selection& selection) const;
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
void calc_selection_box_and_center();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#if ENABLE_WORLD_COORDINATE && ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
void render_grabber_extension(Axis axis, const Transform3d& base_matrix, const BoundingBoxf3& box, bool picking);
|
||||||
|
#else
|
||||||
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking);
|
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE && ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -291,7 +291,11 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
|||||||
return;
|
return;
|
||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_scaling_factor_matrix().inverse();
|
||||||
|
#else
|
||||||
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
|
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed();
|
const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed();
|
||||||
|
|
||||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
@ -508,7 +512,11 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
const Selection &selection = m_parent.get_selection();
|
const Selection &selection = m_parent.get_selection();
|
||||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix_no_offset() * mo->volumes[m_rr.mesh_id]->get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true);
|
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
|
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
|
||||||
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle,
|
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle,
|
||||||
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
|
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
|
||||||
@ -547,7 +555,11 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||||
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
|
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
|
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// Precalculate transformations of individual meshes.
|
// Precalculate transformations of individual meshes.
|
||||||
std::vector<Transform3d> trafo_matrices;
|
std::vector<Transform3d> trafo_matrices;
|
||||||
@ -555,7 +567,11 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
for (const ModelVolume *mv : mo->volumes)
|
for (const ModelVolume *mv : mo->volumes)
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part()) {
|
||||||
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
|
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix_no_offset());
|
||||||
|
#else
|
||||||
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
|
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<ProjectedMousePosition>> projected_mouse_positions_by_mesh = get_projected_mouse_positions(mouse_position, 1., trafo_matrices);
|
std::vector<std::vector<ProjectedMousePosition>> projected_mouse_positions_by_mesh = get_projected_mouse_positions(mouse_position, 1., trafo_matrices);
|
||||||
@ -637,7 +653,11 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
|
||||||
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
|
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix_no_offset();
|
||||||
|
#else
|
||||||
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
|
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// Precalculate transformations of individual meshes.
|
// Precalculate transformations of individual meshes.
|
||||||
std::vector<Transform3d> trafo_matrices;
|
std::vector<Transform3d> trafo_matrices;
|
||||||
@ -645,7 +665,11 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
for (const ModelVolume *mv : mo->volumes)
|
for (const ModelVolume *mv : mo->volumes)
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part()) {
|
||||||
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
|
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix_no_offset());
|
||||||
|
#else
|
||||||
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
|
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now "click" into all the prepared points and spill paint around them.
|
// Now "click" into all the prepared points and spill paint around them.
|
||||||
|
@ -2,15 +2,18 @@
|
|||||||
#include "GLGizmoRotate.hpp"
|
#include "GLGizmoRotate.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
#include <GL/glew.h>
|
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
|
||||||
|
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
|
||||||
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
|
#include <GL/glew.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -99,6 +102,9 @@ bool GLGizmoRotate::on_init()
|
|||||||
|
|
||||||
void GLGizmoRotate::on_start_dragging()
|
void GLGizmoRotate::on_start_dragging()
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
init_data_from_selection(m_parent.get_selection());
|
||||||
|
#else
|
||||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||||
m_center = box.center();
|
m_center = box.center();
|
||||||
m_radius = Offset + box.radius();
|
m_radius = Offset + box.radius();
|
||||||
@ -106,6 +112,7 @@ void GLGizmoRotate::on_start_dragging()
|
|||||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||||
m_snap_fine_in_radius = m_radius;
|
m_snap_fine_in_radius = m_radius;
|
||||||
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoRotate::on_dragging(const UpdateData &data)
|
void GLGizmoRotate::on_dragging(const UpdateData &data)
|
||||||
@ -151,15 +158,21 @@ void GLGizmoRotate::on_render()
|
|||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
if (m_hover_id != 0 && !m_grabbers.front().dragging) {
|
if (m_hover_id != 0 && !m_grabbers.front().dragging) {
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
init_data_from_selection(selection);
|
||||||
|
#else
|
||||||
m_center = box.center();
|
m_center = box.center();
|
||||||
m_radius = Offset + box.radius();
|
m_radius = Offset + box.radius();
|
||||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||||
m_snap_fine_in_radius = m_radius;
|
m_snap_fine_in_radius = m_radius;
|
||||||
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
|
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
|
const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
|
||||||
@ -223,10 +236,17 @@ void GLGizmoRotate::on_render()
|
|||||||
render_angle();
|
render_angle();
|
||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
render_grabber(m_bounding_box);
|
||||||
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
render_grabber_extension(m_bounding_box, false);
|
||||||
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#else
|
||||||
render_grabber(box);
|
render_grabber(box);
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
render_grabber_extension(box, false);
|
render_grabber_extension(box, false);
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
@ -246,17 +266,73 @@ void GLGizmoRotate::on_render_for_picking()
|
|||||||
transform_to_local(selection);
|
transform_to_local(selection);
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
render_grabbers_for_picking(m_bounding_box);
|
||||||
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
render_grabber_extension(m_bounding_box, true);
|
||||||
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#else
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
render_grabbers_for_picking(box);
|
render_grabbers_for_picking(box);
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
render_grabber_extension(box, true);
|
render_grabber_extension(box, true);
|
||||||
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||||
|
{
|
||||||
|
ECoordinatesType coordinates_type;
|
||||||
|
if (selection.is_wipe_tower())
|
||||||
|
coordinates_type = ECoordinatesType::Local;
|
||||||
|
else
|
||||||
|
coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
|
if (coordinates_type == ECoordinatesType::World) {
|
||||||
|
m_bounding_box = selection.get_bounding_box();
|
||||||
|
m_center = m_bounding_box.center();
|
||||||
|
}
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_bounding_box = v.transformed_convex_hull_bounding_box(
|
||||||
|
v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix());
|
||||||
|
m_center = v.world_matrix() * m_bounding_box.center();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_bounding_box.reset();
|
||||||
|
const Selection::IndicesList& ids = selection.get_volume_idxs();
|
||||||
|
for (unsigned int id : ids) {
|
||||||
|
const GLVolume& v = *selection.get_volume(id);
|
||||||
|
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||||
|
}
|
||||||
|
const Geometry::Transformation inst_trafo = selection.get_first_volume()->get_instance_transformation();
|
||||||
|
m_bounding_box = m_bounding_box.transformed(inst_trafo.get_scaling_factor_matrix());
|
||||||
|
m_center = inst_trafo.get_matrix_no_scaling_factor() * m_bounding_box.center();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_radius = Offset + m_bounding_box.radius();
|
||||||
|
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||||
|
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||||
|
m_snap_fine_in_radius = m_radius;
|
||||||
|
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||||
|
|
||||||
|
if (coordinates_type == ECoordinatesType::World)
|
||||||
|
m_orient_matrix = Transform3d::Identity();
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local && (selection.is_wipe_tower() || selection.is_single_volume_or_modifier())) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_orient_matrix = v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_orient_matrix = v.get_instance_transformation().get_rotation_matrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
|
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
{
|
{
|
||||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||||
@ -317,10 +393,10 @@ void GLGizmoRotate::render_circle() const
|
|||||||
#else
|
#else
|
||||||
::glBegin(GL_LINE_LOOP);
|
::glBegin(GL_LINE_LOOP);
|
||||||
for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
|
for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
|
||||||
float angle = (float)i * ScaleStepRad;
|
const float angle = float(i) * ScaleStepRad;
|
||||||
float x = ::cos(angle) * m_radius;
|
const float x = ::cos(angle) * m_radius;
|
||||||
float y = ::sin(angle) * m_radius;
|
const float y = ::sin(angle) * m_radius;
|
||||||
float z = 0.0f;
|
const float z = 0.0f;
|
||||||
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||||
}
|
}
|
||||||
glsafe(::glEnd());
|
glsafe(::glEnd());
|
||||||
@ -519,10 +595,10 @@ void GLGizmoRotate::render_angle() const
|
|||||||
#else
|
#else
|
||||||
::glBegin(GL_LINE_STRIP);
|
::glBegin(GL_LINE_STRIP);
|
||||||
for (unsigned int i = 0; i <= AngleResolution; ++i) {
|
for (unsigned int i = 0; i <= AngleResolution; ++i) {
|
||||||
float angle = (float)i * step_angle;
|
const float angle = float(i) * step_angle;
|
||||||
float x = ::cos(angle) * ex_radius;
|
const float x = ::cos(angle) * ex_radius;
|
||||||
float y = ::sin(angle) * ex_radius;
|
const float y = ::sin(angle) * ex_radius;
|
||||||
float z = 0.0f;
|
const float z = 0.0f;
|
||||||
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||||
}
|
}
|
||||||
glsafe(::glEnd());
|
glsafe(::glEnd());
|
||||||
@ -661,12 +737,20 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
|
|||||||
{
|
{
|
||||||
case X:
|
case X:
|
||||||
{
|
{
|
||||||
ret = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.5 * PI, 0.0)) * Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, -0.5 * PI));
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ret = Geometry::rotation_transform(0.5 * PI * Vec3d::UnitY()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ());
|
||||||
|
#else
|
||||||
|
ret = Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY()) * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Y:
|
case Y:
|
||||||
{
|
{
|
||||||
ret = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, -0.5 * PI)) * Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, -0.5 * PI, 0.0));
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
ret = Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitY());
|
||||||
|
#else
|
||||||
|
ret = Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ()) * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitY());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -677,20 +761,28 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
return Geometry::translation_transform(m_center) * m_orient_matrix * ret;
|
||||||
|
#else
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||||
ret = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true) * ret;
|
ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret;
|
||||||
|
|
||||||
return Geometry::assemble_transform(m_center) * ret;
|
return Geometry::assemble_transform(m_center) * ret;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void GLGizmoRotate::transform_to_local(const Selection& selection) const
|
void GLGizmoRotate::transform_to_local(const Selection& selection) const
|
||||||
{
|
{
|
||||||
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
glsafe(::glMultMatrixd(m_orient_matrix.data()));
|
||||||
|
#else
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) {
|
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) {
|
||||||
const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
const Transform3d orient_matrix = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true);
|
||||||
glsafe(::glMultMatrixd(orient_matrix.data()));
|
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
switch (m_axis)
|
switch (m_axis)
|
||||||
{
|
{
|
||||||
@ -744,8 +836,12 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m = m * m_orient_matrix.inverse();
|
||||||
|
#else
|
||||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||||
m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse();
|
m = m * selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true).inverse();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
m.translate(-m_center);
|
m.translate(-m_center);
|
||||||
|
|
||||||
@ -766,31 +862,51 @@ bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
{
|
{
|
||||||
if (mouse_event.Dragging() && m_dragging) {
|
if (mouse_event.Dragging() && m_dragging) {
|
||||||
// Apply new temporary rotations
|
// Apply new temporary rotations
|
||||||
TransformationType transformation_type(
|
#if ENABLE_WORLD_COORDINATE
|
||||||
TransformationType::World_Relative_Joint);
|
TransformationType transformation_type;
|
||||||
if (mouse_event.AltDown()) transformation_type.set_independent();
|
if (m_parent.get_selection().is_wipe_tower())
|
||||||
|
transformation_type = TransformationType::Instance_Relative_Joint;
|
||||||
|
else {
|
||||||
|
switch (wxGetApp().obj_manipul()->get_coordinates_type())
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case ECoordinatesType::World: { transformation_type = TransformationType::World_Relative_Joint; break; }
|
||||||
|
case ECoordinatesType::Instance: { transformation_type = TransformationType::Instance_Relative_Joint; break; }
|
||||||
|
case ECoordinatesType::Local: { transformation_type = TransformationType::Local_Relative_Joint; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
if (mouse_event.AltDown())
|
||||||
|
transformation_type.set_independent();
|
||||||
m_parent.get_selection().rotate(get_rotation(), transformation_type);
|
m_parent.get_selection().rotate(get_rotation(), transformation_type);
|
||||||
}
|
}
|
||||||
return use_grabbers(mouse_event);
|
return use_grabbers(mouse_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoRotate3D::data_changed() {
|
void GLGizmoRotate3D::data_changed() {
|
||||||
const Selection &selection = m_parent.get_selection();
|
if (m_parent.get_selection().is_wipe_tower()) {
|
||||||
bool is_wipe_tower = selection.is_wipe_tower();
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
if (is_wipe_tower) {
|
const DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
const float wipe_tower_rotation_angle =
|
||||||
float wipe_tower_rotation_angle =
|
dynamic_cast<const ConfigOptionFloat*>(
|
||||||
dynamic_cast<const ConfigOptionFloat *>(
|
config.option("wipe_tower_rotation_angle"))->value;
|
||||||
config.option("wipe_tower_rotation_angle"))
|
|
||||||
->value;
|
|
||||||
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
m_gizmos[0].disable_grabber();
|
m_gizmos[0].disable_grabber();
|
||||||
m_gizmos[1].disable_grabber();
|
m_gizmos[1].disable_grabber();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
set_rotation(Vec3d::Zero());
|
set_rotation(Vec3d::Zero());
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
m_gizmos[0].enable_grabber();
|
m_gizmos[0].enable_grabber();
|
||||||
m_gizmos[1].enable_grabber();
|
m_gizmos[1].enable_grabber();
|
||||||
}
|
}
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
set_rotation(Vec3d::Zero());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoRotate3D::on_init()
|
bool GLGizmoRotate3D::on_init()
|
||||||
|
@ -34,6 +34,10 @@ private:
|
|||||||
float m_snap_coarse_out_radius{ 0.0f };
|
float m_snap_coarse_out_radius{ 0.0f };
|
||||||
float m_snap_fine_in_radius{ 0.0f };
|
float m_snap_fine_in_radius{ 0.0f };
|
||||||
float m_snap_fine_out_radius{ 0.0f };
|
float m_snap_fine_out_radius{ 0.0f };
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
BoundingBoxf3 m_bounding_box;
|
||||||
|
Transform3d m_orient_matrix{ Transform3d::Identity() };
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||||
GLModel m_cone;
|
GLModel m_cone;
|
||||||
@ -119,6 +123,10 @@ private:
|
|||||||
|
|
||||||
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
|
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
|
||||||
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
|
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void init_data_from_selection(const Selection& selection);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
class GLGizmoRotate3D : public GLGizmoBase
|
class GLGizmoRotate3D : public GLGizmoBase
|
||||||
@ -129,7 +137,7 @@ public:
|
|||||||
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
|
|
||||||
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
|
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
|
||||||
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
|
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation.x()); m_gizmos[Y].set_angle(rotation.y()); m_gizmos[Z].set_angle(rotation.z()); }
|
||||||
|
|
||||||
std::string get_tooltip() const override {
|
std::string get_tooltip() const override {
|
||||||
std::string tooltip = m_gizmos[X].get_tooltip();
|
std::string tooltip = m_gizmos[X].get_tooltip();
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#include "GLGizmoScale.hpp"
|
#include "GLGizmoScale.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
@ -14,7 +17,7 @@ namespace Slic3r {
|
|||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
|
||||||
const float GLGizmoScale3D::Offset = 5.0f;
|
const double GLGizmoScale3D::Offset = 5.0;
|
||||||
|
|
||||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
@ -38,16 +41,17 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filen
|
|||||||
|
|
||||||
std::string GLGizmoScale3D::get_tooltip() const
|
std::string GLGizmoScale3D::get_tooltip() const
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Vec3d scale = 100.0 * m_scale;
|
||||||
|
#else
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
|
||||||
bool single_instance = selection.is_single_full_instance();
|
Vec3d scale = 100.0 * Vec3d::Ones();
|
||||||
bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
|
if (selection.is_single_full_instance())
|
||||||
|
scale = 100.0 * selection.get_first_volume()->get_instance_scaling_factor();
|
||||||
Vec3f scale = 100.0f * Vec3f::Ones();
|
else if (selection.is_single_modifier() || selection.is_single_volume())
|
||||||
if (single_instance)
|
scale = 100.0 * selection.get_first_volume()->get_volume_scaling_factor();
|
||||||
scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor().cast<float>();
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
else if (single_volume)
|
|
||||||
scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor().cast<float>();
|
|
||||||
|
|
||||||
if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging)
|
if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging)
|
||||||
return "X: " + format(scale.x(), 4) + "%";
|
return "X: " + format(scale.x(), 4) + "%";
|
||||||
@ -72,12 +76,28 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
if (mouse_event.Dragging()) {
|
if (mouse_event.Dragging()) {
|
||||||
if (m_dragging) {
|
if (m_dragging) {
|
||||||
// Apply new temporary scale factors
|
// Apply new temporary scale factors
|
||||||
TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
|
#if ENABLE_WORLD_COORDINATE
|
||||||
if (mouse_event.AltDown()) transformation_type.set_independent();
|
TransformationType transformation_type;
|
||||||
|
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
|
transformation_type.set_local();
|
||||||
|
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||||
|
transformation_type.set_instance();
|
||||||
|
|
||||||
Selection &selection = m_parent.get_selection();
|
transformation_type.set_relative();
|
||||||
selection.scale(get_scale(), transformation_type);
|
#else
|
||||||
|
TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
if (mouse_event.AltDown())
|
||||||
|
transformation_type.set_independent();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_parent.get_selection().scale_and_translate(m_scale, m_offset, transformation_type);
|
||||||
|
#else
|
||||||
|
Selection& selection = m_parent.get_selection();
|
||||||
|
selection.scale(m_scale, transformation_type);
|
||||||
if (mouse_event.CmdDown()) selection.translate(m_offset, true);
|
if (mouse_event.CmdDown()) selection.translate(m_offset, true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return use_grabbers(mouse_event);
|
return use_grabbers(mouse_event);
|
||||||
@ -85,26 +105,29 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
|
|
||||||
void GLGizmoScale3D::data_changed()
|
void GLGizmoScale3D::data_changed()
|
||||||
{
|
{
|
||||||
const Selection &selection = m_parent.get_selection();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
set_scale(Vec3d::Ones());
|
||||||
|
#else
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
||||||
selection.is_single_volume() ||
|
selection.is_single_volume() ||
|
||||||
selection.is_single_modifier();
|
selection.is_single_modifier();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
m_grabbers[i].enabled = enable_scale_xyz;
|
m_grabbers[i].enabled = enable_scale_xyz;
|
||||||
|
|
||||||
if (enable_scale_xyz) {
|
if (enable_scale_xyz) {
|
||||||
// all volumes in the selection belongs to the same instance, any of
|
// all volumes in the selection belongs to the same instance, any of
|
||||||
// them contains the needed data, so we take the first
|
// them contains the needed data, so we take the first
|
||||||
const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance())
|
||||||
set_scale(volume->get_instance_scaling_factor());
|
set_scale(volume->get_instance_scaling_factor());
|
||||||
} else if (selection.is_single_volume() ||
|
else if (selection.is_single_volume() || selection.is_single_modifier())
|
||||||
selection.is_single_modifier()) {
|
|
||||||
set_scale(volume->get_volume_scaling_factor());
|
set_scale(volume->get_volume_scaling_factor());
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
set_scale(Vec3d::Ones());
|
set_scale(Vec3d::Ones());
|
||||||
}
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoScale3D::on_init()
|
bool GLGizmoScale3D::on_init()
|
||||||
@ -113,15 +136,17 @@ bool GLGizmoScale3D::on_init()
|
|||||||
m_grabbers.push_back(Grabber());
|
m_grabbers.push_back(Grabber());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
double half_pi = 0.5 * (double)PI;
|
double half_pi = 0.5 * (double)PI;
|
||||||
|
|
||||||
// x axis
|
// x axis
|
||||||
m_grabbers[0].angles(1) = half_pi;
|
m_grabbers[0].angles.y() = half_pi;
|
||||||
m_grabbers[1].angles(1) = half_pi;
|
m_grabbers[1].angles.y() = half_pi;
|
||||||
|
|
||||||
// y axis
|
// y axis
|
||||||
m_grabbers[2].angles(0) = half_pi;
|
m_grabbers[2].angles.x() = half_pi;
|
||||||
m_grabbers[3].angles(0) = half_pi;
|
m_grabbers[3].angles.x() = half_pi;
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
m_shortcut_key = WXK_CONTROL_S;
|
m_shortcut_key = WXK_CONTROL_S;
|
||||||
|
|
||||||
@ -142,9 +167,15 @@ bool GLGizmoScale3D::on_is_activable() const
|
|||||||
void GLGizmoScale3D::on_start_dragging()
|
void GLGizmoScale3D::on_start_dragging()
|
||||||
{
|
{
|
||||||
assert(m_hover_id != -1);
|
assert(m_hover_id != -1);
|
||||||
m_starting.drag_position = m_grabbers[m_hover_id].center;
|
|
||||||
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||||
m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_starting.drag_position = m_grabbers_transform * m_grabbers[m_hover_id].center;
|
||||||
|
m_starting.box = m_bounding_box;
|
||||||
|
m_starting.center = m_center;
|
||||||
|
m_starting.instance_center = m_instance_center;
|
||||||
|
#else
|
||||||
|
m_starting.drag_position = m_grabbers[m_hover_id].center;
|
||||||
|
m_starting.box = (m_starting.ctrl_down && m_hover_id < 6) ? m_bounding_box : m_parent.get_selection().get_bounding_box();
|
||||||
|
|
||||||
const Vec3d& center = m_starting.box.center();
|
const Vec3d& center = m_starting.box.center();
|
||||||
m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max.x(), center.y(), center.z());
|
m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max.x(), center.y(), center.z());
|
||||||
@ -153,6 +184,7 @@ void GLGizmoScale3D::on_start_dragging()
|
|||||||
m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z());
|
m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z());
|
||||||
m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z());
|
m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z());
|
||||||
m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z());
|
m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::on_stop_dragging() {
|
void GLGizmoScale3D::on_stop_dragging() {
|
||||||
@ -175,78 +207,156 @@ void GLGizmoScale3D::on_render()
|
|||||||
{
|
{
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
|
||||||
bool single_instance = selection.is_single_full_instance();
|
|
||||||
bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
|
|
||||||
|
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
m_box.reset();
|
m_bounding_box.reset();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_grabbers_transform = Transform3d::Identity();
|
||||||
|
m_center = Vec3d::Zero();
|
||||||
|
m_instance_center = Vec3d::Zero();
|
||||||
|
if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
#else
|
||||||
m_transform = Transform3d::Identity();
|
m_transform = Transform3d::Identity();
|
||||||
// Transforms grabbers' offsets to world refefence system
|
// Transforms grabbers' offsets to world refefence system
|
||||||
Transform3d offsets_transform = Transform3d::Identity();
|
Transform3d offsets_transform = Transform3d::Identity();
|
||||||
m_offsets_transform = Transform3d::Identity();
|
m_offsets_transform = Transform3d::Identity();
|
||||||
Vec3d angles = Vec3d::Zero();
|
Vec3d angles = Vec3d::Zero();
|
||||||
|
|
||||||
if (single_instance) {
|
if (selection.is_single_full_instance()) {
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// calculate bounding box in instance local reference system
|
// calculate bounding box in instance local reference system
|
||||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||||
for (unsigned int idx : idxs) {
|
for (unsigned int idx : idxs) {
|
||||||
const GLVolume* vol = selection.get_volume(idx);
|
const GLVolume& v = *selection.get_volume(idx);
|
||||||
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
|
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_bounding_box = m_bounding_box.transformed(selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// gets transform from first selected volume
|
// gets transform from first selected volume
|
||||||
const GLVolume* v = selection.get_volume(*idxs.begin());
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
m_transform = v->get_instance_transformation().get_matrix();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d inst_trafo = v.get_instance_transformation().get_matrix_no_scaling_factor();
|
||||||
|
m_grabbers_transform = inst_trafo * Geometry::translation_transform(m_bounding_box.center());
|
||||||
|
m_center = inst_trafo * m_bounding_box.center();
|
||||||
|
m_instance_center = v.get_instance_offset();
|
||||||
|
}
|
||||||
|
else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_instance_coordinates()) {
|
||||||
|
#else
|
||||||
|
m_transform = v.get_instance_transformation().get_matrix();
|
||||||
|
|
||||||
// gets angles from first selected volume
|
// gets angles from first selected volume
|
||||||
angles = v->get_instance_rotation();
|
angles = v.get_instance_rotation();
|
||||||
// consider rotation+mirror only components of the transform for offsets
|
// consider rotation+mirror only components of the transform for offsets
|
||||||
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
|
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror());
|
||||||
m_offsets_transform = offsets_transform;
|
m_offsets_transform = offsets_transform;
|
||||||
}
|
}
|
||||||
else if (single_volume) {
|
else if (selection.is_single_modifier() || selection.is_single_volume()) {
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
m_box = v->bounding_box();
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
m_transform = v->world_matrix();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(
|
||||||
|
v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_matrix_no_offset()));
|
||||||
|
Geometry::Transformation trafo(v.get_instance_transformation().get_rotation_matrix());
|
||||||
|
trafo.set_offset(v.world_matrix().translation());
|
||||||
|
m_grabbers_transform = trafo.get_matrix();
|
||||||
|
m_center = v.world_matrix() * m_bounding_box.center();
|
||||||
|
m_instance_center = m_center;
|
||||||
|
}
|
||||||
|
else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(
|
||||||
|
v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix()));
|
||||||
|
Geometry::Transformation trafo(v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix());
|
||||||
|
trafo.set_offset(v.world_matrix().translation());
|
||||||
|
m_grabbers_transform = trafo.get_matrix();
|
||||||
|
m_center = v.world_matrix() * m_bounding_box.center();
|
||||||
|
m_instance_center = m_center;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_bounding_box = selection.get_bounding_box();
|
||||||
|
m_grabbers_transform = Geometry::assemble_transform(m_bounding_box.center());
|
||||||
|
m_center = m_bounding_box.center();
|
||||||
|
m_instance_center = selection.is_single_full_instance() ? selection.get_first_volume()->get_instance_offset() : m_center;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
m_bounding_box = v.bounding_box();
|
||||||
|
m_transform = v.world_matrix();
|
||||||
angles = Geometry::extract_euler_angles(m_transform);
|
angles = Geometry::extract_euler_angles(m_transform);
|
||||||
// consider rotation+mirror only components of the transform for offsets
|
// consider rotation+mirror only components of the transform for offsets
|
||||||
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
|
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror());
|
||||||
m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v->get_volume_rotation(), Vec3d::Ones(), v->get_volume_mirror());
|
m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation(), Vec3d::Ones(), v.get_volume_mirror());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_box = selection.get_bounding_box();
|
m_bounding_box = selection.get_bounding_box();
|
||||||
|
|
||||||
const Vec3d& center = m_box.center();
|
const Vec3d& center = m_bounding_box.center();
|
||||||
const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
|
const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
|
||||||
const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
|
const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
|
||||||
const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
|
const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
|
||||||
|
|
||||||
const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL));
|
const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
// x axis
|
// x axis
|
||||||
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), center.z()) - offset_x;
|
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||||
|
bool use_constrain = wxGetKeyState(WXK_CONTROL) && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
|
||||||
|
|
||||||
|
m_grabbers[0].center = { -(box_half_size.x() + Offset), 0.0, 0.0 };
|
||||||
|
m_grabbers[0].color = (use_constrain && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
|
m_grabbers[1].center = { box_half_size.x() + Offset, 0.0, 0.0 };
|
||||||
|
m_grabbers[1].color = (use_constrain && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
|
|
||||||
|
// y axis
|
||||||
|
m_grabbers[2].center = { 0.0, -(box_half_size.y() + Offset), 0.0 };
|
||||||
|
m_grabbers[2].color = (use_constrain && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
|
m_grabbers[3].center = { 0.0, box_half_size.y() + Offset, 0.0 };
|
||||||
|
m_grabbers[3].color = (use_constrain && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
|
|
||||||
|
// z axis
|
||||||
|
m_grabbers[4].center = { 0.0, 0.0, -(box_half_size.z() + Offset) };
|
||||||
|
m_grabbers[4].color = (use_constrain && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||||
|
m_grabbers[5].center = { 0.0, 0.0, box_half_size.z() + Offset };
|
||||||
|
m_grabbers[5].color = (use_constrain && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||||
|
|
||||||
|
// uniform
|
||||||
|
m_grabbers[6].center = { -(box_half_size.x() + Offset), -(box_half_size.y() + Offset), 0.0 };
|
||||||
|
m_grabbers[6].color = (use_constrain && m_hover_id == 8) ? CONSTRAINED_COLOR : m_highlight_color;
|
||||||
|
m_grabbers[7].center = { box_half_size.x() + Offset, -(box_half_size.y() + Offset), 0.0 };
|
||||||
|
m_grabbers[7].color = (use_constrain && m_hover_id == 9) ? CONSTRAINED_COLOR : m_highlight_color;
|
||||||
|
m_grabbers[8].center = { box_half_size.x() + Offset, box_half_size.y() + Offset, 0.0 };
|
||||||
|
m_grabbers[8].color = (use_constrain && m_hover_id == 6) ? CONSTRAINED_COLOR : m_highlight_color;
|
||||||
|
m_grabbers[9].center = { -(box_half_size.x() + Offset), box_half_size.y() + Offset, 0.0 };
|
||||||
|
m_grabbers[9].color = (use_constrain && m_hover_id == 7) ? CONSTRAINED_COLOR : m_highlight_color;
|
||||||
|
#else
|
||||||
|
// x axis
|
||||||
|
m_grabbers[0].center = m_transform * Vec3d(m_bounding_box.min.x(), center.y(), center.z()) - offset_x;
|
||||||
m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), center.z()) + offset_x;
|
m_grabbers[1].center = m_transform * Vec3d(m_bounding_box.max.x(), center.y(), center.z()) + offset_x;
|
||||||
m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
|
|
||||||
// y axis
|
// y axis
|
||||||
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), center.z()) - offset_y;
|
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_bounding_box.min.y(), center.z()) - offset_y;
|
||||||
m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), center.z()) + offset_y;
|
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_bounding_box.max.y(), center.z()) + offset_y;
|
||||||
m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
|
|
||||||
// z axis
|
// z axis
|
||||||
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z()) - offset_z;
|
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.min.z()) - offset_z;
|
||||||
m_grabbers[4].color = (ctrl_down && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
m_grabbers[4].color = (ctrl_down && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||||
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z()) + offset_z;
|
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.max.z()) + offset_z;
|
||||||
m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||||
|
|
||||||
// uniform
|
// uniform
|
||||||
m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), center.z()) - offset_x - offset_y;
|
m_grabbers[6].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.min.y(), center.z()) - offset_x - offset_y;
|
||||||
m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), center.z()) + offset_x - offset_y;
|
m_grabbers[7].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.min.y(), center.z()) + offset_x - offset_y;
|
||||||
m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), center.z()) + offset_x + offset_y;
|
m_grabbers[8].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.max.y(), center.z()) + offset_x + offset_y;
|
||||||
m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), center.z()) - offset_x + offset_y;
|
m_grabbers[9].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.max.y(), center.z()) - offset_x + offset_y;
|
||||||
|
|
||||||
for (int i = 6; i < 10; ++i) {
|
for (int i = 6; i < 10; ++i) {
|
||||||
m_grabbers[i].color = m_highlight_color;
|
m_grabbers[i].color = m_highlight_color;
|
||||||
}
|
}
|
||||||
@ -255,12 +365,25 @@ void GLGizmoScale3D::on_render()
|
|||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
m_grabbers[i].angles = angles;
|
m_grabbers[i].angles = angles;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
const Transform3d base_matrix = local_transform(selection);
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
m_grabbers[i].matrix = base_matrix;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
glsafe(::glPushMatrix());
|
||||||
|
transform_to_local(selection);
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
|
const float grabber_mean_size = (float)((m_bounding_box.size().x() + m_bounding_box.size().y() + m_bounding_box.size().z()) / 3.0);
|
||||||
|
#else
|
||||||
const BoundingBoxf3& selection_box = selection.get_bounding_box();
|
const BoundingBoxf3& selection_box = selection.get_bounding_box();
|
||||||
|
|
||||||
const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0);
|
const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
if (m_hover_id == -1) {
|
if (m_hover_id == -1) {
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
@ -270,7 +393,11 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
if (m_grabbers[0].enabled && m_grabbers[1].enabled)
|
if (m_grabbers[0].enabled && m_grabbers[1].enabled)
|
||||||
@ -317,7 +444,11 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
render_grabbers_connection(0, 1, m_grabbers[0].color);
|
render_grabbers_connection(0, 1, m_grabbers[0].color);
|
||||||
@ -328,7 +459,7 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader = wxGetApp().get_shader("gouraud_light");
|
shader = wxGetApp().get_shader("gouraud_light");
|
||||||
#else
|
#else
|
||||||
// draw connection
|
// draw connection
|
||||||
glsafe(::glColor4fv(m_grabbers[0].color.data()));
|
glsafe(::glColor4fv(AXES_COLOR[0].data()));
|
||||||
render_grabbers_connection(0, 1);
|
render_grabbers_connection(0, 1);
|
||||||
|
|
||||||
// draw grabbers
|
// draw grabbers
|
||||||
@ -350,7 +481,11 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
render_grabbers_connection(2, 3, m_grabbers[2].color);
|
render_grabbers_connection(2, 3, m_grabbers[2].color);
|
||||||
@ -361,7 +496,7 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader = wxGetApp().get_shader("gouraud_light");
|
shader = wxGetApp().get_shader("gouraud_light");
|
||||||
#else
|
#else
|
||||||
// draw connection
|
// draw connection
|
||||||
glsafe(::glColor4fv(m_grabbers[2].color.data()));
|
glsafe(::glColor4fv(AXES_COLOR[1].data()));
|
||||||
render_grabbers_connection(2, 3);
|
render_grabbers_connection(2, 3);
|
||||||
|
|
||||||
// draw grabbers
|
// draw grabbers
|
||||||
@ -383,7 +518,11 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
render_grabbers_connection(4, 5, m_grabbers[4].color);
|
render_grabbers_connection(4, 5, m_grabbers[4].color);
|
||||||
@ -394,7 +533,7 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader = wxGetApp().get_shader("gouraud_light");
|
shader = wxGetApp().get_shader("gouraud_light");
|
||||||
#else
|
#else
|
||||||
// draw connection
|
// draw connection
|
||||||
glsafe(::glColor4fv(m_grabbers[4].color.data()));
|
glsafe(::glColor4fv(AXES_COLOR[2].data()));
|
||||||
render_grabbers_connection(4, 5);
|
render_grabbers_connection(4, 5);
|
||||||
|
|
||||||
// draw grabbers
|
// draw grabbers
|
||||||
@ -416,7 +555,11 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
|
#else
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
render_grabbers_connection(6, 7, m_drag_color);
|
render_grabbers_connection(6, 7, m_drag_color);
|
||||||
@ -448,12 +591,34 @@ void GLGizmoScale3D::on_render()
|
|||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
glsafe(::glPopMatrix());
|
||||||
|
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::on_render_for_picking()
|
void GLGizmoScale3D::on_render_for_picking()
|
||||||
{
|
{
|
||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
const Transform3d base_matrix = local_transform(m_parent.get_selection());
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
m_grabbers[i].matrix = base_matrix;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
glsafe(::glPushMatrix());
|
||||||
|
transform_to_local(m_parent.get_selection());
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
render_grabbers_for_picking(m_bounding_box);
|
||||||
|
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
glsafe(::glPopMatrix());
|
||||||
|
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#else
|
||||||
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
|
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
@ -509,13 +674,67 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
|
|||||||
}
|
}
|
||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||||
{
|
{
|
||||||
double ratio = calc_ratio(data);
|
double ratio = calc_ratio(data);
|
||||||
|
if (ratio > 0.0) {
|
||||||
|
Vec3d curr_scale = m_scale;
|
||||||
|
Vec3d starting_scale = m_starting.scale;
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
|
|
||||||
|
curr_scale(axis) = starting_scale(axis) * ratio;
|
||||||
|
m_scale = curr_scale;
|
||||||
|
|
||||||
|
if (m_starting.ctrl_down && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier())) {
|
||||||
|
double local_offset = 0.5 * (ratio - 1.0) * m_starting.box.size()(axis);
|
||||||
|
|
||||||
|
if (m_hover_id == 2 * axis)
|
||||||
|
local_offset *= -1.0;
|
||||||
|
|
||||||
|
Vec3d center_offset = m_starting.instance_center - m_starting.center; // world coordinates (== Vec3d::Zero() for single volume selection)
|
||||||
|
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
|
||||||
|
// from world coordinates to instance coordinates
|
||||||
|
center_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix().inverse() * center_offset;
|
||||||
|
|
||||||
|
local_offset += (ratio - 1.0) * center_offset(axis);
|
||||||
|
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case X: { m_offset = local_offset * Vec3d::UnitX(); break; }
|
||||||
|
case Y: { m_offset = local_offset * Vec3d::UnitY(); break; }
|
||||||
|
case Z: { m_offset = local_offset * Vec3d::UnitZ(); break; }
|
||||||
|
default: { m_offset = Vec3d::Zero(); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
|
||||||
|
// from instance coordinates to world coordinates
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix() * m_offset;
|
||||||
|
|
||||||
|
if (selection.is_single_volume_or_modifier()) {
|
||||||
|
if (coordinates_type == ECoordinatesType::Instance)
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() * m_offset;
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local) {
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() *
|
||||||
|
selection.get_first_volume()->get_volume_transformation().get_rotation_matrix() * m_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_offset = Vec3d::Zero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||||
|
{
|
||||||
|
const double ratio = calc_ratio(data);
|
||||||
if (ratio > 0.0) {
|
if (ratio > 0.0) {
|
||||||
m_scale(axis) = m_starting.scale(axis) * ratio;
|
m_scale(axis) = m_starting.scale(axis) * ratio;
|
||||||
|
|
||||||
if (m_starting.ctrl_down) {
|
if (m_starting.ctrl_down) {
|
||||||
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
|
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
|
||||||
|
|
||||||
if (m_hover_id == 2 * axis)
|
if (m_hover_id == 2 * axis)
|
||||||
local_offset *= -1.0;
|
local_offset *= -1.0;
|
||||||
|
|
||||||
@ -534,36 +753,86 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
|||||||
m_offset = Vec3d::Zero();
|
m_offset = Vec3d::Zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void GLGizmoScale3D::do_scale_uniform(const UpdateData & data)
|
||||||
|
{
|
||||||
|
const double ratio = calc_ratio(data);
|
||||||
|
if (ratio > 0.0) {
|
||||||
|
m_scale = m_starting.scale * ratio;
|
||||||
|
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
|
if (m_starting.ctrl_down && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier())) {
|
||||||
|
m_offset = 0.5 * (ratio - 1.0) * m_starting.box.size();
|
||||||
|
|
||||||
|
if (m_hover_id == 6 || m_hover_id == 9)
|
||||||
|
m_offset.x() *= -1.0;
|
||||||
|
if (m_hover_id == 6 || m_hover_id == 7)
|
||||||
|
m_offset.y() *= -1.0;
|
||||||
|
|
||||||
|
Vec3d center_offset = m_starting.instance_center - m_starting.center; // world coordinates (== Vec3d::Zero() for single volume selection)
|
||||||
|
|
||||||
|
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
|
||||||
|
// from world coordinates to instance coordinates
|
||||||
|
center_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix().inverse() * center_offset;
|
||||||
|
|
||||||
|
m_offset += (ratio - 1.0) * center_offset;
|
||||||
|
|
||||||
|
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
|
||||||
|
// from instance coordinates to world coordinates
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix() * m_offset;
|
||||||
|
|
||||||
|
if (selection.is_single_volume_or_modifier()) {
|
||||||
|
if (coordinates_type == ECoordinatesType::Instance)
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() * m_offset;
|
||||||
|
else if (coordinates_type == ECoordinatesType::Local) {
|
||||||
|
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() *
|
||||||
|
selection.get_first_volume()->get_volume_transformation().get_rotation_matrix() * m_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_offset = Vec3d::Zero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
||||||
{
|
{
|
||||||
double ratio = calc_ratio(data);
|
const double ratio = calc_ratio(data);
|
||||||
if (ratio > 0.0) {
|
if (ratio > 0.0) {
|
||||||
m_scale = m_starting.scale * ratio;
|
m_scale = m_starting.scale * ratio;
|
||||||
m_offset = Vec3d::Zero();
|
m_offset = Vec3d::Zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||||
{
|
{
|
||||||
double ratio = 0.0;
|
double ratio = 0.0;
|
||||||
|
|
||||||
Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.box.center();
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Vec3d starting_vec = m_starting.drag_position - m_starting.center;
|
||||||
|
#else
|
||||||
|
const Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.box.center();
|
||||||
|
const Vec3d starting_vec = m_starting.drag_position - pivot;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
const double len_starting_vec = starting_vec.norm();
|
||||||
|
|
||||||
Vec3d starting_vec = m_starting.drag_position - pivot;
|
|
||||||
double len_starting_vec = starting_vec.norm();
|
|
||||||
if (len_starting_vec != 0.0) {
|
if (len_starting_vec != 0.0) {
|
||||||
Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
const Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
||||||
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
||||||
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
|
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
|
||||||
// in our case plane normal and ray direction are the same (orthogonal view)
|
// in our case plane normal and ray direction are the same (orthogonal view)
|
||||||
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
|
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
|
||||||
Vec3d inters = data.mouse_ray.a + (m_starting.drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
|
const Vec3d inters = data.mouse_ray.a + (m_starting.drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
|
||||||
// vector from the starting position to the found intersection
|
// vector from the starting position to the found intersection
|
||||||
Vec3d inters_vec = inters - m_starting.drag_position;
|
const Vec3d inters_vec = inters - m_starting.drag_position;
|
||||||
|
|
||||||
// finds projection of the vector along the staring direction
|
// finds projection of the vector along the staring direction
|
||||||
double proj = inters_vec.dot(starting_vec.normalized());
|
const double proj = inters_vec.dot(starting_vec.normalized());
|
||||||
|
|
||||||
ratio = (len_starting_vec + proj) / len_starting_vec;
|
ratio = (len_starting_vec + proj) / len_starting_vec;
|
||||||
}
|
}
|
||||||
@ -574,5 +843,34 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
|||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
Transform3d GLGizmoScale3D::local_transform(const Selection& selection) const
|
||||||
|
{
|
||||||
|
Transform3d ret = Geometry::assemble_transform(m_center);
|
||||||
|
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
const GLVolume& v = *selection.get_first_volume();
|
||||||
|
Transform3d orient_matrix = v.get_instance_transformation().get_rotation_matrix();
|
||||||
|
if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
|
orient_matrix = orient_matrix * v.get_volume_transformation().get_rotation_matrix();
|
||||||
|
ret = ret * orient_matrix;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void GLGizmoScale3D::transform_to_local(const Selection& selection) const
|
||||||
|
{
|
||||||
|
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||||
|
|
||||||
|
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
Transform3d orient_matrix = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true);
|
||||||
|
if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
|
orient_matrix = orient_matrix * selection.get_first_volume()->get_volume_transformation().get_matrix(true, false, true, true);
|
||||||
|
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -3,31 +3,46 @@
|
|||||||
|
|
||||||
#include "GLGizmoBase.hpp"
|
#include "GLGizmoBase.hpp"
|
||||||
|
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
class Selection;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
class GLGizmoScale3D : public GLGizmoBase
|
class GLGizmoScale3D : public GLGizmoBase
|
||||||
{
|
{
|
||||||
static const float Offset;
|
static const double Offset;
|
||||||
|
|
||||||
struct StartingData
|
struct StartingData
|
||||||
{
|
{
|
||||||
Vec3d scale;
|
bool ctrl_down{ false };
|
||||||
Vec3d drag_position;
|
Vec3d scale{ Vec3d::Ones() };
|
||||||
|
Vec3d drag_position{ Vec3d::Zero() };
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Vec3d center{ Vec3d::Zero() };
|
||||||
|
Vec3d instance_center{ Vec3d::Zero() };
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
BoundingBoxf3 box;
|
BoundingBoxf3 box;
|
||||||
Vec3d pivots[6];
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
bool ctrl_down;
|
std::array<Vec3d, 6> pivots{ Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() };
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
StartingData() : scale(Vec3d::Ones()), drag_position(Vec3d::Zero()), ctrl_down(false) { for (int i = 0; i < 5; ++i) { pivots[i] = Vec3d::Zero(); } }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable BoundingBoxf3 m_box;
|
BoundingBoxf3 m_bounding_box;
|
||||||
mutable Transform3d m_transform;
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Transform3d m_grabbers_transform;
|
||||||
|
Vec3d m_center{ Vec3d::Zero() };
|
||||||
|
Vec3d m_instance_center{ Vec3d::Zero() };
|
||||||
|
#else
|
||||||
|
Transform3d m_transform;
|
||||||
// Transforms grabbers offsets to the proper reference system (world for instances, instance for volumes)
|
// Transforms grabbers offsets to the proper reference system (world for instances, instance for volumes)
|
||||||
mutable Transform3d m_offsets_transform;
|
Transform3d m_offsets_transform;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
Vec3d m_scale{ Vec3d::Ones() };
|
Vec3d m_scale{ Vec3d::Ones() };
|
||||||
Vec3d m_offset{ Vec3d::Zero() };
|
Vec3d m_offset{ Vec3d::Zero() };
|
||||||
double m_snap_step{ 0.05 };
|
double m_snap_step{ 0.05 };
|
||||||
@ -54,7 +69,11 @@ public:
|
|||||||
void set_snap_step(double step) { m_snap_step = step; }
|
void set_snap_step(double step) { m_snap_step = step; }
|
||||||
|
|
||||||
const Vec3d& get_scale() const { return m_scale; }
|
const Vec3d& get_scale() const { return m_scale; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; m_offset = Vec3d::Zero(); }
|
||||||
|
#else
|
||||||
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
|
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
std::string get_tooltip() const override;
|
std::string get_tooltip() const override;
|
||||||
|
|
||||||
@ -87,6 +106,13 @@ private:
|
|||||||
void do_scale_uniform(const UpdateData& data);
|
void do_scale_uniform(const UpdateData& data);
|
||||||
|
|
||||||
double calc_ratio(const UpdateData& data) const;
|
double calc_ratio(const UpdateData& data) const;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
Transform3d local_transform(const Selection& selection) const;
|
||||||
|
#else
|
||||||
|
void transform_to_local(const Selection& selection) const;
|
||||||
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,9 +146,13 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
});
|
});
|
||||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
|
||||||
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* vol = selection.get_first_volume();
|
||||||
Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix());
|
Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_scaling_matrix_inverse = transformation.get_scaling_factor_matrix().inverse();
|
||||||
|
#else
|
||||||
const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse();
|
const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
#if ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * transformation.get_matrix();
|
const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * transformation.get_matrix();
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
@ -357,7 +361,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
|
|||||||
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
||||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ void SelectionInfo::on_update()
|
|||||||
const Selection& selection = get_pool()->get_canvas()->get_selection();
|
const Selection& selection = get_pool()->get_canvas()->get_selection();
|
||||||
if (selection.is_single_full_instance()) {
|
if (selection.is_single_full_instance()) {
|
||||||
m_model_object = selection.get_model()->objects[selection.get_object_idx()];
|
m_model_object = selection.get_model()->objects[selection.get_object_idx()];
|
||||||
m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z();
|
m_z_shift = selection.get_first_volume()->get_sla_shift_z();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_model_object = nullptr;
|
m_model_object = nullptr;
|
||||||
|
@ -408,7 +408,8 @@ bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) {
|
|||||||
// at this moment is enebled to process mouse move under gizmo
|
// at this moment is enebled to process mouse move under gizmo
|
||||||
// tools bar e.g. Do not interupt dragging.
|
// tools bar e.g. Do not interupt dragging.
|
||||||
return false;
|
return false;
|
||||||
} else if (mc.exist_tooltip) {
|
}
|
||||||
|
else if (mc.exist_tooltip) {
|
||||||
// first move out of gizmo tool bar - unselect tooltip
|
// first move out of gizmo tool bar - unselect tooltip
|
||||||
mc.exist_tooltip = false;
|
mc.exist_tooltip = false;
|
||||||
update_hover_state(Undefined);
|
update_hover_state(Undefined);
|
||||||
@ -423,10 +424,12 @@ bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) {
|
|||||||
mc.left = true;
|
mc.left = true;
|
||||||
open_gizmo(gizmo);
|
open_gizmo(gizmo);
|
||||||
return true;
|
return true;
|
||||||
} else if (mouse_event.RightDown()) {
|
}
|
||||||
|
else if (mouse_event.RightDown()) {
|
||||||
mc.right = true;
|
mc.right = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (mouse_event.MiddleDown()) {
|
}
|
||||||
|
else if (mouse_event.MiddleDown()) {
|
||||||
mc.middle = true;
|
mc.middle = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -442,13 +445,16 @@ bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) {
|
|||||||
}
|
}
|
||||||
// draging start on toolbar so no propagation into scene
|
// draging start on toolbar so no propagation into scene
|
||||||
return true;
|
return true;
|
||||||
} else if (mc.left && mouse_event.LeftUp()) {
|
}
|
||||||
|
else if (mc.left && mouse_event.LeftUp()) {
|
||||||
mc.left = false;
|
mc.left = false;
|
||||||
return true;
|
return true;
|
||||||
} else if (mc.right && mouse_event.RightUp()) {
|
}
|
||||||
|
else if (mc.right && mouse_event.RightUp()) {
|
||||||
mc.right = false;
|
mc.right = false;
|
||||||
return true;
|
return true;
|
||||||
} else if (mc.middle && mouse_event.MiddleUp()) {
|
}
|
||||||
|
else if (mc.middle && mouse_event.MiddleUp()) {
|
||||||
mc.middle = false;
|
mc.middle = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,11 @@ void MeshClipper::render_cut()
|
|||||||
|
|
||||||
void MeshClipper::recalculate_triangles()
|
void MeshClipper::recalculate_triangles()
|
||||||
{
|
{
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3f instance_matrix_no_translation_no_scaling = m_trafo.get_rotation_matrix().cast<float>();
|
||||||
|
#else
|
||||||
const Transform3f& instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
|
const Transform3f& instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
// Calculate clipping plane normal in mesh coordinates.
|
// Calculate clipping plane normal in mesh coordinates.
|
||||||
const Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>();
|
const Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>();
|
||||||
const Vec3d up = up_noscale.cast<double>().cwiseProduct(m_trafo.get_scaling_factor());
|
const Vec3d up = up_noscale.cast<double>().cwiseProduct(m_trafo.get_scaling_factor());
|
||||||
@ -303,7 +307,11 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo
|
|||||||
{
|
{
|
||||||
std::vector<unsigned> out;
|
std::vector<unsigned> out;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Transform3d instance_matrix_no_translation_no_scaling = trafo.get_rotation_matrix();
|
||||||
|
#else
|
||||||
const Transform3d& instance_matrix_no_translation_no_scaling = trafo.get_matrix(true,false,true);
|
const Transform3d& instance_matrix_no_translation_no_scaling = trafo.get_matrix(true,false,true);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
Vec3d direction_to_camera = -camera.get_dir_forward();
|
Vec3d direction_to_camera = -camera.get_dir_forward();
|
||||||
Vec3d direction_to_camera_mesh = (instance_matrix_no_translation_no_scaling.inverse() * direction_to_camera).normalized().eval();
|
Vec3d direction_to_camera_mesh = (instance_matrix_no_translation_no_scaling.inverse() * direction_to_camera).normalized().eval();
|
||||||
direction_to_camera_mesh = direction_to_camera_mesh.cwiseProduct(trafo.get_scaling_factor());
|
direction_to_camera_mesh = direction_to_camera_mesh.cwiseProduct(trafo.get_scaling_factor());
|
||||||
|
@ -57,6 +57,9 @@
|
|||||||
#include "GUI_ObjectManipulation.hpp"
|
#include "GUI_ObjectManipulation.hpp"
|
||||||
#include "GUI_ObjectLayers.hpp"
|
#include "GUI_ObjectLayers.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "GUI_Geometry.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#include "GUI_Factories.hpp"
|
#include "GUI_Factories.hpp"
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
@ -1514,6 +1517,11 @@ void Sidebar::update_mode()
|
|||||||
|
|
||||||
wxWindowUpdateLocker noUpdates(this);
|
wxWindowUpdateLocker noUpdates(this);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
if (m_mode == comSimple)
|
||||||
|
p->object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
p->object_list->get_sizer()->Show(m_mode > comSimple);
|
p->object_list->get_sizer()->Show(m_mode > comSimple);
|
||||||
|
|
||||||
p->object_list->unselect_objects();
|
p->object_list->unselect_objects();
|
||||||
@ -2077,6 +2085,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
|
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
|
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
|
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
view3D_canvas->Bind(EVT_GLCANVAS_RESET_SKEW, [this](SimpleEvent&) { update(); });
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
|
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool>& evt) { this->sidebar->enable_buttons(evt.data); });
|
view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool>& evt) { this->sidebar->enable_buttons(evt.data); });
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this);
|
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this);
|
||||||
@ -2922,7 +2933,7 @@ int Plater::priv::get_selected_volume_idx() const
|
|||||||
if ((0 > idx) || (idx > 1000))
|
if ((0 > idx) || (idx > 1000))
|
||||||
#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
|
||||||
return-1;
|
return-1;
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* v = selection.get_first_volume();
|
||||||
if (model.objects[idx]->volumes.size() > 1)
|
if (model.objects[idx]->volumes.size() > 1)
|
||||||
return v->volume_idx();
|
return v->volume_idx();
|
||||||
return -1;
|
return -1;
|
||||||
@ -3484,7 +3495,11 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
|
|||||||
new_volume->set_type(old_volume->type());
|
new_volume->set_type(old_volume->type());
|
||||||
new_volume->set_material_id(old_volume->material_id());
|
new_volume->set_material_id(old_volume->material_id());
|
||||||
new_volume->set_transformation(old_volume->get_transformation());
|
new_volume->set_transformation(old_volume->get_transformation());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
||||||
|
#else
|
||||||
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
|
assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
|
||||||
if (old_volume->source.is_converted_from_inches)
|
if (old_volume->source.is_converted_from_inches)
|
||||||
new_volume->convert_from_imperial_units();
|
new_volume->convert_from_imperial_units();
|
||||||
@ -3521,7 +3536,7 @@ void Plater::priv::replace_with_stl()
|
|||||||
if (selection.is_wipe_tower() || get_selection().get_volume_idxs().size() != 1)
|
if (selection.is_wipe_tower() || get_selection().get_volume_idxs().size() != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* v = selection.get_first_volume();
|
||||||
int object_idx = v->object_idx();
|
int object_idx = v->object_idx();
|
||||||
int volume_idx = v->volume_idx();
|
int volume_idx = v->volume_idx();
|
||||||
|
|
||||||
@ -3839,10 +3854,16 @@ void Plater::priv::reload_from_disk()
|
|||||||
new_volume->config.apply(old_volume->config);
|
new_volume->config.apply(old_volume->config);
|
||||||
new_volume->set_type(old_volume->type());
|
new_volume->set_type(old_volume->type());
|
||||||
new_volume->set_material_id(old_volume->material_id());
|
new_volume->set_material_id(old_volume->material_id());
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
new_volume->set_transformation(Geometry::translation_transform(old_volume->source.transform.get_offset()) *
|
||||||
|
old_volume->get_transformation().get_matrix_no_offset() * old_volume->source.transform.get_matrix_no_offset());
|
||||||
|
new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
||||||
|
#else
|
||||||
new_volume->set_transformation(Geometry::assemble_transform(old_volume->source.transform.get_offset()) *
|
new_volume->set_transformation(Geometry::assemble_transform(old_volume->source.transform.get_offset()) *
|
||||||
old_volume->get_transformation().get_matrix(true) *
|
old_volume->get_transformation().get_matrix(true) *
|
||||||
old_volume->source.transform.get_matrix(true));
|
old_volume->source.transform.get_matrix(true));
|
||||||
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
new_volume->source.object_idx = old_volume->source.object_idx;
|
new_volume->source.object_idx = old_volume->source.object_idx;
|
||||||
new_volume->source.volume_idx = old_volume->source.volume_idx;
|
new_volume->source.volume_idx = old_volume->source.volume_idx;
|
||||||
assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
|
assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
|
||||||
@ -4448,7 +4469,11 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
|||||||
const bool is_some_full_instances = selection.is_single_full_instance() ||
|
const bool is_some_full_instances = selection.is_single_full_instance() ||
|
||||||
selection.is_single_full_object() ||
|
selection.is_single_full_object() ||
|
||||||
selection.is_multiple_full_instance();
|
selection.is_multiple_full_instance();
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const bool is_part = selection.is_single_volume_or_modifier();
|
||||||
|
#else
|
||||||
const bool is_part = selection.is_single_volume() || selection.is_single_modifier();
|
const bool is_part = selection.is_single_volume() || selection.is_single_modifier();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
menu = is_some_full_instances ? menus.object_menu() :
|
menu = is_some_full_instances ? menus.object_menu() :
|
||||||
is_part ? menus.part_menu() : menus.multi_selection_menu();
|
is_part ? menus.part_menu() : menus.multi_selection_menu();
|
||||||
}
|
}
|
||||||
@ -6030,7 +6055,7 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
|
|||||||
if (selection.get_mode() == Selection::Instance)
|
if (selection.get_mode() == Selection::Instance)
|
||||||
mesh = mesh_to_export(*model_object, (selection.is_single_full_object() && model_object->instances.size() > 1) ? -1 : selection.get_instance_idx());
|
mesh = mesh_to_export(*model_object, (selection.is_single_full_object() && model_object->instances.size() > 1) ? -1 : selection.get_instance_idx());
|
||||||
else {
|
else {
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_first_volume();
|
||||||
mesh = model_object->volumes[volume->volume_idx()]->mesh();
|
mesh = model_object->volumes[volume->volume_idx()]->mesh();
|
||||||
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
|
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,12 @@
|
|||||||
#define slic3r_GUI_Selection_hpp_
|
#define slic3r_GUI_Selection_hpp_
|
||||||
|
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
#include "GUI_Geometry.hpp"
|
||||||
|
#include "CoordAxes.hpp"
|
||||||
|
#else
|
||||||
#include "GLModel.hpp"
|
#include "GLModel.hpp"
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -24,6 +29,7 @@ using ModelObjectPtrs = std::vector<ModelObject*>;
|
|||||||
|
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
class TransformationType
|
class TransformationType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -76,6 +82,7 @@ private:
|
|||||||
|
|
||||||
Enum m_value;
|
Enum m_value;
|
||||||
};
|
};
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
class Selection
|
class Selection
|
||||||
{
|
{
|
||||||
@ -110,16 +117,19 @@ private:
|
|||||||
private:
|
private:
|
||||||
struct TransformCache
|
struct TransformCache
|
||||||
{
|
{
|
||||||
Vec3d position;
|
Vec3d position{ Vec3d::Zero() };
|
||||||
Vec3d rotation;
|
Vec3d rotation{ Vec3d::Zero() };
|
||||||
Vec3d scaling_factor;
|
Vec3d scaling_factor{ Vec3d::Ones() };
|
||||||
Vec3d mirror;
|
Vec3d mirror{ Vec3d::Ones() };
|
||||||
Transform3d rotation_matrix;
|
Transform3d rotation_matrix{ Transform3d::Identity() };
|
||||||
Transform3d scale_matrix;
|
Transform3d scale_matrix{ Transform3d::Identity() };
|
||||||
Transform3d mirror_matrix;
|
Transform3d mirror_matrix{ Transform3d::Identity() };
|
||||||
Transform3d full_matrix;
|
Transform3d full_matrix{ Transform3d::Identity() };
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
Geometry::Transformation transform;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
TransformCache();
|
TransformCache() = default;
|
||||||
explicit TransformCache(const Geometry::Transformation& transform);
|
explicit TransformCache(const Geometry::Transformation& transform);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,13 +141,18 @@ private:
|
|||||||
VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
|
VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
|
||||||
|
|
||||||
const Vec3d& get_volume_position() const { return m_volume.position; }
|
const Vec3d& get_volume_position() const { return m_volume.position; }
|
||||||
|
#if !ENABLE_WORLD_COORDINATE
|
||||||
const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
|
const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
|
||||||
const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
|
const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
|
||||||
const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
|
const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
|
||||||
|
#endif // !ENABLE_WORLD_COORDINATE
|
||||||
const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
|
const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
|
||||||
const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
|
const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
|
||||||
const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
|
const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
|
||||||
const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
|
const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Geometry::Transformation& get_volume_transform() const { return m_volume.transform; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
const Vec3d& get_instance_position() const { return m_instance.position; }
|
const Vec3d& get_instance_position() const { return m_instance.position; }
|
||||||
const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
|
const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
|
||||||
@ -147,6 +162,9 @@ private:
|
|||||||
const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
|
const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
|
||||||
const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
|
const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
|
||||||
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
|
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
const Geometry::Transformation& get_instance_transform() const { return m_instance.transform; }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -207,15 +225,32 @@ private:
|
|||||||
Cache m_cache;
|
Cache m_cache;
|
||||||
Clipboard m_clipboard;
|
Clipboard m_clipboard;
|
||||||
std::optional<BoundingBoxf3> m_bounding_box;
|
std::optional<BoundingBoxf3> m_bounding_box;
|
||||||
// Bounding box of a selection, with no instance scaling applied. This bounding box
|
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||||
// is useful for absolute scaling of tilted objects in world coordinate space.
|
// This bounding box is useful for absolute scaling of tilted objects in world coordinate space.
|
||||||
|
// Modifiers are NOT taken in account
|
||||||
std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
|
std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates.
|
||||||
|
// Modifiers are NOT taken in account
|
||||||
std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
|
std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
std::optional<BoundingBoxf3> m_full_unscaled_instance_bounding_box;
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
std::optional<BoundingBoxf3> m_full_scaled_instance_bounding_box;
|
||||||
|
// Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
std::optional<BoundingBoxf3> m_full_unscaled_instance_local_bounding_box;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
#if ENABLE_RENDER_SELECTION_CENTER
|
#if ENABLE_RENDER_SELECTION_CENTER
|
||||||
GLModel m_vbo_sphere;
|
GLModel m_vbo_sphere;
|
||||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
CoordAxes m_axes;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
GLModel m_arrow;
|
GLModel m_arrow;
|
||||||
GLModel m_curved_arrow;
|
GLModel m_curved_arrow;
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
@ -290,6 +325,9 @@ public:
|
|||||||
bool is_from_single_object() const;
|
bool is_from_single_object() const;
|
||||||
bool is_sla_compliant() const;
|
bool is_sla_compliant() const;
|
||||||
bool is_instance_mode() const { return m_mode == Instance; }
|
bool is_instance_mode() const { return m_mode == Instance; }
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
bool is_single_volume_or_modifier() const { return is_single_volume() || is_single_modifier(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); }
|
bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); }
|
||||||
// returns true if the selection contains all the given indices
|
// returns true if the selection contains all the given indices
|
||||||
@ -299,7 +337,18 @@ public:
|
|||||||
// returns true if the selection contains all and only the given indices
|
// returns true if the selection contains all and only the given indices
|
||||||
bool matches(const std::vector<unsigned int>& volume_idxs) const;
|
bool matches(const std::vector<unsigned int>& volume_idxs) const;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
enum class EUniformScaleRequiredReason : unsigned char
|
||||||
|
{
|
||||||
|
NotRequired,
|
||||||
|
InstanceNotAxisAligned_World,
|
||||||
|
VolumeNotAxisAligned_World,
|
||||||
|
VolumeNotAxisAligned_Instance,
|
||||||
|
MultipleSelection,
|
||||||
|
};
|
||||||
|
#else
|
||||||
bool requires_uniform_scale() const;
|
bool requires_uniform_scale() const;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
// Returns the the object id if the selection is from a single object, otherwise is -1
|
// Returns the the object id if the selection is from a single object, otherwise is -1
|
||||||
int get_object_idx() const;
|
int get_object_idx() const;
|
||||||
@ -311,28 +360,60 @@ public:
|
|||||||
|
|
||||||
const IndicesList& get_volume_idxs() const { return m_list; }
|
const IndicesList& get_volume_idxs() const { return m_list; }
|
||||||
const GLVolume* get_volume(unsigned int volume_idx) const;
|
const GLVolume* get_volume(unsigned int volume_idx) const;
|
||||||
|
const GLVolume* get_first_volume() const { return get_volume(*m_list.begin()); }
|
||||||
|
|
||||||
const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
|
const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
|
||||||
|
|
||||||
unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
|
unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
|
||||||
const BoundingBoxf3& get_bounding_box() const;
|
const BoundingBoxf3& get_bounding_box() const;
|
||||||
// Bounding box of a selection, with no instance scaling applied. This bounding box
|
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||||
// is useful for absolute scaling of tilted objects in world coordinate space.
|
// This bounding box is useful for absolute scaling of tilted objects in world coordinate space.
|
||||||
|
// Modifiers are NOT taken in account
|
||||||
const BoundingBoxf3& get_unscaled_instance_bounding_box() const;
|
const BoundingBoxf3& get_unscaled_instance_bounding_box() const;
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates.
|
||||||
|
// Modifiers are NOT taken in account
|
||||||
const BoundingBoxf3& get_scaled_instance_bounding_box() const;
|
const BoundingBoxf3& get_scaled_instance_bounding_box() const;
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
const BoundingBoxf3& get_full_unscaled_instance_bounding_box() const;
|
||||||
|
// Bounding box of a single full instance selection, in world coordinates.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
const BoundingBoxf3& get_full_scaled_instance_bounding_box() const;
|
||||||
|
|
||||||
|
// Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied.
|
||||||
|
// Modifiers are taken in account
|
||||||
|
const BoundingBoxf3& get_full_unscaled_instance_local_bounding_box() const;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void setup_cache();
|
void setup_cache();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void translate(const Vec3d& displacement, TransformationType transformation_type);
|
||||||
|
#else
|
||||||
void translate(const Vec3d& displacement, bool local = false);
|
void translate(const Vec3d& displacement, bool local = false);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||||
void flattening_rotate(const Vec3d& normal);
|
void flattening_rotate(const Vec3d& normal);
|
||||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||||
void scale_to_fit_print_volume(const BuildVolume& volume);
|
void scale_to_fit_print_volume(const BuildVolume& volume);
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type);
|
||||||
|
void reset_skew();
|
||||||
|
#else
|
||||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
|
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// returns:
|
||||||
|
// -1 if the user refused to proceed with baking when asked
|
||||||
|
// 0 if the baking was performed
|
||||||
|
// 1 if no baking was needed
|
||||||
|
int bake_transform_if_needed() const;
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void erase();
|
void erase();
|
||||||
|
|
||||||
void render(float scale_factor = 1.0);
|
void render(float scale_factor = 1.0);
|
||||||
@ -368,10 +449,23 @@ private:
|
|||||||
void do_remove_volume(unsigned int volume_idx);
|
void do_remove_volume(unsigned int volume_idx);
|
||||||
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
|
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
|
||||||
void do_remove_object(unsigned int object_idx);
|
void do_remove_object(unsigned int object_idx);
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void set_bounding_boxes_dirty() {
|
||||||
|
m_bounding_box.reset();
|
||||||
|
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
||||||
|
m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset();
|
||||||
|
m_full_unscaled_instance_local_bounding_box.reset();;
|
||||||
|
}
|
||||||
|
#else
|
||||||
void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
|
void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
void render_synchronized_volumes();
|
void render_synchronized_volumes();
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void render_bounding_box(const BoundingBoxf3& box, const Transform3d& trafo, const ColorRGB& color);
|
||||||
|
#else
|
||||||
void render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color);
|
void render_bounding_box(const BoundingBoxf3& box, const ColorRGB& color);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
#else
|
#else
|
||||||
void render_selected_volumes() const;
|
void render_selected_volumes() const;
|
||||||
void render_bounding_box(const BoundingBoxf3& box, float* color) const;
|
void render_bounding_box(const BoundingBoxf3& box, float* color) const;
|
||||||
@ -389,11 +483,15 @@ private:
|
|||||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SyncRotationType {
|
enum class SyncRotationType {
|
||||||
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
|
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
|
||||||
SYNC_ROTATION_NONE = 0,
|
NONE = 0,
|
||||||
// Synchronize after rotation by an axis not parallel with Z.
|
// Synchronize after rotation by an axis not parallel with Z.
|
||||||
SYNC_ROTATION_GENERAL = 1,
|
GENERAL = 1,
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
// Fully synchronize rotation.
|
||||||
|
FULL = 2,
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
|
void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
|
||||||
void synchronize_unselected_volumes();
|
void synchronize_unselected_volumes();
|
||||||
@ -405,6 +503,11 @@ private:
|
|||||||
|
|
||||||
void paste_volumes_from_clipboard();
|
void paste_volumes_from_clipboard();
|
||||||
void paste_objects_from_clipboard();
|
void paste_objects_from_clipboard();
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
|
||||||
|
const Transform3d& transform);
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -581,8 +581,12 @@ void LockButton::OnButton(wxCommandEvent& event)
|
|||||||
if (m_disabled)
|
if (m_disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
SetLock(!m_is_pushed);
|
||||||
|
#else
|
||||||
m_is_pushed = !m_is_pushed;
|
m_is_pushed = !m_is_pushed;
|
||||||
update_button_bitmaps();
|
update_button_bitmaps();
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user