Browse Source

SceneGraph: hide internal transformation implementation from public API.

Previously it was possible to access internal transformation
implementation from Transformation and thus also from Object, e.g.:

    typedef SceneGraph::Object<SceneGraph::MatrixTransformation2D> Object2D;

    Object2D o;
    o.fromMatrix(...); // What does this here and why it returns matrix?!

Now everything is hidden in Implementation namespace and all
traces of previous code are removed from documentation. It might now be
slightly harder for users to implement their own transformation
implementations, but it wasn't easy before either. The widely used ones
are already implemented, so it shouldn't be too much of a problem.
Similarly for potential backward compatibility issues, I assume nobody
needed to implement their own transformation yet.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
0f8d2f2e98
  1. 85
      src/SceneGraph/AbstractTransformation.h
  2. 71
      src/SceneGraph/DualComplexTransformation.h
  3. 75
      src/SceneGraph/DualQuaternionTransformation.h
  4. 45
      src/SceneGraph/MatrixTransformation2D.h
  5. 45
      src/SceneGraph/MatrixTransformation3D.h
  6. 4
      src/SceneGraph/Object.h
  7. 23
      src/SceneGraph/Object.hpp
  8. 77
      src/SceneGraph/RigidMatrixTransformation2D.h
  9. 77
      src/SceneGraph/RigidMatrixTransformation3D.h
  10. 8
      src/SceneGraph/Test/DualComplexTransformationTest.cpp
  11. 8
      src/SceneGraph/Test/DualQuaternionTransformationTest.cpp
  12. 8
      src/SceneGraph/Test/MatrixTransformation2DTest.cpp
  13. 8
      src/SceneGraph/Test/MatrixTransformation3DTest.cpp
  14. 12
      src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp
  15. 12
      src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp

85
src/SceneGraph/AbstractTransformation.h

@ -40,15 +40,7 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base for transformations
Provides transformation implementation for Object instances. See @ref scenegraph
for introduction.
@section AbstractTransformation-subclassing Subclassing
When subclassing, you have to:
- Implement all members listed in **Subclass implementation** group above
- Provide implicit (parameterless) constructor
Provides transformation implementation for @ref Object instances.
@see @ref scenegraph, @ref AbstractBasicTransformation2D,
@ref AbstractBasicTransformation3D, @ref AbstractTransformation2D,
@ -64,76 +56,6 @@ template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Abstrac
explicit AbstractTransformation();
#ifdef DOXYGEN_GENERATING_OUTPUT
/**
* @{ @name Subclass implementation
*
* These members must be defined by the implementation.
*/
/**
* @todo Common way to call setClean() on the object after setting
* transformation & disallowing transformation setting on scene,
* so the implementer doesn't forget to do it? It could also
* allow to hide Object::isScene() from unwanted publicity.
*/
/**
* @brief Transformation data type
*
* The type must satisfy the following requirements:
*
* - Default constructor must create identity transformation
*
* Defined in subclasses.
*/
typedef U DataType;
/**
* @brief Convert transformation to matrix
*
* Defined in subclasses.
*/
static typename DimensionTraits<dimensions, T>::MatrixType toMatrix(const DataType& transformation);
/**
* @brief Convert transformation from matrix
*
* Defined in subclasses.
*/
static DataType fromMatrix(const typename DimensionTraits<dimensions, T>::MatrixType& matrix);
/**
* @brief Compose transformations
*
* Defined in subclasses.
*/
static DataType compose(const DataType& parent, const DataType& child);
/**
* @brief Inverted transformation
*
* Defined in subclasses.
*/
static DataType inverted(const DataType& transformation);
/**
* @brief %Object transformation
*
* Relative to parent. Defined in subclasses.
*/
DataType transformation() const;
/**
* @brief Absolute transformation
*
* Relative to root object. Defined in subclasses.
*/
DataType absoluteTransformation() const;
/*@}*/
#endif
/**
* @brief Reset object transformation
* @return Reference to self (for method chaining)
@ -212,6 +134,11 @@ typedef AbstractBasicTransformation3D<Float> AbstractTransformation3D;
typedef AbstractTransformation<3, Float> AbstractTransformation3D;
#endif
namespace Implementation {
/* See DualQuaternionTransformation.h for example implementation */
template<class T> struct Transformation;
}
}}
#endif

