mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-02 06:40:39 +08:00
move matrix decomposition to instance class
This commit is contained in:
parent
5aa8d8e748
commit
794b3a1419
@ -503,13 +503,13 @@ TMFParserContext::startElement(const char *name, const char **atts)
|
||||
// Apply transformation if supplied.
|
||||
const char* transformation_matrix = get_attribute(atts, "transform");
|
||||
if(transformation_matrix){
|
||||
// Decompose the affine matrix.
|
||||
TransformationMatrix trafo;
|
||||
std::vector<double> single_transformations;
|
||||
if(!get_transformations(transformation_matrix, trafo, &single_transformations))
|
||||
if(!extract_trafo(transformation_matrix, trafo))
|
||||
this->stop();
|
||||
|
||||
apply_transformation(instance, trafo, single_transformations);
|
||||
// Decompose the affine matrix.
|
||||
instance->set_complete_trafo(trafo);
|
||||
}
|
||||
|
||||
node_type_new = NODE_TYPE_ITEM;
|
||||
@ -560,7 +560,7 @@ TMFParserContext::startElement(const char *name, const char **atts)
|
||||
if(transformation_matrix){
|
||||
TransformationMatrix trafo;
|
||||
|
||||
if(!get_transformations(transformation_matrix, trafo))
|
||||
if(!extract_trafo(transformation_matrix, trafo))
|
||||
this->stop();
|
||||
|
||||
volume->apply_transformation(trafo);
|
||||
@ -708,7 +708,7 @@ TMFParserContext::stop()
|
||||
}
|
||||
|
||||
bool
|
||||
TMFParserContext::get_transformations(std::string matrix, TransformationMatrix &trafo, std::vector<double>* transformations)
|
||||
TMFParserContext::extract_trafo(std::string matrix, TransformationMatrix &trafo)
|
||||
{
|
||||
// Get the values.
|
||||
double m[12];
|
||||
@ -741,93 +741,9 @@ TMFParserContext::get_transformations(std::string matrix, TransformationMatrix &
|
||||
trafo.m13 = m[10];
|
||||
trafo.m23 = m[11];
|
||||
|
||||
if (transformations)
|
||||
{
|
||||
|
||||
transformations->push_back(m[9]);
|
||||
transformations->push_back(m[10]);
|
||||
|
||||
// Get the scale values.
|
||||
double sx = sqrt( m[0] * m[0] + m[1] * m[1] + m[2] * m[2]),
|
||||
sy = sqrt( m[3] * m[3] + m[4] * m[4] + m[5] * m[5]),
|
||||
sz = sqrt( m[6] * m[6] + m[7] * m[7] + m[8] * m[8]);
|
||||
|
||||
double uniform_scaling = (sx + sy + sz) / 3;
|
||||
transformations->push_back(uniform_scaling);
|
||||
|
||||
// Get the rotation values.
|
||||
// Normalize scale from the rotation matrix.
|
||||
m[0] /= sx; m[1] /= sy; m[2] /= sz;
|
||||
m[3] /= sx; m[4] /= sy; m[5] /= sz;
|
||||
m[6] /= sx; m[7] /= sy; m[8] /= sz;
|
||||
|
||||
// Get quaternion values
|
||||
double q_w = sqrt(std::max(0.0, 1.0 + m[0] + m[4] + m[8])) / 2,
|
||||
q_x = sqrt(std::max(0.0, 1.0 + m[0] - m[4] - m[8])) / 2,
|
||||
q_y = sqrt(std::max(0.0, 1.0 - m[0] + m[4] - m[8])) / 2,
|
||||
q_z = sqrt(std::max(0.0, 1.0 - m[0] - m[4] + m[8])) / 2;
|
||||
|
||||
q_x *= ((q_x * (m[5] - m[7])) <= 0 ? -1 : 1);
|
||||
q_y *= ((q_y * (m[6] - m[2])) <= 0 ? -1 : 1);
|
||||
q_z *= ((q_z * (m[1] - m[3])) <= 0 ? -1 : 1);
|
||||
|
||||
// Normalize quaternion values.
|
||||
double q_magnitude = sqrt(q_w * q_w + q_x * q_x + q_y * q_y + q_z * q_z);
|
||||
q_w /= q_magnitude;
|
||||
q_x /= q_magnitude;
|
||||
q_y /= q_magnitude;
|
||||
q_z /= q_magnitude;
|
||||
|
||||
double test = q_x * q_y + q_z * q_w;
|
||||
double result_z;
|
||||
// singularity at north pole
|
||||
if (test > 0.499)
|
||||
{
|
||||
result_z = PI / 2;
|
||||
}
|
||||
// singularity at south pole
|
||||
else if (test < -0.499)
|
||||
{
|
||||
result_z = -PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_z = asin(2 * q_x * q_y + 2 * q_z * q_w);
|
||||
|
||||
if (result_z < 0) result_z += 2 * PI;
|
||||
}
|
||||
transformations->push_back(result_z);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TMFParserContext::apply_transformation(ModelInstance *instance, const TransformationMatrix& complete_trafo, const std::vector<double>& single_transformations)
|
||||
{
|
||||
// Reset internal trafo
|
||||
instance->additional_trafo = TransformationMatrix::mat_eye();
|
||||
|
||||
// Apply scale.
|
||||
instance->scaling_factor = single_transformations[2];
|
||||
|
||||
// Apply z rotation.
|
||||
instance->rotation = single_transformations[3];
|
||||
|
||||
// Apply translation.
|
||||
instance->offset.x = single_transformations[0];
|
||||
instance->offset.y = single_transformations[1];
|
||||
|
||||
// Complete = Instance * Additional
|
||||
// -> Instance^-1 * Complete = (Instance^-1 * Instance) * Additional
|
||||
// -> Instance^-1 * Complete = Additional
|
||||
instance->additional_trafo = TransformationMatrix::multiply(
|
||||
instance->get_trafo_matrix().inverse(),
|
||||
complete_trafo);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ModelVolume*
|
||||
TMFParserContext::add_volume(int start_offset, int end_offset, bool modifier)
|
||||
{
|
||||
|
@ -144,11 +144,10 @@ struct TMFParserContext{
|
||||
void characters(const XML_Char *s, int len);
|
||||
void stop();
|
||||
|
||||
/// Get scale, rotation and scale transformation from affine matrix.
|
||||
/// Get transformation from string encoded matrix.
|
||||
/// \param matrix string the 3D matrix where elements are separated by space.
|
||||
/// \return TransformationMatrix a matrix that contains the complete defined transformation.
|
||||
/// \return optional vector<double> a vector contains [translation x, y, uniform scale factor, zRotation].
|
||||
bool get_transformations(std::string matrix, TransformationMatrix& trafo, std::vector<double>* transformations = nullptr);
|
||||
bool extract_trafo(std::string matrix, TransformationMatrix& trafo);
|
||||
|
||||
/// Add a new volume to the current object.
|
||||
/// \param start_offset size_t the start index in the m_volume_facets vector.
|
||||
@ -157,10 +156,6 @@ struct TMFParserContext{
|
||||
/// \return ModelVolume* a pointer to the newly added volume.
|
||||
ModelVolume* add_volume(int start_offset, int end_offset, bool modifier);
|
||||
|
||||
/// Apply scale, rotate & translate to the given instance.
|
||||
/// \param instance ModelInstance*
|
||||
/// \param transfornmations vector<int>
|
||||
void apply_transformation(ModelInstance* instance, const TransformationMatrix& complete_trafo, const std::vector<double>& single_transformations);
|
||||
};
|
||||
|
||||
} }
|
||||
|
@ -1170,8 +1170,15 @@ ModelInstance::ModelInstance(ModelObject *object)
|
||||
: rotation(0), scaling_factor(1), object(object)
|
||||
{}
|
||||
|
||||
ModelInstance::ModelInstance(ModelObject *object, const TransformationMatrix & trafo)
|
||||
: object(object)
|
||||
{
|
||||
this->set_complete_trafo(trafo);
|
||||
}
|
||||
|
||||
|
||||
ModelInstance::ModelInstance(ModelObject *object, const ModelInstance &other)
|
||||
: rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object)
|
||||
: rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), additional_trafo(other.additional_trafo), object(object)
|
||||
{}
|
||||
|
||||
ModelInstance& ModelInstance::operator= (ModelInstance other)
|
||||
@ -1186,6 +1193,77 @@ ModelInstance::swap(ModelInstance &other)
|
||||
std::swap(this->rotation, other.rotation);
|
||||
std::swap(this->scaling_factor, other.scaling_factor);
|
||||
std::swap(this->offset, other.offset);
|
||||
std::swap(this->additional_trafo, other.additional_trafo);
|
||||
}
|
||||
|
||||
void ModelInstance::set_complete_trafo(TransformationMatrix const & trafo)
|
||||
{
|
||||
// Extraction code moved from TMF class
|
||||
|
||||
this->offset.x = trafo.m03;
|
||||
this->offset.y = trafo.m13;
|
||||
|
||||
// Get the scale values.
|
||||
double sx = sqrt( trafo.m00 * trafo.m00 + trafo.m10 * trafo.m10 + trafo.m20 * trafo.m20),
|
||||
sy = sqrt( trafo.m01 * trafo.m01 + trafo.m11 * trafo.m11 + trafo.m21 * trafo.m21),
|
||||
sz = sqrt( trafo.m02 * trafo.m02 + trafo.m12 * trafo.m12 + trafo.m22 * trafo.m22);
|
||||
|
||||
this->scaling_factor = (sx + sy + sz) / 3;
|
||||
|
||||
// Get the rotation values.
|
||||
// Normalize scale from the matrix.
|
||||
TransformationMatrix rotmat = trafo.multiplyLeft(TransformationMatrix::mat_scale(1/sx, 1/sy, 1/sz));
|
||||
rotmat.m00 /= sx; rotmat.m10 /= sy; rotmat.m20 /= sz;
|
||||
rotmat.m01 /= sx; rotmat.m11 /= sy; rotmat.m21 /= sz;
|
||||
rotmat.m02 /= sx; rotmat.m12 /= sy; rotmat.m22 /= sz;
|
||||
|
||||
// Get quaternion values
|
||||
double q_w = sqrt(std::max(0.0, 1.0 + rotmat.m00 + rotmat.m11 + rotmat.m22)) / 2,
|
||||
q_x = sqrt(std::max(0.0, 1.0 + rotmat.m00 - rotmat.m11 - rotmat.m22)) / 2,
|
||||
q_y = sqrt(std::max(0.0, 1.0 - rotmat.m00 + rotmat.m11 - rotmat.m22)) / 2,
|
||||
q_z = sqrt(std::max(0.0, 1.0 - rotmat.m00 - rotmat.m11 + rotmat.m22)) / 2;
|
||||
|
||||
q_x *= ((q_x * (rotmat.m21 - rotmat.m12)) <= 0 ? -1 : 1);
|
||||
q_y *= ((q_y * (rotmat.m02 - rotmat.m20)) <= 0 ? -1 : 1);
|
||||
q_z *= ((q_z * (rotmat.m10 - rotmat.m01)) <= 0 ? -1 : 1);
|
||||
|
||||
// Normalize quaternion values.
|
||||
double q_magnitude = sqrt(q_w * q_w + q_x * q_x + q_y * q_y + q_z * q_z);
|
||||
q_w /= q_magnitude;
|
||||
q_x /= q_magnitude;
|
||||
q_y /= q_magnitude;
|
||||
q_z /= q_magnitude;
|
||||
|
||||
double test = q_x * q_y + q_z * q_w;
|
||||
double result_z;
|
||||
// singularity at north pole
|
||||
if (test > 0.499)
|
||||
{
|
||||
result_z = PI / 2;
|
||||
}
|
||||
// singularity at south pole
|
||||
else if (test < -0.499)
|
||||
{
|
||||
result_z = -PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_z = asin(2 * q_x * q_y + 2 * q_z * q_w);
|
||||
|
||||
if (result_z < 0) result_z += 2 * PI;
|
||||
}
|
||||
|
||||
this->rotation = result_z;
|
||||
|
||||
this->additional_trafo = TransformationMatrix::mat_eye();
|
||||
|
||||
// Complete = Instance * Additional
|
||||
// -> Instance^-1 * Complete = (Instance^-1 * Instance) * Additional
|
||||
// -> Instance^-1 * Complete = Additional
|
||||
this->additional_trafo = TransformationMatrix::multiply(
|
||||
this->get_trafo_matrix().inverse(),
|
||||
trafo);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -1209,9 +1287,7 @@ TransformationMatrix ModelInstance::get_trafo_matrix(bool dont_translate) const
|
||||
|
||||
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
|
||||
{
|
||||
// rotate around mesh origin
|
||||
double c = cos(this->rotation);
|
||||
double s = sin(this->rotation);
|
||||
TransformationMatrix
|
||||
Pointf3 pts[4] = {
|
||||
bbox.min,
|
||||
bbox.max,
|
||||
|
@ -605,6 +605,9 @@ class ModelInstance
|
||||
/// \return ModelObject* pointer to the owner ModelObject
|
||||
ModelObject* get_object() const { return this->object; };
|
||||
|
||||
/// Set the internal instance parameters by extracting them from the given complete transformation
|
||||
void set_complete_trafo(TransformationMatrix const & trafo);
|
||||
|
||||
//TRAFO:should be deprecated
|
||||
/// Transform an external TriangleMesh object
|
||||
/// \param mesh TriangleMesh* pointer to the the mesh
|
||||
@ -632,6 +635,11 @@ class ModelInstance
|
||||
/// \param object ModelObject* pointer to the owner ModelObject
|
||||
ModelInstance(ModelObject *object);
|
||||
|
||||
/// Constructor
|
||||
/// \param object ModelObject* pointer to the owner ModelObject
|
||||
/// \param trafo transformation that the Model Instance should initially represent
|
||||
ModelInstance(ModelObject *object, const TransformationMatrix & trafo);
|
||||
|
||||
/// Constructor
|
||||
/// \param object ModelObject* pointer to the owner ModelObject
|
||||
/// \param other ModelInstance an instance to be copied in the new ModelInstance object
|
||||
|
Loading…
x
Reference in New Issue
Block a user