Lay flat - rotation is now done in one go directly about the necessary axis
This commit is contained in:
parent
d197a5149a
commit
86b67bbd42
@ -140,10 +140,16 @@ sub new {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# callback to react to gizmo rotate
|
# callback to react to gizmo rotate
|
||||||
|
# omitting last three parameters means rotation around Z
|
||||||
|
# otherwise they are the components of the rotation axis vector
|
||||||
my $on_gizmo_rotate = sub {
|
my $on_gizmo_rotate = sub {
|
||||||
my ($angle_z, $angle_y) = @_;
|
my ($angle, $axis_x, $axis_y, $axis_z) = @_;
|
||||||
$self->rotate(rad2deg($angle_z), Z, 'absolute');
|
if (!defined $axis_x) {
|
||||||
$self->rotate(rad2deg($angle_y), Y, 'absolute') if $angle_y != 0;
|
$self->rotate(rad2deg($angle), Z, 'absolute');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->rotate(rad2deg($angle), undef, 'absolute', $axis_x, $axis_y, $axis_z) if $angle != 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
# callback to update object's geometry info while using gizmos
|
# callback to update object's geometry info while using gizmos
|
||||||
@ -1031,28 +1037,40 @@ sub _get_number_from_user {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub rotate {
|
sub rotate {
|
||||||
my ($self, $angle, $axis, $relative_key) = @_;
|
my ($self, $angle, $axis, $relative_key, $axis_x, $axis_y, $axis_z) = @_;
|
||||||
$relative_key //= 'absolute'; # relative or absolute coordinates
|
$relative_key //= 'absolute'; # relative or absolute coordinates
|
||||||
$axis //= Z; # angle is in degrees
|
$axis_x //= 0;
|
||||||
|
$axis_y //= 0;
|
||||||
|
$axis_z //= 0;
|
||||||
my $relative = $relative_key eq 'relative';
|
my $relative = $relative_key eq 'relative';
|
||||||
|
|
||||||
my ($obj_idx, $object) = $self->selected_object;
|
my ($obj_idx, $object) = $self->selected_object;
|
||||||
return if !defined $obj_idx;
|
return if !defined $obj_idx;
|
||||||
|
|
||||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||||
my $model_instance = $model_object->instances->[0];
|
my $model_instance = $model_object->instances->[0];
|
||||||
|
|
||||||
if (!defined $angle) {
|
if (!defined $angle) {
|
||||||
my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z';
|
my $axis_name = $axis == X ? 'X' : $axis == Y ? 'Y' : 'Z';
|
||||||
my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0;
|
my $default = $axis == Z ? rad2deg($model_instance->rotation) : 0;
|
||||||
$angle = $self->_get_number_from_user(L("Enter the rotation angle:"), L("Rotate around ").$axis_name.(" axis"), L("Invalid rotation angle entered"), $default);
|
$angle = $self->_get_number_from_user(L("Enter the rotation angle:"), L("Rotate around ").$axis_name.(" axis"), L("Invalid rotation angle entered"), $default);
|
||||||
return if $angle eq '';
|
return if $angle eq '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Let's calculate vector of rotation axis (if we don't have it already)
|
||||||
|
# The minus is there so that the direction is the same as was established
|
||||||
|
if (defined $axis) {
|
||||||
|
if ($axis == X) {
|
||||||
|
$axis_x = -1;
|
||||||
|
}
|
||||||
|
if ($axis == Y) {
|
||||||
|
$axis_y = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$self->stop_background_process;
|
$self->stop_background_process;
|
||||||
|
|
||||||
if ($axis == Z) {
|
if (defined $axis && $axis == Z) {
|
||||||
my $new_angle = deg2rad($angle);
|
my $new_angle = deg2rad($angle);
|
||||||
foreach my $inst (@{ $model_object->instances }) {
|
foreach my $inst (@{ $model_object->instances }) {
|
||||||
my $rotation = ($relative ? $inst->rotation : 0.) + $new_angle;
|
my $rotation = ($relative ? $inst->rotation : 0.) + $new_angle;
|
||||||
@ -1067,13 +1085,15 @@ sub rotate {
|
|||||||
}
|
}
|
||||||
# $object->transform_thumbnail($self->{model}, $obj_idx);
|
# $object->transform_thumbnail($self->{model}, $obj_idx);
|
||||||
} else {
|
} else {
|
||||||
# rotation around X and Y needs to be performed on mesh
|
if (defined $axis) {
|
||||||
# so we first apply any Z rotation
|
# rotation around X and Y needs to be performed on mesh
|
||||||
if ($model_instance->rotation != 0) {
|
# so we first apply any Z rotation
|
||||||
$model_object->rotate($model_instance->rotation, Z);
|
if ($model_instance->rotation != 0) {
|
||||||
$_->set_rotation(0) for @{ $model_object->instances };
|
$model_object->rotate($model_instance->rotation, Slic3r::Pointf3->new(0, 0, -1));
|
||||||
|
$_->set_rotation(0) for @{ $model_object->instances };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$model_object->rotate(deg2rad($angle), $axis);
|
$model_object->rotate(deg2rad($angle), Slic3r::Pointf3->new($axis_x, $axis_y, $axis_z));
|
||||||
|
|
||||||
# # realign object to Z = 0
|
# # realign object to Z = 0
|
||||||
# $model_object->center_around_origin;
|
# $model_object->center_around_origin;
|
||||||
@ -1099,7 +1119,7 @@ sub mirror {
|
|||||||
|
|
||||||
# apply Z rotation before mirroring
|
# apply Z rotation before mirroring
|
||||||
if ($model_instance->rotation != 0) {
|
if ($model_instance->rotation != 0) {
|
||||||
$model_object->rotate($model_instance->rotation, Z);
|
$model_object->rotate($model_instance->rotation, Slic3r::Pointf3->new(0, 0, 1));
|
||||||
$_->set_rotation(0) for @{ $model_object->instances };
|
$_->set_rotation(0) for @{ $model_object->instances };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1146,7 +1166,7 @@ sub changescale {
|
|||||||
|
|
||||||
# apply Z rotation before scaling
|
# apply Z rotation before scaling
|
||||||
if ($model_instance->rotation != 0) {
|
if ($model_instance->rotation != 0) {
|
||||||
$model_object->rotate($model_instance->rotation, Z);
|
$model_object->rotate($model_instance->rotation, Slic3r::Pointf3->new(0, 0, 1));
|
||||||
$_->set_rotation(0) for @{ $model_object->instances };
|
$_->set_rotation(0) for @{ $model_object->instances };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +725,7 @@ void ModelObject::scale(const Pointf3 &versor)
|
|||||||
this->invalidate_bounding_box();
|
this->invalidate_bounding_box();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelObject::rotate(float angle, const Axis &axis)
|
void ModelObject::rotate(float angle, const Pointf3& axis)
|
||||||
{
|
{
|
||||||
for (ModelVolume *v : this->volumes)
|
for (ModelVolume *v : this->volumes)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ public:
|
|||||||
void translate(const Vectorf3 &vector) { this->translate(vector.x, vector.y, vector.z); }
|
void translate(const Vectorf3 &vector) { this->translate(vector.x, vector.y, vector.z); }
|
||||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||||
void scale(const Pointf3 &versor);
|
void scale(const Pointf3 &versor);
|
||||||
void rotate(float angle, const Axis &axis);
|
void rotate(float angle, const Pointf3& axis);
|
||||||
void transform(const float* matrix3x4);
|
void transform(const float* matrix3x4);
|
||||||
void mirror(const Axis &axis);
|
void mirror(const Axis &axis);
|
||||||
size_t materials_count() const;
|
size_t materials_count() const;
|
||||||
|
@ -324,6 +324,17 @@ void TriangleMesh::translate(float x, float y, float z)
|
|||||||
stl_invalidate_shared_vertices(&this->stl);
|
stl_invalidate_shared_vertices(&this->stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TriangleMesh::rotate(float angle, Pointf3 axis)
|
||||||
|
{
|
||||||
|
if (angle == 0.f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
axis = normalize(axis);
|
||||||
|
Eigen::Transform<float, 3, Eigen::Affine> m = Eigen::Transform<float, 3, Eigen::Affine>::Identity();
|
||||||
|
m.rotate(Eigen::AngleAxisf(angle, Eigen::Vector3f(axis.x, axis.y, axis.z)));
|
||||||
|
stl_transform(&stl, (float*)m.data());
|
||||||
|
}
|
||||||
|
|
||||||
void TriangleMesh::rotate(float angle, const Axis &axis)
|
void TriangleMesh::rotate(float angle, const Axis &axis)
|
||||||
{
|
{
|
||||||
if (angle == 0.f)
|
if (angle == 0.f)
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
void scale(const Pointf3 &versor);
|
void scale(const Pointf3 &versor);
|
||||||
void translate(float x, float y, float z);
|
void translate(float x, float y, float z);
|
||||||
void rotate(float angle, const Axis &axis);
|
void rotate(float angle, const Axis &axis);
|
||||||
|
void rotate(float angle, Pointf3 axis);
|
||||||
void rotate_x(float angle);
|
void rotate_x(float angle);
|
||||||
void rotate_y(float angle);
|
void rotate_y(float angle);
|
||||||
void rotate_z(float angle);
|
void rotate_z(float angle);
|
||||||
|
@ -2805,9 +2805,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
// Rotate the object so the normal points downward:
|
// Rotate the object so the normal points downward:
|
||||||
Pointf3 normal = m_gizmos.get_flattening_normal();
|
Pointf3 normal = m_gizmos.get_flattening_normal();
|
||||||
if (normal.x != 0.f || normal.y != 0.f || normal.z != 0.f) {
|
if (normal.x != 0.f || normal.y != 0.f || normal.z != 0.f) {
|
||||||
float angle_z = -atan2(normal.y, normal.x);
|
Pointf3 axis = normal.z > 0.999f ? Pointf3(1, 0, 0) : cross(normal, Pointf3(0.f, 0.f, -1.f));
|
||||||
float angle_y = M_PI - atan2(normal.x*cos(angle_z)-normal.y*sin(angle_z), normal.z);
|
float angle = -acos(-normal.z);
|
||||||
m_on_gizmo_rotate_callback.call((double)angle_z, (double)angle_y);
|
m_on_gizmo_rotate_callback.call(angle, axis.x, axis.y, axis.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3093,7 +3093,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
}
|
}
|
||||||
case Gizmos::Rotate:
|
case Gizmos::Rotate:
|
||||||
{
|
{
|
||||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z(), 0.);
|
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -706,12 +706,14 @@ void GLGizmoFlatten::update_planes()
|
|||||||
}
|
}
|
||||||
polygon = Slic3r::Geometry::convex_hull(polygon); // To remove the inner points
|
polygon = Slic3r::Geometry::convex_hull(polygon); // To remove the inner points
|
||||||
|
|
||||||
// Calculate area of the polygon and discard ones that are too small
|
// We will calculate area of the polygon and discard ones that are too small
|
||||||
|
// The limit is more forgiving in case the normal is in the direction of the coordinate axes
|
||||||
|
const float minimal_area = (std::abs(normal.x) > 0.999f || std::abs(normal.y) > 0.999f || std::abs(normal.z) > 0.999f) ? 1.f : 20.f;
|
||||||
float area = 0.f;
|
float area = 0.f;
|
||||||
for (unsigned int i = 0; i < polygon.size(); i++) // Shoelace formula
|
for (unsigned int i = 0; i < polygon.size(); i++) // Shoelace formula
|
||||||
area += polygon[i].x*polygon[i+1 < polygon.size() ? i+1 : 0 ].y - polygon[i+1 < polygon.size() ? i+1 : 0].x*polygon[i].y;
|
area += polygon[i].x*polygon[i+1 < polygon.size() ? i+1 : 0 ].y - polygon[i+1 < polygon.size() ? i+1 : 0].x*polygon[i].y;
|
||||||
area = std::abs(area/2.f);
|
area = std::abs(area/2.f);
|
||||||
if (area < 20.f) {
|
if (area < minimal_area) {
|
||||||
m_planes.erase(m_planes.begin()+(polygon_id--));
|
m_planes.erase(m_planes.begin()+(polygon_id--));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,8 @@ ModelMaterial::attributes()
|
|||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
void scale_xyz(Pointf3* versor)
|
void scale_xyz(Pointf3* versor)
|
||||||
%code{% THIS->scale(*versor); %};
|
%code{% THIS->scale(*versor); %};
|
||||||
void rotate(float angle, Axis axis);
|
void rotate(float angle, Pointf3* axis)
|
||||||
|
%code{% THIS->rotate(angle, *axis); %};
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
|
|
||||||
Model* cut(double z)
|
Model* cut(double z)
|
||||||
|
Loading…
Reference in New Issue
Block a user