71
src/SceneGraph/DualComplexTransformation.h

@ -46,40 +46,8 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
/** @brief Transformation type */
typedef Math::DualComplex<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::DualComplex<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return Math::DualComplex<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix3<T> toMatrix(const Math::DualComplex<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualComplex<T> compose(const Math::DualComplex<T>& parent, const Math::DualComplex<T>& child) {
return parent*child;
}
static Math::DualComplex<T> inverted(const Math::DualComplex<T>& transformation) {
return transformation.invertedNormalized();
}
Math::DualComplex<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualComplex::normalized()
*/
Object<BasicDualComplexTransformation<T>>& normalizeRotation() {
setTransformationInternal(_transformation.normalized());
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
}
/** @brief Object transformation */
Math::DualComplex<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -102,6 +70,19 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualComplex::normalized()
*/
Object<BasicDualComplexTransformation<T>>& normalizeRotation() {
setTransformationInternal(_transformation.normalized());
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
}
/**
* @brief Transform object
* @param transformation Transformation
@ -195,6 +176,28 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
*/
typedef BasicDualComplexTransformation<Float> DualComplexTransformation;
namespace Implementation {
template<class T> struct Transformation<BasicDualComplexTransformation<T>> {
static Math::DualComplex<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return Math::DualComplex<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix3<T> toMatrix(const Math::DualComplex<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualComplex<T> compose(const Math::DualComplex<T>& parent, const Math::DualComplex<T>& child) {
return parent*child;
}
static Math::DualComplex<T> inverted(const Math::DualComplex<T>& transformation) {
return transformation.invertedNormalized();
}
};
}
}}
#endif

75
src/SceneGraph/DualQuaternionTransformation.h

@ -46,42 +46,8 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
/** @brief Underlying transformation type */
typedef Math::DualQuaternion<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::DualQuaternion<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::DualQuaternionTransformation::fromMatrix(): the matrix doesn't represent rigid transformation", {});
return Math::DualQuaternion<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix4<T> toMatrix(const Math::DualQuaternion<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualQuaternion<T> compose(const Math::DualQuaternion<T>& parent, const Math::DualQuaternion<T>& child) {
return parent*child;
}
static Math::DualQuaternion<T> inverted(const Math::DualQuaternion<T>& transformation) {
return transformation.invertedNormalized();
}
Math::DualQuaternion<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualQuaternion::normalized()
*/
Object<BasicDualQuaternionTransformation<T>>& normalizeRotation() {
setTransformation(_transformation.normalized());
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
}
/** @brief Object transformation */
Math::DualQuaternion<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -104,6 +70,19 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualQuaternion::normalized()
*/
Object<BasicDualQuaternionTransformation<T>>& normalizeRotation() {
setTransformation(_transformation.normalized());
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
}
/**
* @brief Multiply transformation
* @param transformation Transformation
@ -201,6 +180,30 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
*/
typedef BasicDualQuaternionTransformation<Float> DualQuaternionTransformation;
namespace Implementation {
template<class T> struct Transformation<BasicDualQuaternionTransformation<T>> {
static Math::DualQuaternion<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::DualQuaternionTransformation: the matrix doesn't represent rigid transformation", {});
return Math::DualQuaternion<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix4<T> toMatrix(const Math::DualQuaternion<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualQuaternion<T> compose(const Math::DualQuaternion<T>& parent, const Math::DualQuaternion<T>& child) {
return parent*child;
}
static Math::DualQuaternion<T> inverted(const Math::DualQuaternion<T>& transformation) {
return transformation.invertedNormalized();
}
};
}
}}
#endif

45
src/SceneGraph/MatrixTransformation2D.h

