transform properties

This commit is contained in:
AndreaRigoni
2026-03-27 02:43:30 +00:00
parent 09859e872c
commit 93e5602562
12 changed files with 299 additions and 114 deletions

View File

@@ -50,6 +50,7 @@
#define U_TRANSFORM_H
#include <Eigen/Geometry>
#include "Math/Units.h"
#include "Math/Dense.h"
@@ -59,27 +60,65 @@ namespace uLib {
///////// AFFINE TRANSFORM WRAPPER //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class AffineTransform {
class AffineTransform : virtual public Object {
public:
uLibTypeMacro(AffineTransform, Object)
/**
* @brief Grouped transformation parameters for property-based control.
*/
struct {
Vector3f Position = Vector3f::Zero();
Vector3f Orientation = Vector3f::Zero();
Vector3f Scale = Vector3f::Ones();
template <class ArchiveT>
void serialize(ArchiveT & ar, const unsigned int version) {
ar & HRPU(Position, "mm");
ar & HRPU(Orientation, "deg");
ar & HRP(Scale);
}
} Transform;
protected:
Eigen::Affine3f m_T;
AffineTransform *m_Parent;
public:
AffineTransform() :
m_T(Matrix4f::Identity()),
m_Parent(NULL)
{}
{
ULIB_ACTIVATE_PROPERTIES(*this);
this->Sync();
}
virtual ~AffineTransform() {}
AffineTransform(AffineTransform *parent) :
m_T(Matrix4f::Identity()),
m_Parent(parent)
{}
{
ULIB_ACTIVATE_PROPERTIES(*this);
this->Sync();
}
AffineTransform(const AffineTransform &copy) :
m_T(copy.m_T),
m_Parent(copy.m_Parent)
{}
m_Parent(copy.m_Parent),
Transform(copy.Transform)
{
ULIB_ACTIVATE_PROPERTIES(*this);
this->Sync();
}
/**
* @brief Registration of properties in groups.
*/
template <class ArchiveT>
void serialize(ArchiveT & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("Transform", Transform);
}
Eigen::Affine3f& GetTransform() { return m_T; }
@@ -87,7 +126,11 @@ public:
void SetParent(AffineTransform *name) { this->m_Parent = name; }
void SetMatrix (Matrix4f mat) { m_T.matrix() = mat; }
void SetMatrix (Matrix4f mat) {
m_T.matrix() = mat;
this->UpdatePropertiesFromMatrix();
}
Matrix4f GetMatrix() const { return m_T.matrix(); }
Matrix4f GetWorldMatrix() const
@@ -96,32 +139,51 @@ public:
else return m_Parent->GetWorldMatrix() * m_T.matrix(); // T = B * A //
}
void SetPosition(const Vector3f v) { this->m_T.translation() = v; }
void SetPosition(const Vector3f v) {
this->Transform.Position = v;
this->Sync();
}
Vector3f GetPosition() const { return this->m_T.translation(); }
Vector3f GetPosition() const { return this->Transform.Position; }
void SetRotation(const Matrix3f m) { this->m_T.linear() = m; }
void SetRotation(const Matrix3f m) {
this->m_T.linear() = m;
this->UpdatePropertiesFromMatrix();
}
Matrix3f GetRotation() const { return this->m_T.rotation(); }
void Translate(const Vector3f v) { this->m_T.translate(v); }
void Scale(const Vector3f v) { this->m_T.scale(v); }
Vector3f GetScale() const {
return Vector3f(m_T.linear().col(0).norm(),
m_T.linear().col(1).norm(),
m_T.linear().col(2).norm());
void Translate(const Vector3f v) {
this->Transform.Position += v;
this->Sync();
}
void Scale(const Vector3f v) {
this->Transform.Scale = this->Transform.Scale.cwiseProduct(v);
this->Sync();
}
void Rotate(const Matrix3f m) { this->m_T.rotate(m); }
Vector3f GetScale() const { return this->Transform.Scale; }
void SetOrientation(const Vector3f v) {
this->Transform.Orientation = v;
this->Sync();
}
Vector3f GetOrientation() const { return this->Transform.Orientation; }
void Rotate(const Matrix3f m) {
this->m_T.rotate(m);
this->UpdatePropertiesFromMatrix();
}
void Rotate(const float angle, Vector3f axis)
{
axis.normalize(); // prehaps not necessary ( see eigens )
axis.normalize();
Eigen::AngleAxisf ax(angle,axis);
this->m_T.rotate(Eigen::Quaternion<float>(ax));
this->UpdatePropertiesFromMatrix();
}
void Rotate(const Vector3f euler_axis) {
@@ -129,17 +191,14 @@ public:
Rotate(angle,euler_axis);
}
void PreRotate(const Matrix3f m) { this->m_T.prerotate(m); }
void PreRotate(const Matrix3f m) { this->m_T.prerotate(m); this->UpdatePropertiesFromMatrix(); }
void QuaternionRotate(const Vector4f q)
{ this->m_T.rotate(Eigen::Quaternion<float>(q)); }
{ this->m_T.rotate(Eigen::Quaternion<float>(q)); this->UpdatePropertiesFromMatrix(); }
void EulerYZYRotate(const Vector3f e) {
Matrix3f mat;
mat = Eigen::AngleAxisf(e.x(), Vector3f::UnitY())
* Eigen::AngleAxisf(e.y(), Vector3f::UnitZ())
* Eigen::AngleAxisf(e.z(), Vector3f::UnitY());
m_T.rotate(mat);
this->Transform.Orientation = e;
this->Sync();
}
void FlipAxes(int first, int second)
@@ -147,7 +206,61 @@ public:
Matrix3f mat = Matrix3f::Identity();
mat.col(first).swap(mat.col(second));
m_T.rotate(mat);
this->UpdatePropertiesFromMatrix();
}
/**
* @brief Decomposes the internal matrix m_T back into Position, Orientation, and Scale properties.
*/
void UpdatePropertiesFromMatrix() {
// 1. Position
Transform.Position = m_T.translation();
// 2. Scale
Matrix3f linear = m_T.linear();
Transform.Scale(0) = linear.col(0).norm();
Transform.Scale(1) = linear.col(1).norm();
Transform.Scale(2) = linear.col(2).norm();
// 3. Rotation (Normalization removes scale)
Matrix3f rotation = linear;
if (Transform.Scale(0) > 1e-6) rotation.col(0) /= Transform.Scale(0);
if (Transform.Scale(1) > 1e-6) rotation.col(1) /= Transform.Scale(1);
if (Transform.Scale(2) > 1e-6) rotation.col(2) /= Transform.Scale(2);
// Euler YZY (indices 1, 2, 1)
Vector3f euler = rotation.eulerAngles(1, 2, 1);
Transform.Orientation = euler / CLHEP::degree;
// Notify properties
PropertyBase* p;
if ((p = this->GetProperty("Transform.Position"))) p->Updated();
if ((p = this->GetProperty("Transform.Orientation"))) p->Updated();
if ((p = this->GetProperty("Transform.Scale"))) p->Updated();
}
signals:
/** Signal emitted when properties change */
virtual void Updated() override {
this->Sync();
ULIB_SIGNAL_EMIT(AffineTransform::Updated);
}
private:
/** Synchronizes m_T with properties */
void Sync() {
m_T = Eigen::Affine3f::Identity();
m_T.translate(Transform.Position);
// Orientation (using YZY order as implied by EulerYZYRotate)
Matrix3f mat;
mat = Eigen::AngleAxisf(Transform.Orientation.x() * CLHEP::degree, Vector3f::UnitY())
* Eigen::AngleAxisf(Transform.Orientation.y() * CLHEP::degree, Vector3f::UnitZ())
* Eigen::AngleAxisf(Transform.Orientation.z() * CLHEP::degree, Vector3f::UnitY());
m_T.rotate(mat);
m_T.scale(Transform.Scale);
}
};