ENH: Rotate around the center of the bounding box
jira:none code is from PrusaSlicer,thanks for enricoturri1966 and PrusaSlicer commit dcec7a8ad40eaad72789f6dba15cafc94664119f Author: enricoturri1966 <enricoturri@seznam.cz> Date: Tue Feb 28 08:08:56 2023 +0100 Fixed Rotate Gizmo orientation for mirrored objects + ensure that instances and volumes always rotate as rigid body Change-Id: I359d15814a6411bbd6bcb753661388bb5e6fb513
This commit is contained in:
parent
82775a1a59
commit
818c7a345a
|
@ -500,6 +500,15 @@ void Transformation::set_rotation(Axis axis, double rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform3d Transformation::get_scaling_factor_matrix() const
|
||||||
|
{
|
||||||
|
Transform3d scale = extract_scale(m_matrix);
|
||||||
|
scale(0, 0) = std::abs(scale(0, 0));
|
||||||
|
scale(1, 1) = std::abs(scale(1, 1));
|
||||||
|
scale(2, 2) = std::abs(scale(2, 2));
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
||||||
{
|
{
|
||||||
set_scaling_factor(X, scaling_factor(0));
|
set_scaling_factor(X, scaling_factor(0));
|
||||||
|
|
|
@ -406,6 +406,7 @@ public:
|
||||||
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);
|
||||||
|
|
||||||
|
Transform3d get_scaling_factor_matrix() const;
|
||||||
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); }
|
||||||
|
|
||||||
|
@ -421,6 +422,7 @@ public:
|
||||||
void set_mirror(Axis axis, double mirror);
|
void set_mirror(Axis axis, double mirror);
|
||||||
|
|
||||||
void set_from_transform(const Transform3d& transform);
|
void set_from_transform(const Transform3d& transform);
|
||||||
|
void set_matrix(const Transform3d &transform) { set_from_transform(transform); }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void reset_offset() { set_offset(Vec3d::Zero()); }
|
void reset_offset() { set_offset(Vec3d::Zero()); }
|
||||||
|
|
|
@ -437,7 +437,7 @@ 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(); }
|
||||||
|
void set_instance_transformation(const Transform3d &transform){ m_instance_transformation.set_matrix(transform); set_bounding_boxes_as_dirty(); }
|
||||||
const Vec3d& get_instance_offset() const { return m_instance_transformation.get_offset(); }
|
const Vec3d& get_instance_offset() const { return m_instance_transformation.get_offset(); }
|
||||||
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); }
|
||||||
|
|
||||||
|
@ -464,6 +464,7 @@ 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(); }
|
||||||
|
void set_volume_transformation(const Transform3d &transform) { m_volume_transformation.set_matrix(transform); set_bounding_boxes_as_dirty(); }
|
||||||
|
|
||||||
const Vec3d& get_volume_offset() const { return m_volume_transformation.get_offset(); }
|
const Vec3d& get_volume_offset() const { return m_volume_transformation.get_offset(); }
|
||||||
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); }
|
||||||
|
|
|
@ -973,7 +973,26 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
||||||
case Rotate:
|
case Rotate:
|
||||||
{
|
{
|
||||||
// Apply new temporary rotations
|
// Apply new temporary rotations
|
||||||
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
TransformationType transformation_type;
|
||||||
|
if (m_parent.get_selection().is_wipe_tower())
|
||||||
|
transformation_type = TransformationType::World_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (evt.AltDown())
|
if (evt.AltDown())
|
||||||
transformation_type.set_independent();
|
transformation_type.set_independent();
|
||||||
selection.rotate(get_rotation(), transformation_type);
|
selection.rotate(get_rotation(), transformation_type);
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
#include <CGAL/Simple_cartesian.h>
|
||||||
|
#include <CGAL/Min_sphere_of_spheres_d.h>
|
||||||
|
#include <CGAL/Min_sphere_of_points_d_traits_3.h>
|
||||||
static const std::array<float, 4> UNIFORM_SCALE_COLOR = { 0.923f, 0.504f, 0.264f, 1.0f };
|
static const std::array<float, 4> UNIFORM_SCALE_COLOR = { 0.923f, 0.504f, 0.264f, 1.0f };
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -36,7 +39,7 @@ Selection::VolumeCache::TransformCache::TransformCache()
|
||||||
, rotation_matrix(Transform3d::Identity())
|
, rotation_matrix(Transform3d::Identity())
|
||||||
, scale_matrix(Transform3d::Identity())
|
, scale_matrix(Transform3d::Identity())
|
||||||
, mirror_matrix(Transform3d::Identity())
|
, mirror_matrix(Transform3d::Identity())
|
||||||
, full_matrix(Transform3d::Identity())
|
, full_tran(Transform3d::Identity())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +48,7 @@ Selection::VolumeCache::TransformCache::TransformCache(const Geometry::Transform
|
||||||
, rotation(transform.get_rotation())
|
, rotation(transform.get_rotation())
|
||||||
, scaling_factor(transform.get_scaling_factor())
|
, scaling_factor(transform.get_scaling_factor())
|
||||||
, mirror(transform.get_mirror())
|
, mirror(transform.get_mirror())
|
||||||
, full_matrix(transform.get_matrix())
|
, full_tran(transform)
|
||||||
{
|
{
|
||||||
rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||||
scale_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scaling_factor);
|
scale_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scaling_factor);
|
||||||
|
@ -1002,6 +1005,40 @@ void Selection::move_to_center(const Vec3d& displacement, bool local)
|
||||||
this->set_bounding_boxes_dirty();
|
this->set_bounding_boxes_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::pair<Vec3d, double> Selection::get_bounding_sphere() const
|
||||||
|
{
|
||||||
|
if (!m_bounding_sphere.has_value()) {
|
||||||
|
std::optional<std::pair<Vec3d, double>> *sphere = const_cast<std::optional<std::pair<Vec3d, double>> *>(&m_bounding_sphere);
|
||||||
|
*sphere = {Vec3d::Zero(), 0.0};
|
||||||
|
|
||||||
|
using K = CGAL::Simple_cartesian<float>;
|
||||||
|
using Traits = CGAL::Min_sphere_of_points_d_traits_3<K, float>;
|
||||||
|
using Min_sphere = CGAL::Min_sphere_of_spheres_d<Traits>;
|
||||||
|
using Point = K::Point_3;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
if (m_valid) {
|
||||||
|
for (unsigned int i : m_list) {
|
||||||
|
const GLVolume & volume = *(*m_volumes)[i];
|
||||||
|
const TriangleMesh * hull = volume.convex_hull();
|
||||||
|
const indexed_triangle_set &its = (hull != nullptr) ? hull->its : m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh().its;
|
||||||
|
const Transform3d & matrix = volume.world_matrix();
|
||||||
|
for (const Vec3f &v : its.vertices) {
|
||||||
|
const Vec3d vv = matrix * v.cast<double>();
|
||||||
|
points.push_back(Point(vv.x(), vv.y(), vv.z()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Min_sphere ms(points.begin(), points.end());
|
||||||
|
const float *center_x = ms.center_cartesian_begin();
|
||||||
|
(*sphere)->first = {*center_x, *(center_x + 1), *(center_x + 2)};
|
||||||
|
(*sphere)->second = ms.radius();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *m_bounding_sphere;
|
||||||
|
}
|
||||||
|
|
||||||
void Selection::setup_cache()
|
void Selection::setup_cache()
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid)
|
||||||
|
@ -1141,34 +1178,61 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
||||||
};
|
};
|
||||||
|
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
|
Transform3d rotation_matrix = Geometry::rotation_transform(rotation);
|
||||||
GLVolume &v = *(*m_volumes)[i];
|
GLVolume &v = *(*m_volumes)[i];
|
||||||
if (is_single_full_instance())
|
const VolumeCache &volume_data = m_cache.volumes_data[i];
|
||||||
rotate_instance(v, i);
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
else if (is_single_volume() || is_single_modifier()) {
|
if (m_mode == Instance ||is_single_full_instance()) {
|
||||||
if (transformation_type.independent())
|
assert(is_from_fully_selected_instance(i));
|
||||||
v.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation() + rotation);
|
if (transformation_type.instance()) {
|
||||||
else {
|
// ensure that the instance rotates as a rigid body
|
||||||
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix();
|
||||||
const Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
if (inst_trafo.is_left_handed()) {
|
||||||
v.set_volume_rotation(new_rotation);
|
Geometry::TransformationSVD inst_svd(inst_trafo);
|
||||||
|
inst_rotation_matrix = inst_svd.u * inst_svd.v.transpose();
|
||||||
|
// ensure the rotation has the proper direction
|
||||||
|
if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX())) rotation_matrix = rotation_matrix.inverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
|
||||||
|
rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset;
|
||||||
|
|
||||||
|
// rotate around selection center
|
||||||
|
const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.rotation_pivot - inst_trafo.get_offset());
|
||||||
|
rotation_matrix = Geometry::translation_transform(inst_pivot) * rotation_matrix * Geometry::translation_transform(-inst_pivot);
|
||||||
}
|
}
|
||||||
|
transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
|
||||||
|
}
|
||||||
|
else if (!is_single_volume_or_modifier()) {
|
||||||
|
assert(transformation_type.world());
|
||||||
|
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_mode == Instance)
|
if (transformation_type.instance()) {//in object Coordinate System
|
||||||
rotate_instance(v, i);
|
// ensure that the volume rotates as a rigid body
|
||||||
else if (m_mode == Volume) {
|
const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix();
|
||||||
// extracts rotations from the composed transformation
|
rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix;
|
||||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
} else {
|
||||||
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
if (transformation_type.local()) {
|
||||||
if (transformation_type.joint()) {
|
// ensure that the volume rotates as a rigid body
|
||||||
const Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
|
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
|
||||||
const Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
|
const Transform3d vol_matrix_no_offset = vol_trafo.get_matrix_no_offset();
|
||||||
v.set_volume_offset(local_pivot + offset);
|
const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix();
|
||||||
|
Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix();
|
||||||
|
if (vol_trafo.is_left_handed()) {
|
||||||
|
Geometry::TransformationSVD vol_svd(vol_trafo);
|
||||||
|
vol_rotation_matrix = vol_svd.u * vol_svd.v.transpose();
|
||||||
|
// ensure the rotation has the proper direction
|
||||||
|
if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX())) rotation_matrix = rotation_matrix.inverse();
|
||||||
}
|
}
|
||||||
v.set_volume_rotation(new_rotation);
|
rotation_matrix = vol_matrix_no_offset.inverse() * inst_scale_matrix.inverse() * vol_rotation_matrix * rotation_matrix *
|
||||||
|
vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2264,6 +2328,7 @@ void Selection::set_caches()
|
||||||
m_cache.sinking_volumes.push_back(i);
|
m_cache.sinking_volumes.push_back(i);
|
||||||
}
|
}
|
||||||
m_cache.dragging_center = get_bounding_box().center();
|
m_cache.dragging_center = get_bounding_box().center();
|
||||||
|
m_cache.rotation_pivot = get_bounding_sphere().first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::do_add_volume(unsigned int volume_idx)
|
void Selection::do_add_volume(unsigned int volume_idx)
|
||||||
|
@ -2915,5 +2980,45 @@ void Selection::paste_objects_from_clipboard()
|
||||||
#endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Selection::transform_instance_relative(
|
||||||
|
GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)
|
||||||
|
{
|
||||||
|
assert(transformation_type.relative());
|
||||||
|
|
||||||
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
|
if (transformation_type.world()) {
|
||||||
|
const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot;
|
||||||
|
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
|
||||||
|
volume.set_instance_transformation(trafo * inst_trafo.get_matrix());
|
||||||
|
} else if (transformation_type.instance())
|
||||||
|
volume.set_instance_transformation(inst_trafo.get_matrix() * transform);
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selection::transform_volume_relative(
|
||||||
|
GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)
|
||||||
|
{
|
||||||
|
assert(transformation_type.relative());
|
||||||
|
|
||||||
|
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
|
||||||
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
|
|
||||||
|
if (transformation_type.world()) {
|
||||||
|
const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d) (inst_trafo.get_matrix().inverse() * world_pivot);
|
||||||
|
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
|
||||||
|
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset *
|
||||||
|
Geometry::translation_transform(-inst_pivot);
|
||||||
|
volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
|
||||||
|
} else if (transformation_type.instance()) {
|
||||||
|
const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d) (inst_trafo.get_matrix().inverse() * world_pivot);
|
||||||
|
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
|
||||||
|
volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
|
||||||
|
} else if (transformation_type.local())
|
||||||
|
volume.set_volume_transformation(vol_trafo.get_matrix() * transform);
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -38,19 +38,25 @@ public:
|
||||||
enum Enum {
|
enum Enum {
|
||||||
// Transforming in a world coordinate system
|
// Transforming in a world coordinate system
|
||||||
World = 0,
|
World = 0,
|
||||||
|
// Transforming in a instance coordinate system
|
||||||
|
Instance = 1,
|
||||||
// Transforming in a local coordinate system
|
// Transforming in a local coordinate system
|
||||||
Local = 1,
|
Local = 2,
|
||||||
// Absolute transformations, allowed in local coordinate system only.
|
// Absolute transformations, allowed in local coordinate system only.
|
||||||
Absolute = 0,
|
Absolute = 0,
|
||||||
// Relative transformations, allowed in both local and world coordinate system.
|
// Relative transformations, allowed in both local and world coordinate system.
|
||||||
Relative = 2,
|
Relative = 4,
|
||||||
// For group selection, the transformation is performed as if the group made a single solid body.
|
// For group selection, the transformation is performed as if the group made a single solid body.
|
||||||
Joint = 0,
|
Joint = 0,
|
||||||
// For group selection, the transformation is performed on each object independently.
|
// For group selection, the transformation is performed on each object independently.
|
||||||
Independent = 4,
|
Independent = 8,
|
||||||
|
|
||||||
World_Relative_Joint = World | Relative | Joint,
|
World_Relative_Joint = World | Relative | Joint,
|
||||||
World_Relative_Independent = World | Relative | Independent,
|
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_Joint = Local | Absolute | Joint,
|
||||||
Local_Absolute_Independent = Local | Absolute | Independent,
|
Local_Absolute_Independent = Local | Absolute | Independent,
|
||||||
Local_Relative_Joint = Local | Relative | Joint,
|
Local_Relative_Joint = Local | Relative | Joint,
|
||||||
|
@ -59,19 +65,37 @@ public:
|
||||||
|
|
||||||
TransformationType() : m_value(World) {}
|
TransformationType() : m_value(World) {}
|
||||||
TransformationType(Enum value) : m_value(value) {}
|
TransformationType(Enum value) : m_value(value) {}
|
||||||
TransformationType& operator=(Enum value) { m_value = value; return *this; }
|
TransformationType &operator=(Enum value)
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Enum operator()() const { return m_value; }
|
Enum operator()() const { return m_value; }
|
||||||
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
|
bool has(Enum v) const { return ((unsigned int) m_value & (unsigned int) v) != 0; }
|
||||||
|
|
||||||
void set_world() { this->remove(Local); }
|
void set_world()
|
||||||
void set_local() { this->add(Local); }
|
{
|
||||||
|
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_absolute() { this->remove(Relative); }
|
||||||
void set_relative() { this->add(Relative); }
|
void set_relative() { this->add(Relative); }
|
||||||
void set_joint() { this->remove(Independent); }
|
void set_joint() { this->remove(Independent); }
|
||||||
void set_independent() { this->add(Independent); }
|
void set_independent() { this->add(Independent); }
|
||||||
|
|
||||||
bool world() const { return !this->has(Local); }
|
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 local() const { return this->has(Local); }
|
||||||
bool absolute() const { return !this->has(Relative); }
|
bool absolute() const { return !this->has(Relative); }
|
||||||
bool relative() const { return this->has(Relative); }
|
bool relative() const { return this->has(Relative); }
|
||||||
|
@ -125,7 +149,7 @@ private:
|
||||||
Transform3d rotation_matrix;
|
Transform3d rotation_matrix;
|
||||||
Transform3d scale_matrix;
|
Transform3d scale_matrix;
|
||||||
Transform3d mirror_matrix;
|
Transform3d mirror_matrix;
|
||||||
Transform3d full_matrix;
|
Geometry::Transformation full_tran;
|
||||||
|
|
||||||
TransformCache();
|
TransformCache();
|
||||||
explicit TransformCache(const Geometry::Transformation& transform);
|
explicit TransformCache(const Geometry::Transformation& transform);
|
||||||
|
@ -145,7 +169,7 @@ private:
|
||||||
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_tran.get_matrix(); }
|
||||||
|
|
||||||
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; }
|
||||||
|
@ -154,7 +178,10 @@ private:
|
||||||
const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
|
const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
|
||||||
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_tran.get_matrix(); }
|
||||||
|
|
||||||
|
const Geometry::Transformation &get_volume_transform() const { return m_volume.full_tran; }
|
||||||
|
const Geometry::Transformation &get_instance_transform() const { return m_instance.full_tran; }
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -199,6 +226,7 @@ private:
|
||||||
ObjectIdxsToInstanceIdxsMap content;
|
ObjectIdxsToInstanceIdxsMap content;
|
||||||
// List of ids of the volumes which are sinking when starting dragging
|
// List of ids of the volumes which are sinking when starting dragging
|
||||||
std::vector<unsigned int> sinking_volumes;
|
std::vector<unsigned int> sinking_volumes;
|
||||||
|
Vec3d rotation_pivot;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Volumes owned by GLCanvas3D.
|
// Volumes owned by GLCanvas3D.
|
||||||
|
@ -223,6 +251,8 @@ private:
|
||||||
// Bounding box aligned to the axis of the currently selected reference system (World/Object/Part)
|
// Bounding box aligned to the axis of the currently selected reference system (World/Object/Part)
|
||||||
// and transform to place and orient it in world coordinates
|
// and transform to place and orient it in world coordinates
|
||||||
std::optional<std::pair<BoundingBoxf3, Transform3d>> m_bounding_box_in_current_reference_system;
|
std::optional<std::pair<BoundingBoxf3, Transform3d>> m_bounding_box_in_current_reference_system;
|
||||||
|
|
||||||
|
std::optional<std::pair<Vec3d, double>> m_bounding_sphere;
|
||||||
#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
|
||||||
|
@ -350,6 +380,8 @@ public:
|
||||||
void start_dragging();
|
void start_dragging();
|
||||||
void stop_dragging() { m_dragging = false; }
|
void stop_dragging() { m_dragging = false; }
|
||||||
bool is_dragging() const { return m_dragging; }
|
bool is_dragging() const { return m_dragging; }
|
||||||
|
// Returns the bounding sphere: first = center, second = radius
|
||||||
|
const std::pair<Vec3d, double> get_bounding_sphere() const;
|
||||||
|
|
||||||
void setup_cache();
|
void setup_cache();
|
||||||
void translate(const Vec3d& displacement, bool local = false);
|
void translate(const Vec3d& displacement, bool local = false);
|
||||||
|
@ -425,6 +457,7 @@ private:
|
||||||
m_bounding_box.reset();
|
m_bounding_box.reset();
|
||||||
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
||||||
m_bounding_box_in_current_reference_system.reset();
|
m_bounding_box_in_current_reference_system.reset();
|
||||||
|
m_bounding_sphere.reset();
|
||||||
}
|
}
|
||||||
void render_selected_volumes() const;
|
void render_selected_volumes() const;
|
||||||
void render_synchronized_volumes() const;
|
void render_synchronized_volumes() const;
|
||||||
|
@ -452,6 +485,11 @@ private:
|
||||||
|
|
||||||
void paste_volumes_from_clipboard();
|
void paste_volumes_from_clipboard();
|
||||||
void paste_objects_from_clipboard();
|
void paste_objects_from_clipboard();
|
||||||
|
|
||||||
|
void transform_instance_relative(
|
||||||
|
GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot);
|
||||||
|
void transform_volume_relative(
|
||||||
|
GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
|
Loading…
Reference in New Issue