Browse Source

Trade: support separate translation/rotation/scaling in ObjectData.

Doesn't make any backwards-incompatible change -- plugins can still
export the transformation as matrix and users can still access the
combined one even if separate transformations are used. Yay!
pull/191/head
Vladimír Vondruš 8 years ago
parent
commit
10b4c069eb
  1. 7
      doc/changelog.dox
  2. 24
      doc/snippets/MagnumTrade.cpp
  3. 6
      src/Magnum/Trade/CMakeLists.txt
  4. 2
      src/Magnum/Trade/MeshObjectData2D.cpp
  5. 16
      src/Magnum/Trade/MeshObjectData2D.h
  6. 2
      src/Magnum/Trade/MeshObjectData3D.cpp
  7. 16
      src/Magnum/Trade/MeshObjectData3D.h
  8. 53
      src/Magnum/Trade/ObjectData2D.cpp
  9. 130
      src/Magnum/Trade/ObjectData2D.h
  10. 53
      src/Magnum/Trade/ObjectData3D.cpp
  11. 130
      src/Magnum/Trade/ObjectData3D.h
  12. 4
      src/Magnum/Trade/Test/CMakeLists.txt
  13. 121
      src/Magnum/Trade/Test/ObjectData2DTest.cpp
  14. 122
      src/Magnum/Trade/Test/ObjectData3DTest.cpp

7
doc/changelog.dox

@ -68,6 +68,13 @@ See also:
@ref Platform::AndroidApplication. This also makes the default framebuffer
parameters consistent across the implementations.
@subsubsection changelog-latest-new-trade Trade library
- @ref Trade::ObjectData2D and @ref Trade::ObjectData3D now support also
separate translation / rotation / scaling specification instead of a
combined transformation matrix. See @ref Trade::ObjectData2D::transformation()
and @ref Trade::ObjectData3D::transformation() for more information.
@subsection changelog-latest-changes Changes and improvements
@subsubsection changelog-latest-changes-audio Audio library

24
doc/snippets/MagnumTrade.cpp

@ -26,6 +26,8 @@
#include "Magnum/PixelFormat.h"
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/ImageData.h"
#include "Magnum/Trade/ObjectData2D.h"
#include "Magnum/Trade/ObjectData3D.h"
#ifdef MAGNUM_TARGET_GL
#include "Magnum/GL/Texture.h"
#endif
@ -67,4 +69,26 @@ else
}
#endif
{
Trade::ObjectData2D& foo();
Trade::ObjectData2D& data = foo();
/* [ObjectData2D-transformation] */
Matrix3 transformation =
Matrix3::from(data.rotation().toMatrix(), data.translation())*
Matrix3::scaling(data.scaling());
/* [ObjectData2D-transformation] */
static_cast<void>(transformation);
}
{
Trade::ObjectData3D& bar();
Trade::ObjectData3D& data = bar();
/* [ObjectData3D-transformation] */
Matrix4 transformation =
Matrix4::from(data.rotation().toMatrix(), data.translation())*
Matrix4::scaling(data.scaling());
/* [ObjectData3D-transformation] */
static_cast<void>(transformation);
}
}

6
src/Magnum/Trade/CMakeLists.txt

@ -34,14 +34,14 @@ set(MagnumTrade_SRCS
MeshData3D.cpp
MeshObjectData2D.cpp
MeshObjectData3D.cpp
ObjectData2D.cpp
ObjectData3D.cpp
PhongMaterialData.cpp
SceneData.cpp
TextureData.cpp)
set(MagnumTrade_GracefulAssert_SRCS
ImageData.cpp)
ImageData.cpp
ObjectData2D.cpp
ObjectData3D.cpp)
set(MagnumTrade_HEADERS
AbstractImporter.h

2
src/Magnum/Trade/MeshObjectData2D.cpp

@ -29,4 +29,6 @@ namespace Magnum { namespace Trade {
MeshObjectData2D::MeshObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const UnsignedInt instance, const Int material, const void* const importerState): ObjectData2D{std::move(children), transformation, ObjectInstanceType2D::Mesh, instance, importerState}, _material{material} {}
MeshObjectData2D::MeshObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, const UnsignedInt instance, const Int material, const void* const importerState): ObjectData2D{std::move(children), translation, rotation, scaling, ObjectInstanceType2D::Mesh, instance, importerState}, _material{material} {}
}}

16
src/Magnum/Trade/MeshObjectData2D.h

@ -42,7 +42,7 @@ Provides access to material information for given mesh instance.
class MAGNUM_TRADE_EXPORT MeshObjectData2D: public ObjectData2D {
public:
/**
* @brief Constructor
* @brief Construct with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param instance Instance ID
@ -53,6 +53,20 @@ class MAGNUM_TRADE_EXPORT MeshObjectData2D: public ObjectData2D {
*/
explicit MeshObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, UnsignedInt instance, Int material, const void* importerState = nullptr);
/**
* @brief Construct with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param instance Instance ID
* @param material Material ID or `-1`
* @param importerState Importer-specific state
*
* Creates object with mesh instance type.
*/
explicit MeshObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, UnsignedInt instance, Int material, const void* importerState = nullptr);
/** @brief Copying is not allowed */
MeshObjectData2D(const MeshObjectData2D&) = delete;

2
src/Magnum/Trade/MeshObjectData3D.cpp