@ -45,27 +45,8 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
/** @brief Underlying transformation type */
typedef Math::Matrix3<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
constexpr static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.inverted();
}
Math::Matrix3<T> transformation() const {
return _transformation;
}
#endif
/** @brief Object transformation */
Math::Matrix3<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -182,6 +163,28 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
*/
typedef BasicMatrixTransformation2D<Float> MatrixTransformation2D;
namespace Implementation {
template<class T> struct Transformation<BasicMatrixTransformation2D<T>> {
constexpr static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.inverted();
}
};
}
}}
#endif

45
src/SceneGraph/MatrixTransformation3D.h

@ -45,27 +45,8 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
/** @brief Underlying transformation type */
typedef Math::Matrix4<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
constexpr static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.inverted();
}
Math::Matrix4<T> transformation() const {
return _transformation;
}
#endif
/** @brief Object transformation */
Math::Matrix4<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -222,6 +203,28 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
*/
typedef BasicMatrixTransformation3D<Float> MatrixTransformation3D;
namespace Implementation {
template<class T> struct Transformation<BasicMatrixTransformation3D<T>> {
constexpr static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.inverted();
}
};
}
}}
#endif

4
src/SceneGraph/Object.h

@ -215,7 +215,7 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* @see transformation()
*/
MatrixType transformationMatrix() const {
return Transformation::toMatrix(Transformation::transformation());
return Implementation::Transformation<Transformation>::toMatrix(Transformation::transformation());
}
/**
@ -224,7 +224,7 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* @see absoluteTransformation()
*/
MatrixType absoluteTransformationMatrix() const {
return Transformation::toMatrix(absoluteTransformation());
return Implementation::Transformation<Transformation>::toMatrix(absoluteTransformation());
}
/**

23
src/SceneGraph/Object.hpp

@ -91,8 +91,8 @@ template<class Transformation> Object<Transformation>& Object<Transformation>::s
template<class Transformation> Object<Transformation>& Object<Transformation>::setParentKeepTransformation(Object<Transformation>* parent) {
CORRADE_ASSERT(scene() == parent->scene(), "SceneGraph::Object::setParentKeepTransformation(): both parents must be in the same scene", *this);
const auto transformation = Transformation::compose(
Transformation::inverted(parent->absoluteTransformation()), absoluteTransformation());
const auto transformation = Implementation::Transformation<Transformation>::compose(
Implementation::Transformation<Transformation>::inverted(parent->absoluteTransformation()), absoluteTransformation());
setParent(parent);
Transformation::setTransformation(transformation);
@ -101,7 +101,7 @@ template<class Transformation> Object<Transformation>& Object<Transformation>::s
template<class Transformation> typename Transformation::DataType Object<Transformation>::absoluteTransformation() const {
if(!parent()) return Transformation::transformation();
return Transformation::compose(parent()->absoluteTransformation(), Transformation::transformation());
return Implementation::Transformation<Transformation>::compose(parent()->absoluteTransformation(), Transformation::transformation());
}
template<class Transformation> void Object<Transformation>::setDirty() {
@ -153,7 +153,7 @@ template<class Transformation> void Object<Transformation>::setClean() {
objects.pop();
/* Compose transformation and clean object */
absoluteTransformation = Transformation::compose(absoluteTransformation, o->transformation());
absoluteTransformation = Implementation::Transformation<Transformation>::compose(absoluteTransformation, o->transformation());
CORRADE_INTERNAL_ASSERT(o->isDirty());
o->setClean(absoluteTransformation);
CORRADE_ASSERT(!o->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", );
@ -171,10 +171,10 @@ template<class Transformation> auto Object<Transformation>::doTransformationMatr
}
template<class Transformation> auto Object<Transformation>::transformationMatrices(const std::vector<Object<Transformation>*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector<MatrixType> {
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Transformation::fromMatrix(initialTransformationMatrix));
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Implementation::Transformation<Transformation>::fromMatrix(initialTransformationMatrix));
std::vector<MatrixType> transformationMatrices(transformations.size());
for(std::size_t i = 0; i != objects.size(); ++i)
transformationMatrices[i] = Transformation::toMatrix(transformations[i]);
transformationMatrices[i] = Implementation::Transformation<Transformation>::toMatrix(transformations[i]);
return transformationMatrices;
}
@ -310,16 +310,16 @@ template<class Transformation> typename Transformation::DataType Object<Transfor
if(!parent) {
CORRADE_INTERNAL_ASSERT(o->isScene());
return (jointTransformations[joint] =
Transformation::compose(initialTransformation, jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(initialTransformation, jointTransformations[joint]));
/* Joint object, compose transformation with the joint, done */
} else if(parent->flags & Flag::Joint) {
return (jointTransformations[joint] =
Transformation::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, initialTransformation), jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, initialTransformation), jointTransformations[joint]));
/* Else compose transformation with parent, go up the hierarchy */
} else {
jointTransformations[joint] = Transformation::compose(parent->transformation(), jointTransformations[joint]);
jointTransformations[joint] = Implementation::Transformation<Transformation>::compose(parent->transformation(), jointTransformations[joint]);
o = parent;
}
}
@ -385,7 +385,7 @@ template<class Transformation> void Object<Transformation>::setClean(const typen
if(i->cachedTransformations() & CachedTransformation::Absolute) {
if(!(cached & CachedTransformation::Absolute)) {
cached |= CachedTransformation::Absolute;
matrix = Transformation::toMatrix(absoluteTransformation);
matrix = Implementation::Transformation<Transformation>::toMatrix(absoluteTransformation);
}
i->clean(matrix);
@ -396,7 +396,8 @@ template<class Transformation> void Object<Transformation>::setClean(const typen
if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) {
if(!(cached & CachedTransformation::InvertedAbsolute)) {
cached |= CachedTransformation::InvertedAbsolute;
invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation));
invertedMatrix = Implementation::Transformation<Transformation>::toMatrix(
Implementation::Transformation<Transformation>::inverted(absoluteTransformation));
}
i->cleanInverted(invertedMatrix);

77
src/SceneGraph/RigidMatrixTransformation2D.h

@ -49,43 +49,8 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
/** @brief Underlying transformation type */
typedef Math::Matrix3<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D::fromMatrix(): the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.invertedRigid();
}
Math::Matrix3<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation2D<T>>& normalizeRotation() {
setTransformationInternal(Math::Matrix3<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
}
/** @brief Object transformation */
Math::Matrix3<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -108,6 +73,20 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation2D<T>>& normalizeRotation() {
setTransformationInternal(Math::Matrix3<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
}
/**
* @brief Transform object
* @param transformation Transformation
@ -215,6 +194,30 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
*/
typedef BasicRigidMatrixTransformation2D<Float> RigidMatrixTransformation2D;
namespace Implementation {
template<class T> struct Transformation<BasicRigidMatrixTransformation2D<T>> {
static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D: the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.invertedRigid();
}
};
}
}}
#endif

