mirror of https://github.com/mosra/magnum.git
Browse Source
Functionality present in Object is now split into three main components: * Object itself, handling parent/children relationships * Transformation implementation and interfaces for common functionality * Object features, providing transformation caching and base for cameras, collision shapes, rigid bodies etc. Some functionality depending on former implementation is temporarily disabled and will be reworked later.pull/7/head
22 changed files with 1526 additions and 581 deletions
@ -0,0 +1,319 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractFeature_h |
||||
#define Magnum_SceneGraph_AbstractFeature_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractFeature, alias Magnum::SceneGraph::AbstractFeature2D, Magnum::SceneGraph::AbstractFeature3D |
||||
*/ |
||||
|
||||
#include <Containers/EnumSet.h> |
||||
#include <Containers/LinkedList.h> |
||||
|
||||
#include "AbstractObject.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
namespace Implementation { |
||||
enum class FeatureCachedTransformation: std::uint8_t { |
||||
Absolute = 1 << 0, |
||||
InvertedAbsolute = 1 << 1 |
||||
}; |
||||
|
||||
typedef Corrade::Containers::EnumSet<FeatureCachedTransformation, std::uint8_t> FeatureCachedTransformations; |
||||
|
||||
CORRADE_ENUMSET_OPERATORS(FeatureCachedTransformations) |
||||
} |
||||
#endif |
||||
|
||||
/**
|
||||
@brief Base for object features |
||||
|
||||
Contained in Object, takes care of transformation caching. See @ref scenegraph |
||||
for introduction. |
||||
|
||||
@section AbstractFeature-subclassing Subclassing |
||||
|
||||
Feature is templated on dimension count and underlying transformation type, so |
||||
it can be used only on object having transformation with the same dimension |
||||
count and type. |
||||
|
||||
@subsection AbstractFeature-subclassing-caching Caching transformations in features |
||||
|
||||
Features can cache absolute transformation of the object instead of computing |
||||
it from scratch every time to achieve better performance. See |
||||
@ref scenegraph-caching for introduction. |
||||
|
||||
In order to have caching, you must enable it first, because by default the |
||||
caching is disabled. You can enable it using setCachedTransformations() and |
||||
then implement corresponding cleaning function(s) -- either clean(), |
||||
cleanInverted() or both. Example: |
||||
@code |
||||
class CachingFeature: public SceneGraph::AbstractFeature3D<> { |
||||
public: |
||||
CachingFeature(SceneGraph::AbstractObject3D<>* object): SceneGraph::AbstractFeature3D<>(object) { |
||||
setCachedTransformations(CachedTransformation::Absolute); |
||||
} |
||||
|
||||
protected: |
||||
void clean(const Matrix4& absoluteTransformation) override { |
||||
absolutePosition = absoluteTransformation.translation(); |
||||
} |
||||
|
||||
private: |
||||
Vector3 absolutePosition; |
||||
}; |
||||
@endcode |
||||
|
||||
Before using the cached value explicitly request object cleaning by calling |
||||
`object()->setClean()`. |
||||
|
||||
@subsection AbstractFeature-subclassing-transformation Accessing object transformation |
||||
|
||||
Features has by default access only to AbstractObject, which is base of Object |
||||
not depending on any particular transformation implementation. This has the |
||||
advantage that features doesn't have to be implemented for all possible |
||||
transformation implementations, thus preventing code duplication. However it |
||||
is impossible to transform the object using only pointer to AbstractObject. |
||||
|
||||
The transformations have interfaces for common functionality, so the feature |
||||
can use that interface instead of being specialized for all relevant |
||||
transformation implementations. Using small trick we are able to get pointer |
||||
to both AbstractObject and needed transformation from one constructor |
||||
parameter: |
||||
@code |
||||
class TransformingFeature: public SceneGraph::AbstractFeature3D<> { |
||||
public: |
||||
template<class T> inline TransformingFeature(SceneGraph::Object<T>* object): |
||||
SceneGraph::AbstractFeature3D<>(object), transformation(object) {} |
||||
|
||||
private: |
||||
SceneGraph::AbstractTranslationRotation3D<>* transformation; |
||||
}; |
||||
@endcode |
||||
If we take for example @ref Object "Object<MatrixTransformation3D<>>", it is |
||||
derived from @ref AbstractObject "AbstractObject3D<>" and |
||||
@ref MatrixTransformation3D "MatrixTransformation3D<>", which is derived from |
||||
@ref AbstractTranslationRotationScaling3D "AbstractTranslationRotationScaling3D<>", |
||||
which is derived from |
||||
@ref AbstractTranslationRotation3D "AbstractTranslationRotation3D<>", |
||||
which is automatically extracted from the pointer in our constructor. |
||||
|
||||
@see AbstractFeature2D, AbstractFeature3D |
||||
*/ |
||||
template<std::uint8_t dimensions, class T = GLfloat> class AbstractFeature |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
: private Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>> |
||||
#endif |
||||
{ |
||||
friend class Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>; |
||||
friend class Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>; |
||||
template<class Transformation> friend class Object; |
||||
|
||||
public: |
||||
/**
|
||||
* @brief Constructor |
||||
* @param object %Object holding this feature |
||||
*/ |
||||
inline AbstractFeature(AbstractObject<dimensions, T>* object) { |
||||
object->Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::insert(this); |
||||
} |
||||
|
||||
virtual ~AbstractFeature() = 0; |
||||
|
||||
/** @brief %Object holding this feature */ |
||||
inline AbstractObject<dimensions, T>* object() { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::list(); |
||||
} |
||||
|
||||
/** @overload */ |
||||
inline const AbstractObject<dimensions, T>* object() const { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::list(); |
||||
} |
||||
|
||||
/** @brief Previous feature or `nullptr`, if this is first feature */ |
||||
inline AbstractFeature<dimensions, T>* previousFeature() { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous(); |
||||
} |
||||
|
||||
/** @overload */ |
||||
inline const AbstractFeature<dimensions, T>* previousFeature() const { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::previous(); |
||||
} |
||||
|
||||
/** @brief Next feature or `nullptr`, if this is last feature */ |
||||
inline AbstractFeature<dimensions, T>* nextFeature() { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::next(); |
||||
} |
||||
|
||||
/** @overload */ |
||||
inline const AbstractFeature<dimensions, T>* nextFeature() const { |
||||
return Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>::next(); |
||||
} |
||||
|
||||
/**
|
||||
* @{ @name Transformation caching |
||||
* |
||||
* See @ref scenegraph-caching for more information. |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief Which transformation to cache in this feature |
||||
* |
||||
* @see @ref scenegraph-caching, CachedTransformations, |
||||
* setCachedTransformations(), clean(), cleanInverted() |
||||
* @todo Provide also simpler representations from which could benefit |
||||
* other transformation implementations, as they won't need to |
||||
* e.g. create transformation matrix from quaternion? |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
typedef Implementation::FeatureCachedTransformation CachedTransformation; |
||||
#else |
||||
enum class CachedTransformation: std::uint8_t { |
||||
/**
|
||||
* Absolute transformation is cached. |
||||
* |
||||
* If enabled, clean() is called when cleaning object. |
||||
*/ |
||||
Absolute = 1 << 0, |
||||
|
||||
/**
|
||||
* Inverted absolute transformation is cached. |
||||
* |
||||
* If enabled, cleanInverted() is called when cleaning object. |
||||
*/ |
||||
InvertedAbsolute = 1 << 1 |
||||
}; |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Which transformations to cache in this feature |
||||
* |
||||
* @see @ref scenegraph-caching, setCachedTransformations(), clean(), |
||||
* cleanInverted() |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
typedef Implementation::FeatureCachedTransformations CachedTransformations; |
||||
#else |
||||
typedef Corrade::Containers::EnumSet<CachedTransformation, std::uint8_t> CachedTransformations; |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Which transformations are cached |
||||
* |
||||
* @see @ref scenegraph-caching, clean(), cleanInverted() |
||||
*/ |
||||
inline CachedTransformations cachedTransformations() const { return _cachedTransformations; } |
||||
|
||||
protected: |
||||
/**
|
||||
* @brief Set transformations to be cached |
||||
* |
||||
* Based on which transformation types are enabled, clean() or |
||||
* cleanInverted() is called when cleaning absolute object |
||||
* transformation. |
||||
* |
||||
* Nothing is enabled by default. |
||||
* @see @ref scenegraph-caching |
||||
*/ |
||||
inline void setCachedTransformations(CachedTransformations transformations) { _cachedTransformations = transformations; } |
||||
|
||||
/**
|
||||
* @brief Mark feature as dirty |
||||
* |
||||
* Reimplement only if you want to invalidate some external data when |
||||
* object is marked as dirty. All expensive computations should be |
||||
* done in clean() and cleanInverted(). |
||||
* |
||||
* Default implementation does nothing. |
||||
* @see @ref scenegraph-caching |
||||
*/ |
||||
inline virtual void markDirty() {} |
||||
|
||||
/**
|
||||
* @brief Clean data based on absolute transformation |
||||
* |
||||
* When object is cleaned and |
||||
* @ref CachedTransformation "CachedTransformation::Absolute" is |
||||
* enabled in setCachedTransformations(), this function is called to |
||||
* recalculate data based on absolute object transformation. |
||||
* |
||||
* Default implementation does nothing. |
||||
* @see @ref scenegraph-caching, cleanInverted() |
||||
*/ |
||||
virtual void clean(const typename DimensionTraits<dimensions, T>::MatrixType& absoluteTransformation); |
||||
|
||||
/**
|
||||
* @brief Clean data based on inverted absolute transformation |
||||
* |
||||
* When object is cleaned and |
||||
* @ref CachedTransformation "CachedTransformation::InvertedAbsolute" |
||||
* is enabled in setCachedTransformations(), this function is called |
||||
* to recalculate data based on inverted absolute object |
||||
* transformation. |
||||
* |
||||
* Default implementation does nothing. |
||||
* @see @ref scenegraph-caching, clean() |
||||
*/ |
||||
virtual void cleanInverted(const typename DimensionTraits<dimensions, T>::MatrixType& invertedAbsoluteTransformation); |
||||
|
||||
/*@}*/ |
||||
|
||||
private: |
||||
CachedTransformations _cachedTransformations; |
||||
}; |
||||
|
||||
template<std::uint8_t dimensions, class T> inline AbstractFeature<dimensions, T>::~AbstractFeature() {} |
||||
template<std::uint8_t dimensions, class T> inline void AbstractFeature<dimensions, T>::clean(const typename DimensionTraits<dimensions, T>::MatrixType&) {} |
||||
template<std::uint8_t dimensions, class T> inline void AbstractFeature<dimensions, T>::cleanInverted(const typename DimensionTraits<dimensions, T>::MatrixType&) {} |
||||
|
||||
/**
|
||||
@brief Base for two-dimensional features |
||||
|
||||
Convenience alternative to <tt>%AbstractFeature<2, T></tt>. See AbstractFeature |
||||
for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractFeature<2, T></tt> instead. |
||||
@see AbstractFeature3D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractFeature2D = AbstractFeature<2, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractFeature<2, T = GLfloat> AbstractFeature2D; |
||||
#endif |
||||
|
||||
/**
|
||||
@brief Base for three-dimensional features |
||||
|
||||
Convenience alternative to <tt>%AbstractFeature<3, T></tt>. See AbstractFeature |
||||
for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractFeature<3, T></tt> instead. |
||||
@see AbstractFeature2D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractFeature3D = AbstractFeature<3, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractFeature<2, T = GLfloat> AbstractFeature3D; |
||||
#endif |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,130 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractObject_h |
||||
#define Magnum_SceneGraph_AbstractObject_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractObject, alias Magnum::SceneGraph::AbstractObject2D, Magnum::SceneGraph::AbstractObject3D |
||||
*/ |
||||
|
||||
#include <Containers/LinkedList.h> |
||||
|
||||
#include "DimensionTraits.h" |
||||
#include "Magnum.h" |
||||
|
||||
#include "magnumCompatibility.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
template<std::uint8_t, class> class AbstractFeature; |
||||
|
||||
/**
|
||||
@brief Base for objects |
||||
|
||||
Provides minimal interface for features, not depending on object |
||||
transformation implementation. See Object or @ref scenegraph for more |
||||
information. |
||||
|
||||
@see AbstractObject2D, AbstractObject3D |
||||
*/ |
||||
template<std::uint8_t dimensions, class T = GLfloat> class AbstractObject |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
: private Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>> |
||||
#endif |
||||
{ |
||||
friend class Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>; |
||||
friend class Corrade::Containers::LinkedListItem<AbstractFeature<dimensions, T>, AbstractObject<dimensions, T>>; |
||||
friend AbstractFeature<dimensions, T>::AbstractFeature(AbstractObject<dimensions, T>*); |
||||
|
||||
public: |
||||
/** @brief Feature object type */ |
||||
typedef AbstractFeature<dimensions, T> FeatureType; |
||||
|
||||
inline virtual ~AbstractObject() {} |
||||
|
||||
/** @brief Whether this object has features */ |
||||
inline bool hasFeatures() const { |
||||
return !Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::isEmpty(); |
||||
} |
||||
|
||||
/** @brief First object feature or `nullptr`, if this object has no features */ |
||||
inline FeatureType* firstFeature() { |
||||
return Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::first(); |
||||
} |
||||
|
||||
/** @overload */ |
||||
inline const FeatureType* firstFeature() const { |
||||
return Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::first(); |
||||
} |
||||
|
||||
/** @brief Last object feature or `nullptr`, if this object has no features */ |
||||
inline FeatureType* lastFeature() { |
||||
return Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::last(); |
||||
} |
||||
|
||||
/** @overload */ |
||||
inline const FeatureType* lastFeature() const { |
||||
return Corrade::Containers::LinkedList<AbstractFeature<dimensions, T>>::last(); |
||||
} |
||||
|
||||
/** @{ @name Object transformation */ |
||||
|
||||
/**
|
||||
* @brief Transformation matrix relative to root object |
||||
* |
||||
* @see Object::absoluteTransformation() |
||||
*/ |
||||
virtual typename DimensionTraits<dimensions, T>::MatrixType absoluteTransformationMatrix() const = 0; |
||||
|
||||
/*@}*/ |
||||
}; |
||||
|
||||
/**
|
||||
@brief Base for two-dimensional objects |
||||
|
||||
Convenience alternative to <tt>%AbstractObject<2, T></tt>. See AbstractObject |
||||
for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractObject<2, T></tt> instead. |
||||
@see AbstractObject3D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractObject2D = AbstractObject<2, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractObject<2, T = GLfloat> AbstractObject2D; |
||||
#endif |
||||
|
||||
/**
|
||||
@brief Base for three-dimensional objects |
||||
|
||||
Convenience alternative to <tt>%AbstractObject<3, T></tt>. See AbstractObject |
||||
for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractObject<3, T></tt> instead. |
||||
@see AbstractObject2D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractObject3D = AbstractObject<3, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractObject<3, T = GLfloat> AbstractObject3D; |
||||
#endif |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,169 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractTransformation_h |
||||
#define Magnum_SceneGraph_AbstractTransformation_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractTransformation, enum Magnum::SceneGraph::TransformationType, alias Magnum::SceneGraph::AbstractTransformation2D, Magnum::SceneGraph::AbstractTransformation3D |
||||
*/ |
||||
|
||||
#include <vector> |
||||
|
||||
#include "Magnum.h" |
||||
#include "DimensionTraits.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
template<class> class Object; |
||||
|
||||
/**
|
||||
@brief Base for transformations |
||||
|
||||
Provides transformation implementation for Object instances. See @ref scenegraph |
||||
for introduction. |
||||
|
||||
@section AbstractTransformation-subclassing Subclassing |
||||
|
||||
When sublassing, you have to: |
||||
|
||||
- Implement all members described in **Subclass implementation** group above |
||||
- Provide implicit (parameterless) constructor |
||||
|
||||
@see AbstractTransformation2D, AbstractTransformation3D |
||||
*/ |
||||
template<std::uint8_t dimensions, class T = GLfloat> class AbstractTransformation { |
||||
public: |
||||
/** @brief Underlying floating-point type */ |
||||
typedef T Type; |
||||
|
||||
/** @brief Dimension count */ |
||||
static const std::uint8_t Dimensions = dimensions; |
||||
|
||||
virtual ~AbstractTransformation() = 0; |
||||
|
||||
#ifdef DOXYGEN_GENERATING_OUTPUT |
||||
/**
|
||||
* @{ @name Subclass implementation |
||||
* |
||||
* These members must be defined by the implementation. |
||||
*/ |
||||
|
||||
/**
|
||||
* @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 Transformation type */ |
||||
enum class TransformationType: std::uint8_t { |
||||
/** Global transformation, applied after all other transformations. */ |
||||
Global = 0x00, |
||||
|
||||
/** Local transformation, applied before all other transformations. */ |
||||
Local = 0x01 |
||||
}; |
||||
|
||||
template<std::uint8_t dimensions, class T> inline AbstractTransformation<dimensions, T>::~AbstractTransformation() {} |
||||
|
||||
/**
|
||||
@brief Base for two-dimensional transformations |
||||
|
||||
Convenience alternative to <tt>%AbstractTransformation<2, T></tt>. See |
||||
AbstractTransformation for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractTransformation<2, T></tt> |
||||
instead. |
||||
@see AbstractTransformation3D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractTransformation2D = AbstractTransformation<2, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractTransformation<2, T = GLfloat> AbstractTransformation2D; |
||||
#endif |
||||
|
||||
/**
|
||||
@brief Base for three-dimensional transformations |
||||
|
||||
Convenience alternative to <tt>%AbstractTransformation<3, T></tt>. See |
||||
AbstractTransformation for more information. |
||||
@note Not available on GCC < 4.7. Use <tt>%AbstractTransformation<3, T></tt> |
||||
instead. |
||||
@see AbstractTransformation2D |
||||
@todoc Remove workaround when Doxygen supports alias template |
||||
*/ |
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#ifndef MAGNUM_GCC46_COMPATIBILITY |
||||
template<class T = GLfloat> using AbstractTransformation3D = AbstractTransformation<3, T>; |
||||
#endif |
||||
#else |
||||
typedef AbstractTransformation<3, T = GLfloat> AbstractTransformation3D; |
||||
#endif |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,56 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractTranslationRotation2D_h |
||||
#define Magnum_SceneGraph_AbstractTranslationRotation2D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractTranslationRotation2D |
||||
*/ |
||||
|
||||
#include "AbstractTransformation.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Base for two-dimensional transformations supporting translation and rotation |
||||
|
||||
@see AbstractTranslationRotation3D |
||||
*/ |
||||
template<class T = GLfloat> class AbstractTranslationRotation2D: public AbstractTransformation<2, T> { |
||||
public: |
||||
/**
|
||||
* @brief Translate object |
||||
* @param vector Translation vector |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see Vector2::xAxis(), Vector2::yAxis() |
||||
*/ |
||||
virtual AbstractTranslationRotation2D<T>* translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) = 0; |
||||
|
||||
/**
|
||||
* @brief Rotate object |
||||
* @param angle Angle in radians, counterclockwise |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see deg(), rad() |
||||
*/ |
||||
virtual AbstractTranslationRotation2D<T>* rotate(T angle, TransformationType type = TransformationType::Global) = 0; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,57 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractTranslationRotation3D_h |
||||
#define Magnum_SceneGraph_AbstractTranslationRotation3D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractTranslationRotation3D |
||||
*/ |
||||
|
||||
#include "AbstractTransformation.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Base for three-dimensional transformations supporting translation and rotation |
||||
|
||||
@see AbstractTranslationRotation2D |
||||
*/ |
||||
template<class T = GLfloat> class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { |
||||
public: |
||||
/**
|
||||
* @brief Translate object |
||||
* @param vector Translation vector |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis() |
||||
*/ |
||||
virtual AbstractTranslationRotation3D<T>* translate(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) = 0; |
||||
|
||||
/**
|
||||
* @brief Rotate object |
||||
* @param angle Angle in radians, counterclockwise |
||||
* @param normalizedAxis Normalized rotation axis |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see deg(), rad(), Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis() |
||||
*/ |
||||
virtual AbstractTranslationRotation3D<T>* rotate(T angle, const Math::Vector3<T>& normalizedAxis, TransformationType type = TransformationType::Global) = 0; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,46 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractTranslationRotationScaling2D_h |
||||
#define Magnum_SceneGraph_AbstractTranslationRotationScaling2D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractTranslationRotationScaling2D |
||||
*/ |
||||
|
||||
#include "AbstractTranslationRotation2D.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Base for two-dimensional transformations supporting translation, rotation and scaling |
||||
|
||||
@see AbstractTranslationRotationScaling2D |
||||
*/ |
||||
template<class T = GLfloat> class AbstractTranslationRotationScaling2D: public AbstractTranslationRotation2D<T> { |
||||
public: |
||||
/**
|
||||
* @brief Scale object |
||||
* @param vector Scaling vector |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see Vector2::xScale(), Vector2::yScale() |
||||
*/ |
||||
virtual AbstractTranslationRotationScaling2D<T>* scale(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) = 0; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,46 @@
|
||||
#ifndef Magnum_SceneGraph_AbstractTranslationRotationScaling3D_h |
||||
#define Magnum_SceneGraph_AbstractTranslationRotationScaling3D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::AbstractTranslationRotationScaling3D |
||||
*/ |
||||
|
||||
#include "AbstractTranslationRotation3D.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Base for three-dimensional transformations supporting translation, rotation and scaling |
||||
|
||||
@see AbstractTranslationRotationScaling2D |
||||
*/ |
||||
template<class T = GLfloat> class AbstractTranslationRotationScaling3D: public AbstractTranslationRotation3D<T> { |
||||
public: |
||||
/**
|
||||
* @brief Scale object |
||||
* @param vector Scaling vector |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
* |
||||
* @see Vector3::xScale(), Vector3::yScale(), Vector3::zScale() |
||||
*/ |
||||
virtual AbstractTranslationRotationScaling3D<T>* scale(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) = 0; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
#include "MatrixTransformation2D.h" |
||||
|
||||
#include "Object.hpp" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template class SCENEGRAPH_EXPORT Object<MatrixTransformation2D<>>; |
||||
#endif |
||||
|
||||
}} |
||||
@ -0,0 +1,136 @@
|
||||
#ifndef Magnum_SceneGraph_MatrixTransformation2D_h |
||||
#define Magnum_SceneGraph_MatrixTransformation2D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::MatrixTransformation2D |
||||
*/ |
||||
|
||||
#include "Math/Matrix3.h" |
||||
#include "AbstractTranslationRotationScaling2D.h" |
||||
#include "Object.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Two-dimensional transformation implemented using matrices |
||||
|
||||
@see MatrixTransformation3D |
||||
*/ |
||||
template<class T = GLfloat> class MatrixTransformation2D: public AbstractTranslationRotationScaling2D<T> { |
||||
public: |
||||
/** @brief Transformation matrix type */ |
||||
typedef typename DimensionTraits<2, T>::MatrixType DataType; |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
inline constexpr static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) { |
||||
return matrix; |
||||
} |
||||
|
||||
inline constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) { |
||||
return transformation; |
||||
} |
||||
|
||||
inline static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) { |
||||
return parent*child; |
||||
} |
||||
|
||||
inline static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) { |
||||
return transformation.inverted(); |
||||
} |
||||
|
||||
inline Math::Matrix3<T> transformation() const { |
||||
return _transformation; |
||||
} |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set transformation |
||||
* @return Pointer to self (for method chaining) |
||||
*/ |
||||
MatrixTransformation2D<T>* setTransformation(const Math::Matrix3<T>& transformation) { |
||||
/* Setting transformation is forbidden for the scene */ |
||||
/** @todo Assert for this? */ |
||||
/** @todo Do this in some common code? */ |
||||
if(!static_cast<Object<MatrixTransformation2D<T>>*>(this)->isScene()) { |
||||
_transformation = transformation; |
||||
static_cast<Object<MatrixTransformation2D<T>>*>(this)->setDirty(); |
||||
} |
||||
|
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Multiply transformation |
||||
* @param transformation Transformation |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
*/ |
||||
inline MatrixTransformation2D<T>* multiplyTransformation(const Math::Matrix3<T>& transformation, TransformationType type = TransformationType::Global) { |
||||
setTransformation(type == TransformationType::Global ? |
||||
transformation*_transformation : _transformation*transformation); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling2D::translate() |
||||
* Same as calling multiplyTransformation() with Matrix3::translation(). |
||||
*/ |
||||
inline MatrixTransformation2D<T>* translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix3<T>::translation(vector), type); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling2D::rotate() |
||||
* Same as calling multiplyTransformation() with Matrix3::rotation(). |
||||
*/ |
||||
inline MatrixTransformation2D<T>* rotate(T angle, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix3<T>::rotation(angle), type); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling2D::scale() |
||||
* Same as calling multiplyTransformation() with Matrix3::scaling(). |
||||
*/ |
||||
inline MatrixTransformation2D<T>* scale(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix3<T>::scaling(vector), type); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Move object in stacking order |
||||
* @param under Sibling object under which to move or `nullptr`, |
||||
* if you want to move it above all. |
||||
* @return Pointer to self (for method chaining) |
||||
*/ |
||||
inline MatrixTransformation2D<T>* move(Object<MatrixTransformation2D<T>>* under) { |
||||
static_cast<Object<MatrixTransformation2D>*>(this)->Corrade::Containers::LinkedList<Object<MatrixTransformation2D<T>>>::move(this, under); |
||||
return this; |
||||
} |
||||
|
||||
protected: |
||||
/* Allow construction only from Object */ |
||||
inline MatrixTransformation2D() {} |
||||
|
||||
private: |
||||
Math::Matrix3<T> _transformation; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
#include "MatrixTransformation3D.h" |
||||
|
||||
#include "Object.hpp" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
template class SCENEGRAPH_EXPORT Object<MatrixTransformation3D<>>; |
||||
#endif |
||||
|
||||
}} |
||||
@ -0,0 +1,125 @@
|
||||
#ifndef Magnum_SceneGraph_MatrixTransformation3D_h |
||||
#define Magnum_SceneGraph_MatrixTransformation3D_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class Magnum::SceneGraph::MatrixTransformation3D |
||||
*/ |
||||
|
||||
#include "Math/Matrix4.h" |
||||
#include "AbstractTranslationRotationScaling3D.h" |
||||
#include "Object.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
/**
|
||||
@brief Three-dimensional transformation implemented using matrices |
||||
|
||||
@see MatrixTransformation2D |
||||
*/ |
||||
template<class T = GLfloat> class MatrixTransformation3D: public AbstractTranslationRotationScaling3D<T> { |
||||
public: |
||||
/** @brief Transformation matrix type */ |
||||
typedef typename DimensionTraits<3, T>::MatrixType DataType; |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
inline constexpr static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) { |
||||
return matrix; |
||||
} |
||||
|
||||
inline constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) { |
||||
return transformation; |
||||
} |
||||
|
||||
inline static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) { |
||||
return parent*child; |
||||
} |
||||
|
||||
inline static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) { |
||||
return transformation.inverted(); |
||||
} |
||||
|
||||
inline Math::Matrix4<T> transformation() const { |
||||
return _transformation; |
||||
} |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set transformation |
||||
* @return Pointer to self (for method chaining) |
||||
*/ |
||||
MatrixTransformation3D<T>* setTransformation(const Math::Matrix4<T>& transformation) { |
||||
/* Setting transformation is forbidden for the scene */ |
||||
/** @todo Assert for this? */ |
||||
/** @todo Do this in some common code? */ |
||||
if(!static_cast<Object<MatrixTransformation3D<T>>*>(this)->isScene()) { |
||||
_transformation = transformation; |
||||
static_cast<Object<MatrixTransformation3D<T>>*>(this)->setDirty(); |
||||
} |
||||
|
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Multiply transformation |
||||
* @param transformation Transformation |
||||
* @param type Transformation type |
||||
* @return Pointer to self (for method chaining) |
||||
*/ |
||||
inline MatrixTransformation3D<T>* multiplyTransformation(const Math::Matrix4<T>& transformation, TransformationType type = TransformationType::Global) { |
||||
setTransformation(type == TransformationType::Global ? |
||||
transformation*_transformation : _transformation*transformation); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling3D::translate() |
||||
* Same as calling multiplyTransformation() with Matrix4::translation(). |
||||
*/ |
||||
inline MatrixTransformation3D<T>* translate(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix4<T>::translation(vector), type); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling3D::rotate() |
||||
* Same as calling multiplyTransformation() with Matrix4::rotation(). |
||||
*/ |
||||
inline MatrixTransformation3D<T>* rotate(T angle, const Math::Vector3<T>& normalizedAxis, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix4<T>::rotation(angle, normalizedAxis), type); |
||||
return this; |
||||
} |
||||
|
||||
/**
|
||||
* @copydoc AbstractTranslationRotationScaling3D::scale() |
||||
* Same as calling multiplyTransformation() with Matrix4::scaling(). |
||||
*/ |
||||
inline MatrixTransformation3D<T>* scale(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) override { |
||||
multiplyTransformation(Math::Matrix4<T>::scaling(vector), type); |
||||
return this; |
||||
} |
||||
|
||||
protected: |
||||
/* Allow construction only from Object */ |
||||
inline MatrixTransformation3D() {} |
||||
|
||||
private: |
||||
Math::Matrix4<T> _transformation; |
||||
}; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -1,147 +0,0 @@
|
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
#include "Object.h" |
||||
|
||||
#include <stack> |
||||
|
||||
#include "Scene.h" |
||||
#include "Camera.h" |
||||
|
||||
using namespace std; |
||||
using namespace Magnum::Math; |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
template<std::uint8_t dimensions> typename AbstractObject<dimensions>::ObjectType* AbstractObject<dimensions>::setParent(ObjectType* parent) { |
||||
/* Skip if nothing to do or this is scene */ |
||||
if(this->parent() == parent || isScene()) return static_cast<ObjectType*>(this); |
||||
|
||||
/* Only Fry can be his own grandfather */ |
||||
ObjectType* p = parent; |
||||
while(p) { |
||||
/** @todo Assert for this */ |
||||
if(p == this) return static_cast<ObjectType*>(this); |
||||
p = p->parent(); |
||||
} |
||||
|
||||
/* Remove the object from old parent children list */ |
||||
if(this->parent()) |
||||
this->parent()->cut(static_cast<ObjectType*>(this)); |
||||
|
||||
/* Add the object to list of new parent */ |
||||
if(parent) |
||||
parent->insert(static_cast<ObjectType*>(this)); |
||||
|
||||
setDirty(); |
||||
return static_cast<ObjectType*>(this); |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> typename DimensionTraits<dimensions, GLfloat>::MatrixType AbstractObject<dimensions>::absoluteTransformation(CameraType* camera) { |
||||
/* Shortcut for absolute transformation of camera relative to itself */ |
||||
if(camera == this) return typename DimensionTraits<dimensions, GLfloat>::MatrixType(); |
||||
|
||||
typename DimensionTraits<dimensions, GLfloat>::MatrixType t = _transformation; |
||||
|
||||
ObjectType* p = parent(); |
||||
while(p != nullptr) { |
||||
t = p->transformation()*t; |
||||
|
||||
/* We got to the scene, multiply with camera matrix */ |
||||
if(p->isScene()) { |
||||
if(camera) { |
||||
CORRADE_ASSERT(camera->scene() == scene(), "Object::absoluteTransformation(): the camera is not part of the same scene as object!", t); |
||||
t = camera->cameraMatrix()*t; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
p = p->parent(); |
||||
} |
||||
|
||||
CORRADE_ASSERT(p != nullptr || camera == nullptr, "Object::absoluteTransformation(): the object is not part of camera scene!", t); |
||||
|
||||
return t; |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> typename AbstractObject<dimensions>::SceneType* AbstractObject<dimensions>::scene() { |
||||
/* Goes up the family tree until it finds object which is parent of itself
|
||||
(that's the scene) */ |
||||
ObjectType* p = parent(); |
||||
while(p != nullptr) { |
||||
if(p->isScene()) return static_cast<SceneType*>(p); |
||||
p = p->parent(); |
||||
} |
||||
|
||||
return nullptr; |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> typename AbstractObject<dimensions>::ObjectType* AbstractObject<dimensions>::setTransformation(const typename DimensionTraits<dimensions, GLfloat>::MatrixType& transformation) { |
||||
/* Setting transformation is forbidden for the scene */ |
||||
/** @todo Assert for this? */ |
||||
if(isScene()) return static_cast<ObjectType*>(this); |
||||
|
||||
_transformation = transformation; |
||||
setDirty(); |
||||
return static_cast<ObjectType*>(this); |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> void AbstractObject<dimensions>::setDirty() { |
||||
/* The object (and all its children) are already dirty, nothing to do */ |
||||
if(dirty) return; |
||||
|
||||
dirty = true; |
||||
|
||||
/* Make all children dirty */ |
||||
for(ObjectType* i = firstChild(); i; i = i->nextSibling()) |
||||
i->setDirty(); |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> void AbstractObject<dimensions>::setClean() { |
||||
/* The object (and all its parents) are already clean, nothing to do */ |
||||
if(!dirty) return; |
||||
|
||||
/* Collect all parents */ |
||||
stack<ObjectType*> objects; |
||||
ObjectType* p = static_cast<ObjectType*>(this); |
||||
for(;;) { |
||||
objects.push(p); |
||||
|
||||
/* Stop on root object / clean object */ |
||||
if(p->parent() == nullptr || !p->parent()->isDirty()) |
||||
break; |
||||
|
||||
p = p->parent(); |
||||
} |
||||
|
||||
/* Call setClean(const Matrix4&) for every parent and also this object */ |
||||
ObjectType* o = objects.top(); |
||||
objects.pop(); |
||||
typename DimensionTraits<dimensions, GLfloat>::MatrixType absoluteTransformation = o->absoluteTransformation(); |
||||
o->clean(absoluteTransformation); |
||||
while(!objects.empty()) { |
||||
o = objects.top(); |
||||
objects.pop(); |
||||
absoluteTransformation = absoluteTransformation*o->transformation(); |
||||
o->clean(absoluteTransformation); |
||||
} |
||||
} |
||||
|
||||
/* Explicitly instantiate the templates */ |
||||
template class AbstractObject<2>; |
||||
template class AbstractObject<3>; |
||||
|
||||
}} |
||||
@ -0,0 +1,159 @@
|
||||
#ifndef Magnum_SceneGraph_Object_hpp |
||||
#define Magnum_SceneGraph_Object_hpp |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
This file is part of Magnum. |
||||
|
||||
Magnum is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU Lesser General Public License version 3 |
||||
only, as published by the Free Software Foundation. |
||||
|
||||
Magnum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU Lesser General Public License version 3 for more details. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief @ref compilation-speedup-hpp "Template implementation" for Object.h |
||||
*/ |
||||
|
||||
#include "Object.h" |
||||
|
||||
#include <stack> |
||||
|
||||
#include "Scene.h" |
||||
|
||||
namespace Magnum { namespace SceneGraph { |
||||
|
||||
template<class Transformation> Scene<Transformation>* Object<Transformation>::scene() { |
||||
Object<Transformation>* p(this); |
||||
while(p && !p->isScene()) p = p->parent(); |
||||
return static_cast<Scene<Transformation>*>(p); |
||||
} |
||||
|
||||
template<class Transformation> const Scene<Transformation>* Object<Transformation>::scene() const { |
||||
const Object<Transformation>* p(this); |
||||
while(p && !p->isScene()) p = p->parent(); |
||||
return static_cast<const Scene<Transformation>*>(p); |
||||
} |
||||
|
||||
template<class Transformation> Object<Transformation>* Object<Transformation>::setParent(Object<Transformation>* parent) { |
||||
/* Skip if parent is already parent or this is scene (which cannot have parent) */ |
||||
/** @todo Assert for setting parent to scene */ |
||||
if(this->parent() == parent || isScene()) return this; |
||||
|
||||
/* Object cannot be parented to its child */ |
||||
Object<Transformation>* p = parent; |
||||
while(p) { |
||||
/** @todo Assert for this */ |
||||
if(p == this) return this; |
||||
p = p->parent(); |
||||
} |
||||
|
||||
/* Remove the object from old parent children list */ |
||||
if(this->parent()) this->parent()->Corrade::Containers::LinkedList<Object<Transformation>>::cut(this); |
||||
|
||||
/* Add the object to list of new parent */ |
||||
if(parent) parent->Corrade::Containers::LinkedList<Object<Transformation>>::insert(this); |
||||
|
||||
setDirty(); |
||||
return this; |
||||
} |
||||
|
||||
template<class Transformation> typename Transformation::DataType Object<Transformation>::absoluteTransformation() const { |
||||
if(!parent()) return Transformation::transformation(); |
||||
return Transformation::compose(parent()->absoluteTransformation(), Transformation::transformation()); |
||||
} |
||||
|
||||
template<class Transformation> void Object<Transformation>::setDirty() { |
||||
/* The transformation of this object (and all children) is already dirty,
|
||||
nothing to do */ |
||||
if(flags & Flag::Dirty) return; |
||||
|
||||
Object<Transformation>* self = static_cast<Object<Transformation>*>(this); |
||||
|
||||
/* Make all features dirty */ |
||||
for(AbstractFeature<Transformation::Dimensions, typename Transformation::Type>* i = self->firstFeature(); i; i = i->nextFeature()) |
||||
i->markDirty(); |
||||
|
||||
/* Make all children dirty */ |
||||
for(Object<Transformation>* i = self->firstChild(); i; i = i->nextSibling()) |
||||
i->setDirty(); |
||||
|
||||
/* Mark object as dirty */ |
||||
flags |= Flag::Dirty; |
||||
} |
||||
|
||||
template<class Transformation> void Object<Transformation>::setClean() { |
||||
/* The object (and all its parents) are already clean, nothing to do */ |
||||
if(!(flags & Flag::Dirty)) return; |
||||
|
||||
/* Collect all parents, compute base transformation */ |
||||
std::stack<Object<Transformation>*> objects; |
||||
typename Transformation::DataType absoluteTransformation; |
||||
Object<Transformation>* p = static_cast<Object<Transformation>*>(this); |
||||
for(;;) { |
||||
objects.push(p); |
||||
|
||||
p = p->parent(); |
||||
|
||||
/* On root object, base transformation is identity */ |
||||
if(!p) break; |
||||
|
||||
/* Parent object is clean, base transformation is its absolute
|
||||
transformation */ |
||||
if(!p->isDirty()) { |
||||
absoluteTransformation = p->absoluteTransformation(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* Clean features on every collected object, going down from root object */ |
||||
while(!objects.empty()) { |
||||
Object<Transformation>* o = objects.top(); |
||||
objects.pop(); |
||||
|
||||
/* Compose transformations */ |
||||
absoluteTransformation = Transformation::compose(absoluteTransformation, o->transformation()); |
||||
|
||||
/* "Lazy storage" for transformation matrix and inverted transformation matrix */ |
||||
typedef typename AbstractFeature<Transformation::Dimensions, typename Transformation::Type>::CachedTransformation CachedTransformation; |
||||
typename AbstractFeature<Transformation::Dimensions, typename Transformation::Type>::CachedTransformations cached; |
||||
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType |
||||
matrix, invertedMatrix; |
||||
|
||||
/* Clean all features */ |
||||
for(AbstractFeature<Transformation::Dimensions, typename Transformation::Type>* i = o->firstFeature(); i; i = i->nextFeature()) { |
||||
/* Cached absolute transformation, compute it if it wasn't
|
||||
computed already */ |
||||
if(i->cachedTransformations() & CachedTransformation::Absolute) { |
||||
if(!(cached & CachedTransformation::Absolute)) { |
||||
cached |= CachedTransformation::Absolute; |
||||
matrix = Transformation::toMatrix(absoluteTransformation); |
||||
} |
||||
|
||||
i->clean(matrix); |
||||
} |
||||
|
||||
/* Cached inverse absolute transformation, compute it if it wasn't
|
||||
computed already */ |
||||
if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) { |
||||
if(!(cached & CachedTransformation::InvertedAbsolute)) { |
||||
cached |= CachedTransformation::InvertedAbsolute; |
||||
invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation)); |
||||
} |
||||
|
||||
i->cleanInverted(invertedMatrix); |
||||
} |
||||
} |
||||
|
||||
/* Mark object as clean */ |
||||
o->flags &= ~Flag::Dirty; |
||||
} |
||||
} |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -1,3 +1,2 @@
|
||||
corrade_add_test2(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphTestLib) |
||||
corrade_add_test2(SceneGraphCameraTest CameraTest.cpp LIBRARIES MagnumSceneGraph) |
||||
corrade_add_test2(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph) |
||||
|
||||
Loading…
Reference in new issue