@ -29,4 +29,6 @@ namespace Magnum { namespace Trade {
MeshObjectData3D::MeshObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const UnsignedInt instance, const Int material, const void* const importerState): ObjectData3D{std::move(children), transformation, ObjectInstanceType3D::Mesh, instance, importerState}, _material{material} {}
MeshObjectData3D::MeshObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, const UnsignedInt instance, const Int material, const void* const importerState): ObjectData3D{std::move(children), translation, rotation, scaling, ObjectInstanceType3D::Mesh, instance, importerState}, _material{material} {}
}}

16
src/Magnum/Trade/MeshObjectData3D.h

@ -42,7 +42,7 @@ Provides access to material information for given mesh instance.
class MAGNUM_TRADE_EXPORT MeshObjectData3D: public ObjectData3D {
public:
/**
* @brief Constructor
* @brief Construct with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param instance Instance ID
@ -53,6 +53,20 @@ class MAGNUM_TRADE_EXPORT MeshObjectData3D: public ObjectData3D {
*/
explicit MeshObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, UnsignedInt instance, Int material, const void* importerState = nullptr);
/**
* @brief Construct with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param instance Instance ID
* @param material Material ID or `-1`
* @param importerState Importer-specific state
*
* Creates object with mesh instance type.
*/
explicit MeshObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, UnsignedInt instance, Int material, const void* importerState = nullptr);
/** @brief Copying is not allowed */
MeshObjectData3D(const MeshObjectData3D&) = delete;

53
src/Magnum/Trade/ObjectData2D.cpp

@ -25,11 +25,17 @@
#include "ObjectData2D.h"
#include <Corrade/Containers/EnumSet.hpp>
namespace Magnum { namespace Trade {
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const ObjectInstanceType2D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{instanceType}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const ObjectInstanceType2D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{instanceType}, _flags{}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, const ObjectInstanceType2D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{translation, rotation, scaling}, _instanceType{instanceType}, _flags{ObjectFlag2D::HasTransformationRotationScaling}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType2D::Empty}, _flags{}, _instance{-1}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType2D::Empty}, _instance{-1}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, const void* const importerState): _children{std::move(children)}, _transformation{translation, rotation, scaling}, _instanceType{ObjectInstanceType2D::Empty}, _flags{ObjectFlag2D::HasTransformationRotationScaling}, _instance{-1}, _importerState{importerState} {}
ObjectData2D::ObjectData2D(ObjectData2D&&)
#if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409
@ -45,6 +51,32 @@ ObjectData2D& ObjectData2D::operator=(ObjectData2D&&)
#endif
= default;
Vector2 ObjectData2D::translation() const {
CORRADE_ASSERT(_flags & ObjectFlag2D::HasTransformationRotationScaling,
"Trade::ObjectData2D::translation(): object has only a combined transformation", {});
return _transformation.trs.translation;
}
Complex ObjectData2D::rotation() const {
CORRADE_ASSERT(_flags & ObjectFlag2D::HasTransformationRotationScaling,
"Trade::ObjectData2D::rotation(): object has only a combined transformation", {});
return _transformation.trs.rotation;
}
Vector2 ObjectData2D::scaling() const {
CORRADE_ASSERT(_flags & ObjectFlag2D::HasTransformationRotationScaling,
"Trade::ObjectData2D::scaling(): object has only a combined transformation", {});
return _transformation.trs.scaling;
}
Matrix3 ObjectData2D::transformation() const {
if(_flags & ObjectFlag2D::HasTransformationRotationScaling)
return Matrix3::from(_transformation.trs.rotation.toMatrix(),
_transformation.trs.translation)*
Matrix3::scaling(_transformation.trs.scaling);
return _transformation.matrix;
}
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, ObjectInstanceType2D value) {
switch(value) {
@ -59,6 +91,23 @@ Debug& operator<<(Debug& debug, ObjectInstanceType2D value) {
return debug << "Trade::ObjectInstanceType2D(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, ObjectFlag2D value) {
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case ObjectFlag2D::value: return debug << "Trade::ObjectFlag2D::" #value;
_c(HasTransformationRotationScaling)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "Trade::ObjectFlag2D(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, ObjectFlags2D value) {
return enumSetDebugOutput(debug, value, "Trade::ObjectFlags2D{}", {
ObjectFlag2D::HasTransformationRotationScaling});
}
#endif
}}

130
src/Magnum/Trade/ObjectData2D.h