77
src/SceneGraph/RigidMatrixTransformation3D.h

@ -49,43 +49,8 @@ template<class T> class BasicRigidMatrixTransformation3D: public AbstractBasicTr
/** @brief Underlying transformation type */
typedef Math::Matrix4<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation3D::fromMatrix(): the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.invertedRigid();
}
Math::Matrix4<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation3D<T>>& normalizeRotation() {
setTransformation(Math::Matrix4<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
return static_cast<Object<BasicRigidMatrixTransformation3D<T>>&>(*this);
}
/** @brief Object transformation */
Math::Matrix4<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -108,6 +73,20 @@ template<class T> class BasicRigidMatrixTransformation3D: public AbstractBasicTr
return static_cast<Object<BasicRigidMatrixTransformation3D<T>>&>(*this);
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation3D<T>>& normalizeRotation() {
setTransformation(Math::Matrix4<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
return static_cast<Object<BasicRigidMatrixTransformation3D<T>>&>(*this);
}
/**
* @brief Multiply transformation
* @param transformation Transformation
@ -260,6 +239,30 @@ template<class T> class BasicRigidMatrixTransformation3D: public AbstractBasicTr
*/
typedef BasicRigidMatrixTransformation3D<Float> RigidMatrixTransformation3D;
namespace Implementation {
template<class T> struct Transformation<BasicRigidMatrixTransformation3D<T>> {
static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation3D: the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.invertedRigid();
}
};
}
}}
#endif