@ -33,6 +33,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Complex.h"
#include "Magnum/Trade/visibility.h"
namespace Magnum { namespace Trade {
@ -54,6 +55,31 @@ enum class ObjectInstanceType2D: UnsignedByte {
Empty /**< Empty */
};
/**
@brief 2D object flag
@see @ref ObjectFlags2D, @ref ObjectData2D::flags()
*/
enum class ObjectFlag2D: UnsignedByte {
/**
* The object provides separate translation / rotation / scaling
* properties. The @ref ObjectData2D::transformation() matrix returns them
* combined, but it's possible to access particular parts of the
* transformation using @ref ObjectData2D::translation(),
* @ref ObjectData2D::rotation() and @ref ObjectData2D::scaling().
*/
HasTransformationRotationScaling = 1 << 0
};
/**
@brief 2D object flags
@see @ref ObjectData2D::flags()
*/
typedef Containers::EnumSet<ObjectFlag2D> ObjectFlags2D;
CORRADE_ENUMSET_OPERATORS(ObjectFlags2D)
/**
@brief Two-dimensional object data
@ -63,7 +89,7 @@ Provides access to object transformation and hierarchy.
class MAGNUM_TRADE_EXPORT ObjectData2D {
public:
/**
* @brief Constructor
* @brief Construct with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param instanceType Instance type
@ -73,13 +99,35 @@ class MAGNUM_TRADE_EXPORT ObjectData2D {
explicit ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, ObjectInstanceType2D instanceType, UnsignedInt instance, const void* importerState = nullptr);
/**
* @brief Constructor for empty instance
* @brief Construct with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param instanceType Instance type
* @param instance Instance ID
* @param importerState Importer-specific state
*/
explicit ObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, ObjectInstanceType2D instanceType, UnsignedInt instance, const void* importerState = nullptr);
/**
* @brief Construct empty instance with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param importerState Importer-specific state
*/
explicit ObjectData2D(std::vector<UnsignedInt> children, const Matrix3& transformation, const void* importerState = nullptr);
/**
* @brief Construct empty instance with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param importerState Importer-specific state
*/
explicit ObjectData2D(std::vector<UnsignedInt> children, const Vector2& translation, const Complex& rotation, const Vector2& scaling, const void* importerState = nullptr);
/** @brief Copying is not allowed */
ObjectData2D(const ObjectData2D&) = delete;
@ -113,8 +161,62 @@ class MAGNUM_TRADE_EXPORT ObjectData2D {
std::vector<UnsignedInt>& children() { return _children; }
const std::vector<UnsignedInt>& children() const { return _children; } /**< @overload */
/** @brief Transformation (relative to parent) */
Matrix3 transformation() const { return _transformation; }
/** @brief Flags */
ObjectFlags2D flags() const { return _flags; }
/**
* @brief Translation (relative to parent)
*
* Available only if @ref ObjectFlag2D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied as last in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref rotation(), @ref scaling()
*/
Vector2 translation() const;
/**
* @brief Rotation (relative to parent)
*
* Available only if @ref ObjectFlag2D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied second in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref translation(), @ref scaling()
*/
Complex rotation() const;
/**
* @brief Scaling (relative to parent)
*
* Available only if @ref ObjectFlag2D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied as first in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref translation(), @ref rotation()
*/
Vector2 scaling() const;
/**
* @brief Transformation (relative to parent)
*
* If @ref ObjectFlag2D::HasTransformationRotationScaling is not set,
* returns the imported object transformation matrix. Otherwise
* calculates the final transformation matrix @f$ \boldsymbol{M} @f$
* from translation, rotation and scaling matrices @f$ \boldsymbol{T} @f$,
* @f$ \boldsymbol{R} @f$, @f$ \boldsymbol{S} @f$ created from
* @ref translation(), @ref rotation() and @ref scaling() in the
* following order: @f[
* \boldsymbol{M} = \boldsymbol{T} \boldsymbol{R} \boldsymbol{S}
* @f]
*
* The corresponding code is as follows:
*
* @snippet MagnumTrade.cpp ObjectData2D-transformation
*
* @see @ref flags()
*/
Matrix3 transformation() const;
/**
* @brief Instance type
@ -141,8 +243,20 @@ class MAGNUM_TRADE_EXPORT ObjectData2D {
private:
std::vector<UnsignedInt> _children;
Matrix3 _transformation;
union Transformation {
Transformation(const Matrix3& matrix): matrix{matrix} {}
Transformation(const Vector2& translation, const Complex& rotation, const Vector2& scaling): trs{translation, rotation, scaling} {}
~Transformation() {}
Matrix3 matrix;
struct {
Vector2 translation;
Complex rotation;
Vector2 scaling;
} trs;
} _transformation;
ObjectInstanceType2D _instanceType;
ObjectFlags2D _flags;
Int _instance;
const void* _importerState;
};
@ -150,6 +264,12 @@ class MAGNUM_TRADE_EXPORT ObjectData2D {
/** @debugoperatorenum{ObjectInstanceType2D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectInstanceType2D value);
/** @debugoperatorenum{ObjectFlag2D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectFlag2D value);
/** @debugoperatorenum{ObjectFlags2D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectFlags2D value);
}}
#endif

53
src/Magnum/Trade/ObjectData3D.cpp

@ -25,11 +25,17 @@
#include "ObjectData3D.h"
#include <Corrade/Containers/EnumSet.hpp>
namespace Magnum { namespace Trade {
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const ObjectInstanceType3D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{instanceType}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const ObjectInstanceType3D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{instanceType}, _flags{}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, const ObjectInstanceType3D instanceType, const UnsignedInt instance, const void* const importerState): _children{std::move(children)}, _transformation{translation, rotation, scaling}, _instanceType{instanceType}, _flags{ObjectFlag3D::HasTransformationRotationScaling}, _instance{Int(instance)}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType3D::Empty}, _flags{}, _instance{-1}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const void* const importerState): _children{std::move(children)}, _transformation{transformation}, _instanceType{ObjectInstanceType3D::Empty}, _instance{-1}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, const void* const importerState): _children{std::move(children)}, _transformation{translation, rotation, scaling}, _instanceType{ObjectInstanceType3D::Empty}, _flags{ObjectFlag3D::HasTransformationRotationScaling}, _instance{-1}, _importerState{importerState} {}
ObjectData3D::ObjectData3D(ObjectData3D&&)
#if !defined(__GNUC__) || __GNUC__*100 + __GNUC_MINOR__ != 409
@ -45,6 +51,32 @@ ObjectData3D& ObjectData3D::operator=(ObjectData3D&&)
#endif
= default;
Vector3 ObjectData3D::translation() const {
CORRADE_ASSERT(_flags & ObjectFlag3D::HasTransformationRotationScaling,
"Trade::ObjectData3D::translation(): object has only a combined transformation", {});
return _transformation.trs.translation;
}
Quaternion ObjectData3D::rotation() const {
CORRADE_ASSERT(_flags & ObjectFlag3D::HasTransformationRotationScaling,
"Trade::ObjectData3D::rotation(): object has only a combined transformation", {});
return _transformation.trs.rotation;
}
Vector3 ObjectData3D::scaling() const {
CORRADE_ASSERT(_flags & ObjectFlag3D::HasTransformationRotationScaling,
"Trade::ObjectData3D::scaling(): object has only a combined transformation", {});
return _transformation.trs.scaling;
}
Matrix4 ObjectData3D::transformation() const {
if(_flags & ObjectFlag3D::HasTransformationRotationScaling)
return Matrix4::from(_transformation.trs.rotation.toMatrix(),
_transformation.trs.translation)*
Matrix4::scaling(_transformation.trs.scaling);
return _transformation.matrix;
}
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, ObjectInstanceType3D value) {
switch(value) {
@ -60,6 +92,23 @@ Debug& operator<<(Debug& debug, ObjectInstanceType3D value) {
return debug << "Trade::ObjectInstanceType3D(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, ObjectFlag3D value) {
switch(value) {
/* LCOV_EXCL_START */
#define _c(value) case ObjectFlag3D::value: return debug << "Trade::ObjectFlag3D::" #value;
_c(HasTransformationRotationScaling)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "Trade::ObjectFlag3D(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, ObjectFlags3D value) {
return enumSetDebugOutput(debug, value, "Trade::ObjectFlags3D{}", {
ObjectFlag3D::HasTransformationRotationScaling});
}
#endif
}}

130
src/Magnum/Trade/ObjectData3D.h

@ -33,6 +33,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Math/Matrix4.h"
#include "Magnum/Math/Quaternion.h"
#include "Magnum/Trade/visibility.h"
namespace Magnum { namespace Trade {
@ -55,6 +56,31 @@ enum class ObjectInstanceType3D: UnsignedByte {
Empty /**< Empty */
};
/**
@brief 3D object flag
@see @ref ObjectFlags3D, @ref ObjectData3D::flags()
*/
enum class ObjectFlag3D: UnsignedByte {
/**
* The object provides separate translation / rotation / scaling
* properties. The @ref ObjectData3D::transformation() matrix returns them
* combined, but it's possible to access particular parts of the
* transformation using @ref ObjectData3D::translation(),
* @ref ObjectData3D::rotation() and @ref ObjectData3D::scaling().
*/
HasTransformationRotationScaling = 1 << 0
};
/**
@brief 3D object flags
@see @ref ObjectData3D::flags()
*/
typedef Containers::EnumSet<ObjectFlag3D> ObjectFlags3D;
CORRADE_ENUMSET_OPERATORS(ObjectFlags3D)
/**
@brief Three-dimensional object data
@ -64,7 +90,7 @@ Provides access to object transformation and hierarchy.
class MAGNUM_TRADE_EXPORT ObjectData3D {
public:
/**
* @brief Constructor
* @brief Construct with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param instanceType Instance type
@ -74,13 +100,35 @@ class MAGNUM_TRADE_EXPORT ObjectData3D {
explicit ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, ObjectInstanceType3D instanceType, UnsignedInt instance, const void* importerState = nullptr);
/**
* @brief Constructor for empty instance
* @brief Construct with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param instanceType Instance type
* @param instance Instance ID
* @param importerState Importer-specific state
*/
explicit ObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, ObjectInstanceType3D instanceType, UnsignedInt instance, const void* importerState = nullptr);
/**
* @brief Construct empty instance with combined transformation
* @param children Child objects
* @param transformation Transformation (relative to parent)
* @param importerState Importer-specific state
*/
explicit ObjectData3D(std::vector<UnsignedInt> children, const Matrix4& transformation, const void* importerState = nullptr);
/**
* @brief Construct empty instance with separate transformations
* @param children Child objects
* @param translation Translation (relative to parent)
* @param rotation Rotation (relative to parent)
* @param scaling Scaling (relative to parent)
* @param importerState Importer-specific state
*/
explicit ObjectData3D(std::vector<UnsignedInt> children, const Vector3& translation, const Quaternion& rotation, const Vector3& scaling, const void* importerState = nullptr);
/** @brief Copying is not allowed */
ObjectData3D(const ObjectData3D&) = delete;
@ -114,8 +162,62 @@ class MAGNUM_TRADE_EXPORT ObjectData3D {
std::vector<UnsignedInt>& children() { return _children; }
const std::vector<UnsignedInt>& children() const { return _children; } /**< @overload */
/** @brief Transformation (relative to parent) */
Matrix4 transformation() const { return _transformation; }
/** @brief Flags */
ObjectFlags3D flags() const { return _flags; }
/**
* @brief Translation (relative to parent)
*
* Available only if @ref ObjectFlag3D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied as last in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref rotation(), @ref scaling()
*/
Vector3 translation() const;
/**
* @brief Rotation (relative to parent)
*
* Available only if @ref ObjectFlag3D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied second in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref translation(), @ref scaling()
*/
Quaternion rotation() const;
/**
* @brief Scaling (relative to parent)
*
* Available only if @ref ObjectFlag3D::HasTransformationRotationScaling
* is set, use @ref transformation() otherwise. Applied as first in the
* final transformation, see @ref transformation() for more
* information.
* @see @ref flags(), @ref translation(), @ref rotation()
*/
Vector3 scaling() const;
/**
* @brief Transformation (relative to parent)
*
* If @ref ObjectFlag3D::HasTransformationRotationScaling is not set,
* returns the imported object transformation matrix. Otherwise
* calculates the final transformation matrix @f$ \boldsymbol{M} @f$
* from translation, rotation and scaling matrices @f$ \boldsymbol{T} @f$,
* @f$ \boldsymbol{R} @f$, @f$ \boldsymbol{S} @f$ created from
* @ref translation(), @ref rotation() and @ref scaling() in the
* following order: @f[
* \boldsymbol{M} = \boldsymbol{T} \boldsymbol{R} \boldsymbol{S}
* @f]
*
* The corresponding code is as follows:
*
* @snippet MagnumTrade.cpp ObjectData3D-transformation
*
* @see @ref flags()
*/
Matrix4 transformation() const;
/**
* @brief Instance type
@ -140,8 +242,20 @@ class MAGNUM_TRADE_EXPORT ObjectData3D {
private:
std::vector<UnsignedInt> _children;
Matrix4 _transformation;
union Transformation {
Transformation(const Matrix4& matrix): matrix{matrix} {}
Transformation(const Vector3& translation, const Quaternion& rotation, const Vector3& scaling): trs{translation, rotation, scaling} {}
~Transformation() {}
Matrix4 matrix;
struct {
Vector3 translation;
Quaternion rotation;
Vector3 scaling;
} trs;
} _transformation;
ObjectInstanceType3D _instanceType;
ObjectFlags3D _flags;
Int _instance;
const void* _importerState;
};
@ -149,6 +263,12 @@ class MAGNUM_TRADE_EXPORT ObjectData3D {
/** @debugoperatorenum{ObjectInstanceType3D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectInstanceType3D value);
/** @debugoperatorenum{ObjectFlag3D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectFlag3D value);
/** @debugoperatorenum{ObjectFlags3D} */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, ObjectFlags3D value);
}}
#endif