8
src/SceneGraph/Test/DualComplexTransformationTest.cpp

@ -67,24 +67,24 @@ DualComplexTransformationTest::DualComplexTransformationTest() {
void DualComplexTransformationTest::fromMatrix() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f});
CORRADE_COMPARE(DualComplexTransformation::fromMatrix(m), c);
CORRADE_COMPARE(Implementation::Transformation<DualComplexTransformation>::fromMatrix(m), c);
}
void DualComplexTransformationTest::toMatrix() {
DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f});
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(DualComplexTransformation::toMatrix(c), m);
CORRADE_COMPARE(Implementation::Transformation<DualComplexTransformation>::toMatrix(c), m);
}
void DualComplexTransformationTest::compose() {
DualComplex parent = DualComplex::rotation(Deg(17.0f));
DualComplex child = DualComplex::translation({1.0f, -0.3f});
CORRADE_COMPARE(DualComplexTransformation::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<DualComplexTransformation>::compose(parent, child), parent*child);
}
void DualComplexTransformationTest::inverted() {
DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f});
CORRADE_COMPARE(DualComplexTransformation::inverted(c)*c, DualComplex());
CORRADE_COMPARE(Implementation::Transformation<DualComplexTransformation>::inverted(c)*c, DualComplex());
}
void DualComplexTransformationTest::setTransformation() {

8
src/SceneGraph/Test/DualQuaternionTransformationTest.cpp

@ -67,24 +67,24 @@ DualQuaternionTransformationTest::DualQuaternionTransformationTest() {
void DualQuaternionTransformationTest::fromMatrix() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f});
DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(DualQuaternionTransformation::fromMatrix(m), q);
CORRADE_COMPARE(Implementation::Transformation<DualQuaternionTransformation>::fromMatrix(m), q);
}
void DualQuaternionTransformationTest::toMatrix() {
DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f});
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(DualQuaternionTransformation::toMatrix(q), m);
CORRADE_COMPARE(Implementation::Transformation<DualQuaternionTransformation>::toMatrix(q), m);
}
void DualQuaternionTransformationTest::compose() {
DualQuaternion parent = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis());
DualQuaternion child = DualQuaternion::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(DualQuaternionTransformation::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<DualQuaternionTransformation>::compose(parent, child), parent*child);
}
void DualQuaternionTransformationTest::inverted() {
DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(DualQuaternionTransformation::inverted(q)*q, DualQuaternion());
CORRADE_COMPARE(Implementation::Transformation<DualQuaternionTransformation>::inverted(q)*q, DualQuaternion());
}
void DualQuaternionTransformationTest::setTransformation() {

8
src/SceneGraph/Test/MatrixTransformation2DTest.cpp

@ -67,23 +67,23 @@ MatrixTransformation2DTest::MatrixTransformation2DTest() {
void MatrixTransformation2DTest::fromMatrix() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(MatrixTransformation2D::fromMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation2D>::fromMatrix(m), m);
}
void MatrixTransformation2DTest::toMatrix() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(MatrixTransformation2D::toMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation2D>::toMatrix(m), m);
}
void MatrixTransformation2DTest::compose() {
Matrix3 parent = Matrix3::rotation(Deg(17.0f));
Matrix3 child = Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(MatrixTransformation2D::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation2D>::compose(parent, child), parent*child);
}
void MatrixTransformation2DTest::inverted() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(MatrixTransformation2D::inverted(m)*m, Matrix3());
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation2D>::inverted(m)*m, Matrix3());
}
void MatrixTransformation2DTest::setTransformation() {

8
src/SceneGraph/Test/MatrixTransformation3DTest.cpp

@ -67,23 +67,23 @@ MatrixTransformation3DTest::MatrixTransformation3DTest() {
void MatrixTransformation3DTest::fromMatrix() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f});
CORRADE_COMPARE(MatrixTransformation3D::fromMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation3D>::fromMatrix(m), m);
}
void MatrixTransformation3DTest::toMatrix() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f});
CORRADE_COMPARE(MatrixTransformation3D::toMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation3D>::toMatrix(m), m);
}
void MatrixTransformation3DTest::compose() {
Matrix4 parent = Matrix4::rotationX(Deg(17.0f));
Matrix4 child = Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(MatrixTransformation3D::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation3D>::compose(parent, child), parent*child);
}
void MatrixTransformation3DTest::inverted() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f});
CORRADE_COMPARE(MatrixTransformation3D::inverted(m)*m, Matrix4());
CORRADE_COMPARE(Implementation::Transformation<MatrixTransformation3D>::inverted(m)*m, Matrix4());
}
void MatrixTransformation3DTest::setTransformation() {

12
src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp

@ -69,27 +69,27 @@ RigidMatrixTransformation2DTest::RigidMatrixTransformation2DTest() {
void RigidMatrixTransformation2DTest::fromMatrix() {
std::ostringstream o;
Error::setOutput(&o);
RigidMatrixTransformation2D::fromMatrix(Matrix3::scaling(Vector2(4.0f)));
CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation2D::fromMatrix(): the matrix doesn't represent rigid transformation\n");
Implementation::Transformation<RigidMatrixTransformation2D>::fromMatrix(Matrix3::scaling(Vector2(4.0f)));
CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation2D: the matrix doesn't represent rigid transformation\n");
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(RigidMatrixTransformation2D::fromMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation2D>::fromMatrix(m), m);
}
void RigidMatrixTransformation2DTest::toMatrix() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(RigidMatrixTransformation2D::toMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation2D>::toMatrix(m), m);
}
void RigidMatrixTransformation2DTest::compose() {
Matrix3 parent = Matrix3::rotation(Deg(17.0f));
Matrix3 child = Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(RigidMatrixTransformation2D::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation2D>::compose(parent, child), parent*child);
}
void RigidMatrixTransformation2DTest::inverted() {
Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f});
CORRADE_COMPARE(RigidMatrixTransformation2D::inverted(m)*m, Matrix3());
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation2D>::inverted(m)*m, Matrix3());
}
void RigidMatrixTransformation2DTest::setTransformation() {

12
src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp

@ -69,27 +69,27 @@ RigidMatrixTransformation3DTest::RigidMatrixTransformation3DTest() {
void RigidMatrixTransformation3DTest::fromMatrix() {
std::ostringstream o;
Error::setOutput(&o);
RigidMatrixTransformation3D::fromMatrix(Matrix4::scaling(Vector3(4.0f)));
CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation3D::fromMatrix(): the matrix doesn't represent rigid transformation\n");
Implementation::Transformation<RigidMatrixTransformation3D>::fromMatrix(Matrix4::scaling(Vector3(4.0f)));
CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation3D: the matrix doesn't represent rigid transformation\n");
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(RigidMatrixTransformation3D::fromMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation3D>::fromMatrix(m), m);
}
void RigidMatrixTransformation3DTest::toMatrix() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(RigidMatrixTransformation3D::toMatrix(m), m);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation3D>::toMatrix(m), m);
}
void RigidMatrixTransformation3DTest::compose() {
Matrix4 parent = Matrix4::rotationX(Deg(17.0f));
Matrix4 child = Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(RigidMatrixTransformation3D::compose(parent, child), parent*child);
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation3D>::compose(parent, child), parent*child);
}
void RigidMatrixTransformation3DTest::inverted() {
Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f});
CORRADE_COMPARE(RigidMatrixTransformation3D::inverted(m)*m, Matrix4());
CORRADE_COMPARE(Implementation::Transformation<RigidMatrixTransformation3D>::inverted(m)*m, Matrix4());
}
void RigidMatrixTransformation3DTest::setTransformation() {

Loading…
Cancel
Save