4
src/Magnum/Trade/Test/CMakeLists.txt

@ -46,8 +46,8 @@ corrade_add_test(TradeLightDataTest LightDataTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeMaterialDataTest MaterialDataTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeMeshData2DTest MeshData2DTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeMeshData3DTest MeshData3DTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeObjectData2DTest ObjectData2DTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeObjectData3DTest ObjectData3DTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeObjectData2DTest ObjectData2DTest.cpp LIBRARIES MagnumTradeTestLib)
corrade_add_test(TradeObjectData3DTest ObjectData3DTest.cpp LIBRARIES MagnumTradeTestLib)
corrade_add_test(TradeSceneDataTest SceneDataTest.cpp LIBRARIES MagnumTrade)
corrade_add_test(TradeTextureDataTest TextureDataTest.cpp LIBRARIES MagnumTrade)

121
src/Magnum/Trade/Test/ObjectData2DTest.cpp

@ -35,50 +35,104 @@ class ObjectData2DTest: public TestSuite::Tester {
explicit ObjectData2DTest();
void constructEmpty();
void constructEmptyTransformations();
void constructMesh();
void constructMeshTransformations();
void constructCamera();
void constructCopy();
void constructMoveTransformations();
void constructMoveMesh();
void accessInvalidTransformations();
void debugType();
void debugFlag();
void debugFlags();
};
ObjectData2DTest::ObjectData2DTest() {
addTests({&ObjectData2DTest::constructEmpty,
&ObjectData2DTest::constructEmptyTransformations,
&ObjectData2DTest::constructMesh,
&ObjectData2DTest::constructMeshTransformations,
&ObjectData2DTest::constructCamera,
&ObjectData2DTest::constructCopy,
&ObjectData2DTest::constructMoveTransformations,
&ObjectData2DTest::constructMoveMesh,
&ObjectData2DTest::debugType});
&ObjectData2DTest::accessInvalidTransformations,
&ObjectData2DTest::debugType,
&ObjectData2DTest::debugFlag,
&ObjectData2DTest::debugFlags});
}
using namespace Math::Literals;
void ObjectData2DTest::constructEmpty() {
const int a{};
const ObjectData2D data{{0, 2, 3}, Matrix3::translation(Vector2::xAxis(-4.0f)), &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{0, 2, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags2D{});
CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::xAxis(-4.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Empty);
CORRADE_COMPARE(data.instance(), -1);
}
void ObjectData2DTest::constructEmptyTransformations() {
const int a{};
const ObjectData2D data{{0, 2, 3}, Vector2::xAxis(-4.0f), Complex::rotation(32.5_degf), Vector2::yScale(1.5f), &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{0, 2, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlag2D::HasTransformationRotationScaling);
CORRADE_COMPARE(data.translation(), Vector2::xAxis(-4.0f));
CORRADE_COMPARE(data.rotation(), Complex::rotation(32.5_degf));
CORRADE_COMPARE(data.scaling(), Vector2::yScale(1.5f));
CORRADE_COMPARE(data.transformation(),
Matrix3::translation(Vector2::xAxis(-4.0f))*
Matrix3::rotation(32.5_degf)*
Matrix3::scaling(Vector2::yScale(1.5f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Empty);
CORRADE_COMPARE(data.instance(), -1);
}
void ObjectData2DTest::constructMesh() {
const int a{};
const MeshObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), 13, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags2D{});
CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::yAxis(5.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Mesh);
CORRADE_COMPARE(data.instance(), 13);
CORRADE_COMPARE(data.material(), 42);
}
void ObjectData2DTest::constructMeshTransformations() {
const int a{};
const MeshObjectData2D data{{0, 2, 3}, Vector2::xAxis(-4.0f), Complex::rotation(32.5_degf), Vector2::yScale(1.5f), 13, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{0, 2, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlag2D::HasTransformationRotationScaling);
CORRADE_COMPARE(data.translation(), Vector2::xAxis(-4.0f));
CORRADE_COMPARE(data.rotation(), Complex::rotation(32.5_degf));
CORRADE_COMPARE(data.scaling(), Vector2::yScale(1.5f));
CORRADE_COMPARE(data.transformation(),
Matrix3::translation(Vector2::xAxis(-4.0f))*
Matrix3::rotation(32.5_degf)*
Matrix3::scaling(Vector2::yScale(1.5f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Mesh);
CORRADE_COMPARE(data.instance(), 13);
CORRADE_COMPARE(data.material(), 42);
}
void ObjectData2DTest::constructCamera() {
const int a{};
const ObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), ObjectInstanceType2D::Camera, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags2D{});
CORRADE_COMPARE(data.transformation(), Matrix3::translation(Vector2::yAxis(5.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType2D::Camera);
CORRADE_COMPARE(data.instance(), 42);
@ -91,6 +145,42 @@ void ObjectData2DTest::constructCopy() {
CORRADE_VERIFY(!(std::is_assignable<MeshObjectData2D, const MeshObjectData2D&>{}));
}
void ObjectData2DTest::constructMoveTransformations() {
const int a{};
ObjectData2D data{{1, 3}, Vector2::xAxis(-4.0f), Complex::rotation(32.5_degf), Vector2::yScale(1.5f), ObjectInstanceType2D::Camera, 13, &a};
ObjectData2D b{std::move(data)};
CORRADE_COMPARE(b.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(b.flags(), ObjectFlag2D::HasTransformationRotationScaling);
CORRADE_COMPARE(b.translation(), Vector2::xAxis(-4.0f));
CORRADE_COMPARE(b.rotation(), Complex::rotation(32.5_degf));
CORRADE_COMPARE(b.scaling(), Vector2::yScale(1.5f));
CORRADE_COMPARE(b.transformation(),
Matrix3::translation(Vector2::xAxis(-4.0f))*
Matrix3::rotation(32.5_degf)*
Matrix3::scaling(Vector2::yScale(1.5f)));
CORRADE_COMPARE(b.instanceType(), ObjectInstanceType2D::Camera);
CORRADE_COMPARE(b.instance(), 13);
const int c{};
ObjectData2D d{{0, 1}, Matrix3{}, ObjectInstanceType2D::Empty, 27, &c};
d = std::move(b);
CORRADE_COMPARE(d.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(d.flags(), ObjectFlag2D::HasTransformationRotationScaling);
CORRADE_COMPARE(d.translation(), Vector2::xAxis(-4.0f));
CORRADE_COMPARE(d.rotation(), Complex::rotation(32.5_degf));
CORRADE_COMPARE(d.scaling(), Vector2::yScale(1.5f));
CORRADE_COMPARE(d.transformation(),
Matrix3::translation(Vector2::xAxis(-4.0f))*
Matrix3::rotation(32.5_degf)*
Matrix3::scaling(Vector2::yScale(1.5f)));
CORRADE_COMPARE(d.instanceType(), ObjectInstanceType2D::Camera);
CORRADE_COMPARE(d.instance(), 13);
}
void ObjectData2DTest::constructMoveMesh() {
const int a{};
MeshObjectData2D data{{1, 3}, Matrix3::translation(Vector2::yAxis(5.0f)), 13, 42, &a};
@ -98,6 +188,7 @@ void ObjectData2DTest::constructMoveMesh() {
MeshObjectData2D b{std::move(data)};
CORRADE_COMPARE(b.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(b.flags(), ObjectFlags2D{});
CORRADE_COMPARE(b.transformation(), Matrix3::translation(Vector2::yAxis(5.0f)));
CORRADE_COMPARE(b.instanceType(), ObjectInstanceType2D::Mesh);
CORRADE_COMPARE(b.instance(), 13);
@ -109,18 +200,46 @@ void ObjectData2DTest::constructMoveMesh() {
d = std::move(b);
CORRADE_COMPARE(d.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(d.flags(), ObjectFlags2D{});
CORRADE_COMPARE(d.transformation(), Matrix3::translation(Vector2::yAxis(5.0f)));
CORRADE_COMPARE(d.instanceType(), ObjectInstanceType2D::Mesh);
CORRADE_COMPARE(d.instance(), 13);
CORRADE_COMPARE(d.material(), 42);
}
void ObjectData2DTest::accessInvalidTransformations() {
std::ostringstream out;
Error redirectOutput{&out};
const ObjectData2D data{{}, Matrix3{}};
data.translation();
data.rotation();
data.scaling();
CORRADE_COMPARE(out.str(),
"Trade::ObjectData2D::translation(): object has only a combined transformation\n"
"Trade::ObjectData2D::rotation(): object has only a combined transformation\n"
"Trade::ObjectData2D::scaling(): object has only a combined transformation\n");
}
void ObjectData2DTest::debugType() {
std::ostringstream o;
Debug(&o) << ObjectInstanceType2D::Empty << ObjectInstanceType2D(0xbe);
CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType2D::Empty Trade::ObjectInstanceType2D(0xbe)\n");
}
void ObjectData2DTest::debugFlag() {
std::ostringstream o;
Debug(&o) << ObjectFlag2D::HasTransformationRotationScaling << ObjectFlag2D(0xbe);
CORRADE_COMPARE(o.str(), "Trade::ObjectFlag2D::HasTransformationRotationScaling Trade::ObjectFlag2D(0xbe)\n");
}
void ObjectData2DTest::debugFlags() {
std::ostringstream o;
Debug(&o) << (ObjectFlag2D::HasTransformationRotationScaling|ObjectFlags2D{}) << ObjectFlags2D{};
CORRADE_COMPARE(o.str(), "Trade::ObjectFlag2D::HasTransformationRotationScaling Trade::ObjectFlags2D{}\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Trade::Test::ObjectData2DTest)

122
src/Magnum/Trade/Test/ObjectData3DTest.cpp

@ -35,52 +35,106 @@ class ObjectData3DTest: public TestSuite::Tester {
explicit ObjectData3DTest();
void constructEmpty();
void constructEmptyTransformations();
void constructMesh();
void constructMeshTransformations();
void constructCamera();
void constructLight();
void constructCopy();
void constructMoveTransformations();
void constructMoveMesh();
void accessInvalidTransformations();
void debugType();
void debugFlag();
void debugFlags();
};
ObjectData3DTest::ObjectData3DTest() {
addTests({&ObjectData3DTest::constructEmpty,
&ObjectData3DTest::constructEmptyTransformations,
&ObjectData3DTest::constructMesh,
&ObjectData3DTest::constructMeshTransformations,
&ObjectData3DTest::constructCamera,
&ObjectData3DTest::constructLight,
&ObjectData3DTest::constructCopy,
&ObjectData3DTest::constructMoveTransformations,
&ObjectData3DTest::constructMoveMesh,
&ObjectData3DTest::debugType});
&ObjectData3DTest::accessInvalidTransformations,
&ObjectData3DTest::debugType,
&ObjectData3DTest::debugFlag,
&ObjectData3DTest::debugFlags});
}
using namespace Math::Literals;
void ObjectData3DTest::constructEmpty() {
const int a{};
const ObjectData3D data{{0, 2, 3}, Matrix4::translation(Vector3::xAxis(-4.0f)), &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{0, 2, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::xAxis(-4.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Empty);
CORRADE_COMPARE(data.instance(), -1);
}
void ObjectData3DTest::constructEmptyTransformations() {
const int a{};
const ObjectData3D data{{0, 2, 3}, Vector3::xAxis(-4.0f), Quaternion::rotation(32.5_degf, Vector3::zAxis()), Vector3::yScale(1.5f), &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{0, 2, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlag3D::HasTransformationRotationScaling);
CORRADE_COMPARE(data.translation(), Vector3::xAxis(-4.0f));
CORRADE_COMPARE(data.rotation(), Quaternion::rotation(32.5_degf, Vector3::zAxis()));
CORRADE_COMPARE(data.scaling(), Vector3::yScale(1.5f));
CORRADE_COMPARE(data.transformation(),
Matrix4::translation(Vector3::xAxis(-4.0f))*
Matrix4::rotationZ(32.5_degf)*
Matrix4::scaling(Vector3::yScale(1.5f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Empty);
CORRADE_COMPARE(data.instance(), -1);
}
void ObjectData3DTest::constructMesh() {
const int a{};
const MeshObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), 13, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Mesh);
CORRADE_COMPARE(data.instance(), 13);
CORRADE_COMPARE(data.material(), 42);
}
void ObjectData3DTest::constructMeshTransformations() {
const int a{};
const MeshObjectData3D data{{1, 3}, Vector3::xAxis(-4.0f), Quaternion::rotation(32.5_degf, Vector3::zAxis()), Vector3::yScale(1.5f), 13, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlag3D::HasTransformationRotationScaling);
CORRADE_COMPARE(data.translation(), Vector3::xAxis(-4.0f));
CORRADE_COMPARE(data.rotation(), Quaternion::rotation(32.5_degf, Vector3::zAxis()));
CORRADE_COMPARE(data.scaling(), Vector3::yScale(1.5f));
CORRADE_COMPARE(data.transformation(),
Matrix4::translation(Vector3::xAxis(-4.0f))*
Matrix4::rotationZ(32.5_degf)*
Matrix4::scaling(Vector3::yScale(1.5f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Mesh);
CORRADE_COMPARE(data.instance(), 13);
CORRADE_COMPARE(data.material(), 42);
}
void ObjectData3DTest::constructCamera() {
const int a{};
const ObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), ObjectInstanceType3D::Camera, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Camera);
CORRADE_COMPARE(data.instance(), 42);
@ -91,6 +145,7 @@ void ObjectData3DTest::constructLight() {
const ObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), ObjectInstanceType3D::Light, 42, &a};
CORRADE_COMPARE(data.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(data.transformation(), Matrix4::translation(Vector3::yAxis(5.0f)));
CORRADE_COMPARE(data.instanceType(), ObjectInstanceType3D::Light);
CORRADE_COMPARE(data.instance(), 42);
@ -103,6 +158,42 @@ void ObjectData3DTest::constructCopy() {
CORRADE_VERIFY(!(std::is_assignable<MeshObjectData3D, const MeshObjectData3D&>{}));
}
void ObjectData3DTest::constructMoveTransformations() {
const int a{};
ObjectData3D data{{1, 3}, Vector3::xAxis(-4.0f), Quaternion::rotation(32.5_degf, Vector3::zAxis()), Vector3::yScale(1.5f), ObjectInstanceType3D::Light, 13, &a};
ObjectData3D b{std::move(data)};
CORRADE_COMPARE(b.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(b.flags(), ObjectFlag3D::HasTransformationRotationScaling);
CORRADE_COMPARE(b.translation(), Vector3::xAxis(-4.0f));
CORRADE_COMPARE(b.rotation(), Quaternion::rotation(32.5_degf, Vector3::zAxis()));
CORRADE_COMPARE(b.scaling(), Vector3::yScale(1.5f));
CORRADE_COMPARE(b.transformation(),
Matrix4::translation(Vector3::xAxis(-4.0f))*
Matrix4::rotationZ(32.5_degf)*
Matrix4::scaling(Vector3::yScale(1.5f)));
CORRADE_COMPARE(b.instanceType(), ObjectInstanceType3D::Light);
CORRADE_COMPARE(b.instance(), 13);
const int c{};
ObjectData3D d{{0, 1}, Matrix4{}, ObjectInstanceType3D::Empty, 27, &c};
d = std::move(b);
CORRADE_COMPARE(d.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(d.flags(), ObjectFlag3D::HasTransformationRotationScaling);
CORRADE_COMPARE(d.translation(), Vector3::xAxis(-4.0f));
CORRADE_COMPARE(d.rotation(), Quaternion::rotation(32.5_degf, Vector3::zAxis()));
CORRADE_COMPARE(d.scaling(), Vector3::yScale(1.5f));
CORRADE_COMPARE(d.transformation(),
Matrix4::translation(Vector3::xAxis(-4.0f))*
Matrix4::rotationZ(32.5_degf)*
Matrix4::scaling(Vector3::yScale(1.5f)));
CORRADE_COMPARE(d.instanceType(), ObjectInstanceType3D::Light);
CORRADE_COMPARE(d.instance(), 13);
}
void ObjectData3DTest::constructMoveMesh() {
const int a{};
MeshObjectData3D data{{1, 3}, Matrix4::translation(Vector3::yAxis(5.0f)), 13, 42, &a};
@ -110,6 +201,7 @@ void ObjectData3DTest::constructMoveMesh() {
MeshObjectData3D b{std::move(data)};
CORRADE_COMPARE(b.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(b.transformation(), Matrix4::translation(Vector3::yAxis(5.0f)));
CORRADE_COMPARE(b.instanceType(), ObjectInstanceType3D::Mesh);
CORRADE_COMPARE(b.instance(), 13);
@ -121,18 +213,46 @@ void ObjectData3DTest::constructMoveMesh() {
d = std::move(b);
CORRADE_COMPARE(d.children(), (std::vector<UnsignedInt>{1, 3}));
CORRADE_COMPARE(data.flags(), ObjectFlags3D{});
CORRADE_COMPARE(d.transformation(), Matrix4::translation(Vector3::yAxis(5.0f)));
CORRADE_COMPARE(d.instanceType(), ObjectInstanceType3D::Mesh);
CORRADE_COMPARE(d.instance(), 13);
CORRADE_COMPARE(d.material(), 42);
}
void ObjectData3DTest::accessInvalidTransformations() {
std::ostringstream out;
Error redirectOutput{&out};
const ObjectData3D data{{}, Matrix4{}};
data.translation();
data.rotation();
data.scaling();
CORRADE_COMPARE(out.str(),
"Trade::ObjectData3D::translation(): object has only a combined transformation\n"
"Trade::ObjectData3D::rotation(): object has only a combined transformation\n"
"Trade::ObjectData3D::scaling(): object has only a combined transformation\n");
}
void ObjectData3DTest::debugType() {
std::ostringstream o;
Debug(&o) << ObjectInstanceType3D::Light << ObjectInstanceType3D(0xbe);
CORRADE_COMPARE(o.str(), "Trade::ObjectInstanceType3D::Light Trade::ObjectInstanceType3D(0xbe)\n");
}
void ObjectData3DTest::debugFlag() {
std::ostringstream o;
Debug(&o) << ObjectFlag3D::HasTransformationRotationScaling << ObjectFlag3D(0xbe);
CORRADE_COMPARE(o.str(), "Trade::ObjectFlag3D::HasTransformationRotationScaling Trade::ObjectFlag3D(0xbe)\n");
}
void ObjectData3DTest::debugFlags() {
std::ostringstream o;
Debug(&o) << (ObjectFlag3D::HasTransformationRotationScaling|ObjectFlags3D{}) << ObjectFlags3D{};
CORRADE_COMPARE(o.str(), "Trade::ObjectFlag3D::HasTransformationRotationScaling Trade::ObjectFlags3D{}\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Trade::Test::ObjectData3DTest)

Loading…
Cancel
Save