Browse Source

SceneGraph: there is never enough documentation.

pull/87/head
Vladimír Vondruš 11 years ago
parent
commit
9fd25a1fd8
  1. 217
      doc/scenegraph.dox
  2. 2
      src/Magnum/AbstractFramebuffer.cpp
  3. 58
      src/Magnum/SceneGraph/AbstractFeature.h
  4. 10
      src/Magnum/SceneGraph/AbstractObject.h
  5. 3
      src/Magnum/SceneGraph/AbstractTransformation.h
  6. 8
      src/Magnum/SceneGraph/AbstractTranslation.h
  7. 4
      src/Magnum/SceneGraph/AbstractTranslationRotation2D.h
  8. 4
      src/Magnum/SceneGraph/AbstractTranslationRotation3D.h
  9. 4
      src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h
  10. 4
      src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h
  11. 21
      src/Magnum/SceneGraph/Animable.h
  12. 8
      src/Magnum/SceneGraph/Camera2D.h
  13. 10
      src/Magnum/SceneGraph/Camera3D.h
  14. 77
      src/Magnum/SceneGraph/Drawable.h
  15. 2
      src/Magnum/SceneGraph/DualComplexTransformation.h
  16. 2
      src/Magnum/SceneGraph/DualQuaternionTransformation.h
  17. 2
      src/Magnum/SceneGraph/MatrixTransformation2D.h
  18. 3
      src/Magnum/SceneGraph/MatrixTransformation3D.h
  19. 5
      src/Magnum/SceneGraph/Object.h
  20. 2
      src/Magnum/SceneGraph/RigidMatrixTransformation2D.h
  21. 3
      src/Magnum/SceneGraph/RigidMatrixTransformation3D.h
  22. 10
      src/Magnum/SceneGraph/TranslationTransformation.h

217
doc/scenegraph.dox

@ -56,41 +56,83 @@ three main components:
@section scenegraph-transformation Transformations
Transformation handles object position, rotation etc. and its basic property
is dimension count (2D or 3D) and underlying floating-point type.
is dimension count (2D or 3D) and underlying floating-point type. All classes
in @ref SceneGraph are templated on underlying type. However, in most cases
@ref Float "Float" is used and thus nearly all classes have convenience aliases
so you don't have to explicitly specify it.
Scene graph has various transformation implementations for both 2D and 3D. Each
implementation has its own advantages and disadvantages -- for example when
using matrices you can have nearly arbitrary transformations, but composing
transformations, computing their inverse and accounting for floating-point
drift is rather costly operation. On the other hand quaternions won't allow you
to scale or shear objects, but have far better performance characteristics.
@note All classes in @ref SceneGraph are templated on underlying type. However,
in most cases @ref Float "Float" is used and thus nearly all classes have
convenience aliases so you don't have to explicitly specify it.
It's also possible to implement your own transformation class for specific
needs, see source of builtin transformation classes for more information.
Magnum provides the following transformation classes. See documentation of each
class for more detailed information:
- @ref SceneGraph::BasicMatrixTransformation2D "SceneGraph::MatrixTransformation2D" --
arbitrary 2D transformations but with slow inverse transformations and no
floating-point drift reduction
- @ref SceneGraph::BasicMatrixTransformation3D "SceneGraph::MatrixTransformation3D" --
arbitrary 3D transformations but with slow inverse transformations and no
floating-point drift reduction
- @ref SceneGraph::BasicRigidMatrixTransformation2D "SceneGraph::RigidMatrixTransformation2D" --
2D translation, rotation and reflection (no scaling), with relatively fast
inverse transformations and floating-point drift reduction
- @ref SceneGraph::BasicRigidMatrixTransformation3D "SceneGraph::RigidMatrixTransformation3D" --
3D translation, rotation and reflection (no scaling), with relatively fast
inverse transformations and floating-point drift reduction
- @ref SceneGraph::BasicDualComplexTransformation "SceneGraph::DualComplexTransformation" --
2D translation and rotation with fast inverse transformations and
floating-point drift reduction
- @ref SceneGraph::BasicDualQuaternionTransformation "SceneGraph::DualQuaternionTransformation" --
3D translation and rotation with fast inverse transformation and
floating-point drift reduction
- @ref SceneGraph::TranslationTransformation "SceneGraph::TranslationTransformation*D" --
Just 2D/3D translation (no rotation, scaling or anything else)
Common usage of transformation classes is to typedef Scene and Object with
desired transformation type to save unnecessary typing later:
@code
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
@endcode
Scene graph has implementation of transformations in both 2D and 3D, using
either matrices or combination of position and rotation. Each implementation
has its own advantages and disadvantages -- for example when using matrices
you can have nearly arbitrary transformations, but composing transformations
and computing their inverse is costly operation. On the other hand quaternions
won't allow you to scale or shear objects, but are more memory efficient than
matrices.
@attention Note that you have to include both @ref Magnum/SceneGraph/Object.h
and desired transformation class (e.g. @ref Magnum/SceneGraph/MatrixTransformation3D.h)
to be able to use the resulting type.
It's also possible to implement your own transformation class for specific
needs, see source of other transformation classes for more information.
The object type is subclassed from the transformation type and so the
`Object3D` type will then contain all members from both @ref SceneGraph::Object
and @ref SceneGraph::MatrixTransformation3D. For convenience you can use method
chaining:
@code
Scene3D scene;
Object3D object;
object.setParent(&scene)
.rotateY(15.0_degf)
.translate(Vector3::xAxis(5.0f));
@endcode
@section scenegraph-hierarchy Scene hierarchy
Scene hierarchy is skeleton part of scene graph. In the root there is
@ref SceneGraph::Scene and its children are @ref SceneGraph::Object instances.
The hierarchy has some transformation type, identical for all objects (because
Whole hierarchy has one transformation type, identical for all objects (because
for example having part of the tree in 2D and part in 3D just wouldn't make
sense). Common usage is to typedef Scene and Object with desired transformation
type to save unnecessary typing later:
@code
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
@endcode
sense).
Then you can start building the hierarchy by *parenting* one object to another.
Parent object can be either passed in constructor or using
Parent object can be either passed in constructor or set using
@ref SceneGraph::Object::setParent(). Scene is always root object, so it
naturally cannot have parent object. List of object children can be accessed
through @ref SceneGraph::Object::children().
naturally cannot have parent object. Parent and children relationships can be
observed through @ref SceneGraph::Object::parent() and
@ref SceneGraph::Object::children().
@code
Scene3D scene;
@ -98,52 +140,62 @@ auto first = new Object3D(&scene);
auto second = new Object3D(first);
@endcode
The hierarchy takes care of memory management - when an object is destroyed,
The hierarchy takes care of memory management -- when an object is destroyed,
all its children are destroyed too. See detailed explanation of
@ref scenegraph-object-construction-order "construction and destruction order"
for information about possible issues.
The object is derived from the transformation you specified earlier in the
`typedef`, so you can directly transform the objects using methods of given
transformation implementation. Scene, as a root object, cannot have any
transformation. For convenience you can use method chaining:
@code
auto next = new Object3D;
next->setParent(another)
.translate(Vector3::yAxis(3.0f))
.rotateY(35.0_degf);
@endcode
below for information about possible issues.
@section scenegraph-features Object features
The object itself handles only parent/child relationship and transformation.
To make the object renderable, animatable, add collision shape to it etc., you
To make the object renderable, animable, add collision shape to it etc., you
have to add a *feature* to it.
Each feature takes reference to holder object in constructor, so adding a
feature to an object might look just like this, as in some cases you don't even
need to keep the pointer to it. List of object features is accessible through
@ref SceneGraph::Object::features().
Magnum provides the following builtin features. See documentation of each class
for more detailed information and usage examples:
- @ref SceneGraph::AbstractCamera "SceneGraph::Camera*D" -- Handles
projection matrix, aspect ratio correction etc.. Used for rendering parts
of the scene.
- @ref SceneGraph::Drawable "SceneGraph::Drawable*D" -- Adds drawing
functionality to given object. Group of drawables can be then rendered
using the camera feature.
- @ref SceneGraph::Animable "SceneGraph::Animable*D" -- Adds animation
functionality to given object. Group of animables can be then controlled
using @ref SceneGraph::AnimableGroup "SceneGraph::AnimableGroup*D".
- @ref Shapes::Shape -- Adds collision shape to given object. Group of shapes
can be then controlled using @ref Shapes::ShapeGroup "Shapes::ShapeGroup*D".
See @ref shapes for more information.
- @ref DebugTools::ObjectRenderer "DebugTools::ObjectRenderer*D",
@ref DebugTools::ShapeRenderer "DebugTools::ShapeRenderer*D",
@ref DebugTools::ForceRenderer "DebugTools::ForceRenderer*D" -- Visualize
object properties, object shape or force vector for debugging purposes. See
@ref debug-tools for more information.
Each feature takes reference to *holder object* in constructor, so adding a
feature to an object might look just like the following, as in some cases you
don't even need to keep the pointer to it. List of object features is
accessible through @ref SceneGraph::Object::features().
@code
Object3D* o;
new MyFeature(o);
new MyFeature{*o};
@endcode
Some features are passive, some active. Passive features can be just added to
an object like above, without any additional work (for example collision
shape). Active features require the user to implement some virtual function
(for example to draw the object on screen or perform animation step). To make
things convenient, features can be added directly to object itself using
multiple inheritance, so you can conveniently add all the active features you
want and implement needed functions in your own @ref SceneGraph::Object
an object, with no additional work except for possible configuration (for
example collision shape). Active features require the user to implement some
virtual function (for example to draw the object on screen or perform animation
step). To make things convenient, features can be added directly to object
itself using multiple inheritance, so you can conveniently add all the active
features you want and implement needed functions in your own @ref SceneGraph::Object
subclass without having to subclass each feature individually (and making the
code overly verbose). Simplified example:
@code
class Bomb: public Object3D, SceneGraph::Drawable3D, SceneGraph::Animable3D {
class BouncingBall: public Object3D, SceneGraph::Drawable3D, SceneGraph::Animable3D {
public:
Bomb(Object3D* parent): Object3D(parent), SceneGraph::Drawable3D(*this), SceneGraph::Animable3D(*this) {}
explicit BouncingBall(Object3D* parent): Object3D{parent}, SceneGraph::Drawable3D{*this}, SceneGraph::Animable3D{*this} {}
protected:
private:
// drawing implementation for Drawable feature
void draw(...) override;
@ -161,15 +213,15 @@ member and inherited) are destroyed. See detailed explanation of
@ref scenegraph-feature-construction-order "construction and destruction order"
for information about possible issues.
@section scenegraph-caching Transformation caching
@subsection scenegraph-features-caching Transformation caching in features
Some features need to operate with absolute transformations and their
inversions - for example camera needs its inverse transformation to render the
inversions -- for example camera needs its inverse transformation to render the
scene, collision detection needs to know about positions of surrounding
objects etc. To avoid computing the transformations from scratch every time,
the feature can cache them.
The cached data stay until the object is marked as dirty - that is by changing
The cached data stay until the object is marked as dirty -- that is by changing
transformation, changing parent or explicitly calling @ref SceneGraph::Object::setDirty().
If the object is marked as dirty, all its children are marked as dirty too and
@ref SceneGraph::AbstractFeature::markDirty() is called on every feature.
@ -189,17 +241,17 @@ and then implement corresponding cleaning function(s):
@code
class CachingObject: public Object3D, SceneGraph::AbstractFeature3D {
public:
CachingObject(Object3D* parent): SceneGraph::AbstractFeature3D(*this) {
explicit CachingObject(Object3D* parent): Object3D{parent}, SceneGraph::AbstractFeature3D{*this} {
setCachedTransformations(SceneGraph::CachedTransformation::Absolute);
}
protected:
void clean(const Matrix4& absoluteTransformation) override {
absolutePosition = absoluteTransformation.translation();
_absolutePosition = absoluteTransformation.translation();
}
private:
Vector3 absolutePosition;
Vector3 _absolutePosition;
};
@endcode
@ -208,7 +260,56 @@ by calling @ref SceneGraph::Object::setClean(). @ref SceneGraph::Camera3D "Camer
for example, calls it automatically before it starts rendering, as it needs its
own inverse transformation to properly draw the objects.
See @ref SceneGraph-AbstractFeature-subclassing-caching for more information.
@subsection scenegraph-features-transformation Polymorphic access to object transformation
Features by default have access only to @ref SceneGraph::AbstractObject, which
doesn't know about any particular transformation implementation. This has the
advantage that features don't have to be implemented for all possible
transformation implementations. But, as a consequence, it is impossible to
transform the object using only pointer to @ref SceneGraph::AbstractObject.
To solve this, the transformation classes are subclassed from interfaces
sharing common functionality, so the feature can use that interface instead of
being specialized for all relevant transformation implementations. The
following interfaces are available, each having its own set of virtual
functions to control the transformation:
- @ref SceneGraph::AbstractTransformation "SceneGraph::AbstractTransformation*D" --
base for all transformations
- @ref SceneGraph::AbstractTranslation "SceneGraph::AbstractTranslation*D" --
base for all transformations providing translation
- @ref SceneGraph::AbstractBasicTranslationRotation2D "SceneGraph::AbstractTranslationRotation2D",
@ref SceneGraph::AbstractBasicTranslationRotation3D "SceneGraph::AbstractTranslationRotation3D" --
base for all transformations providing translation and rotation
- @ref SceneGraph::AbstractBasicTranslationRotationScaling2D "SceneGraph::AbstractBasicTranslationRotationScaling2D",
@ref SceneGraph::AbstractBasicTranslationRotationScaling3D "SceneGraph::AbstractBasicTranslationRotationScaling3D" --
base for all transformations providing translation, rotation and scaling
These interfaces provide virtual functions which can be used to modify object
transformations. The virtual calls are used only when calling through the
interface and not when using the concrete implementation directly to avoid
negative performance effects. There are no functions to retrieve object
transformation, you need to use the above transformation caching mechanism for
that.
In the following example we are able to get pointer to both
@ref SceneGraph::AbstractObject and needed transformation from one
constructor parameter using small trick:
@code
class TransformingFeature: public SceneGraph::AbstractFeature3D {
public:
template<class T> TransformingFeature(SceneGraph::Object<T>& object):
SceneGraph::AbstractFeature3D(object), transformation(object) {}
private:
SceneGraph::AbstractTranslationRotation3D& transformation;
};
@endcode
If we take for example @ref SceneGraph::Object "SceneGraph::Object<MatrixTransformation3D>",
it is derived from @ref SceneGraph::AbstractObject "SceneGraph::AbstractObject3D"
and @ref SceneGraph::BasicMatrixTransformation3D "SceneGraph::MatrixTransformation3D",
thus the reference to @ref SceneGraph::AbstractBasicTranslationRotation3D "SceneGraph::AbstractTranslationRotation3D",
is automatically extracted from the reference in our constructor.
@section scenegraph-construction-order Construction and destruction order

2
src/Magnum/AbstractFramebuffer.cpp

@ -224,7 +224,7 @@ void AbstractFramebuffer::setViewportInternal() {
glViewport(_viewport.left(), _viewport.bottom(), _viewport.sizeX(), _viewport.sizeY());
}
AbstractFramebuffer& AbstractFramebuffer::clear(FramebufferClearMask mask) {
AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else

58
src/Magnum/SceneGraph/AbstractFeature.h

@ -40,7 +40,7 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Which transformation to cache in given feature
@see @ref scenegraph-caching, @ref CachedTransformations,
@see @ref scenegraph-features-caching, @ref CachedTransformations,
@ref AbstractFeature::setCachedTransformations(), @ref AbstractFeature::clean(),
@ref AbstractFeature::cleanInverted()
@todo Provide also simpler representations from which could benefit
@ -68,7 +68,7 @@ enum class CachedTransformation: UnsignedByte {
/**
@brief Which transformations to cache in this feature
@see @ref scenegraph-caching, @ref AbstractFeature::setCachedTransformations(),
@see @ref scenegraph-features-caching, @ref AbstractFeature::setCachedTransformations(),
@ref AbstractFeature::clean(), @ref AbstractFeature::cleanInverted()
*/
typedef Containers::EnumSet<CachedTransformation> CachedTransformations;
@ -90,12 +90,11 @@ 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.
@anchor SceneGraph-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.
@ref scenegraph-features-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 @ref setCachedTransformations()
@ -104,17 +103,16 @@ and then implement corresponding cleaning function(s) -- either @ref clean(),
@code
class CachingFeature: public SceneGraph::AbstractFeature3D {
public:
CachingFeature(SceneGraph::AbstractObject3D& object): SceneGraph::AbstractFeature3D(object) {
explicit CachingFeature(SceneGraph::AbstractObject3D& object): SceneGraph::AbstractFeature3D{object} {
setCachedTransformations(CachedTransformation::Absolute);
}
protected:
private:
void clean(const Matrix4& absoluteTransformationMatrix) override {
absolutePosition = absoluteTransformationMatrix.translation();
_absolutePosition = absoluteTransformationMatrix.translation();
}
private:
Vector3 absolutePosition;
Vector3 _absolutePosition;
};
@endcode
@ -123,33 +121,22 @@ Before using the cached value explicitly request object cleaning by calling
### Accessing object transformation
Features has by default access only to @ref AbstractObject, which is base of
@ref 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 @ref 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 @ref AbstractObject and needed transformation from one constructor
parameter:
The feature has by default only access to @ref AbstractObject, which doesn't
know about any used transformation. By using small template trick in the
constructor it is possible to gain access to transformation interface in the
constructor:
@code
class TransformingFeature: public SceneGraph::AbstractFeature3D {
public:
template<class T> TransformingFeature(SceneGraph::Object<T>& object):
SceneGraph::AbstractFeature3D(object), transformation(object) {}
template<class T> explicit TransformingFeature(SceneGraph::Object<T>& object):
SceneGraph::AbstractFeature3D{object}, _transformation{object} {}
private:
SceneGraph::AbstractTranslationRotation3D& transformation;
SceneGraph::AbstractTranslationRotation3D& _transformation;
};
@endcode
If we take for example @ref Object "Object<MatrixTransformation3D>", it is
derived from @ref AbstractObject "AbstractObject3D" and
@ref BasicMatrixTransformation3D "MatrixTransformation3D", which is derived
from @ref AbstractBasicTranslationRotationScaling3D "AbstractTranslationRotationScaling3D",
which is derived from @ref AbstractBasicTranslationRotation3D "AbstractTranslationRotation3D",
which is automatically extracted from the reference in our constructor.
See @ref scenegraph-features-transformation for more detailed information.
## Explicit template specializations
@ -222,13 +209,14 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
/**
* @{ @name Transformation caching
*
* See @ref scenegraph-caching for more information.
* See @ref scenegraph-features-caching for more information.
*/
/**
* @brief Which transformations are cached
*
* @see @ref scenegraph-caching, @ref clean(), @ref cleanInverted()
* @see @ref scenegraph-features-caching, @ref clean(),
* @ref cleanInverted()
*/
CachedTransformations cachedTransformations() const {
return _cachedTransformations;
@ -243,7 +231,7 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
* transformation.
*
* Nothing is enabled by default.
* @see @ref scenegraph-caching
* @see @ref scenegraph-features-caching
*/
void setCachedTransformations(CachedTransformations transformations) {
_cachedTransformations = transformations;
@ -257,7 +245,7 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
* done in @ref clean() and @ref cleanInverted().
*
* Default implementation does nothing.
* @see @ref scenegraph-caching
* @see @ref scenegraph-features-caching
*/
virtual void markDirty();
@ -269,7 +257,7 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
* to recalculate data based on absolute object transformation.
*
* Default implementation does nothing.
* @see @ref scenegraph-caching, @ref cleanInverted()
* @see @ref scenegraph-features-caching, @ref cleanInverted()
*/
virtual void clean(const MatrixTypeFor<dimensions, T>& absoluteTransformationMatrix);
@ -282,7 +270,7 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
* transformation.
*
* Default implementation does nothing.
* @see @ref scenegraph-caching, @ref clean()
* @see @ref scenegraph-features-caching, @ref clean()
*/
virtual void cleanInverted(const MatrixTypeFor<dimensions, T>& invertedAbsoluteTransformationMatrix);

10
src/Magnum/SceneGraph/AbstractObject.h

@ -212,7 +212,7 @@ template<UnsignedInt dimensions, class T> class AbstractObject
/**
* @{ @name Transformation caching
*
* See @ref scenegraph-caching for more information.
* See @ref scenegraph-features-caching for more information.
*/
/**
@ -251,7 +251,7 @@ template<UnsignedInt dimensions, class T> class AbstractObject
* Returns `true` if transformation of the object or any parent has
* changed since last call to @ref setClean(), `false` otherwise. All
* objects are dirty by default.
* @see @ref scenegraph-caching
* @see @ref scenegraph-features-caching
*/
bool isDirty() const { return doIsDirty(); }
@ -262,7 +262,8 @@ template<UnsignedInt dimensions, class T> class AbstractObject
* recursively calls @ref setDirty() on every child object which is not
* already dirty. If the object is already marked as dirty, the
* function does nothing.
* @see @ref scenegraph-caching, @ref setClean(), @ref isDirty()
* @see @ref scenegraph-features-caching, @ref setClean(),
* @ref isDirty()
*/
void setDirty() { doSetDirty(); }
@ -277,7 +278,8 @@ template<UnsignedInt dimensions, class T> class AbstractObject
* See also @ref setClean(const std::vector<AbstractObject<dimensions, T>*>&),
* which cleans given set of objects more efficiently than when calling
* @ref setClean() on each object individually.
* @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty()
* @see @ref scenegraph-features-caching, @ref setDirty(),
* @ref isDirty()
*/
void setClean() { doSetClean(); }

3
src/Magnum/SceneGraph/AbstractTransformation.h

@ -39,7 +39,8 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base for transformations
Provides transformation implementation for @ref Object instances.
Provides transformation implementation for @ref Object instances. See
@ref scenegraph-features-transformation for more information.
@anchor SceneGraph-AbstractTransformation-explicit-specializations
## Explicit template specializations

8
src/Magnum/SceneGraph/AbstractTranslation.h

@ -38,13 +38,15 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for two-dimensional scenes supporting translation
See @ref scenegraph-features-transformation for more information.
By default the translation is stored with the same underlying type as resulting
transformation matrix, but it's possible to store translation in e.g. integral
coordinates while having floating-point transformation matrix.
@see @ref AbstractBasicTranslation2D, @ref AbstractBasicTranslation3D,
@ref AbstractTranslation2D, @ref AbstractTranslation3D, @ref scenegraph,
@ref TranslationTransformation
@see @ref scenegraph, @ref AbstractBasicTranslation2D,
@ref AbstractBasicTranslation3D, @ref AbstractTranslation2D,
@ref AbstractTranslation3D, @ref TranslationTransformation
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T, class TranslationType = T>

4
src/Magnum/SceneGraph/AbstractTranslationRotation2D.h

@ -36,7 +36,9 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for two-dimensional scenes supporting translation and rotation
@see @ref AbstractTranslationRotation2D, @ref scenegraph,
See @ref scenegraph-features-transformation for more information.
@see @ref scenegraph, @ref AbstractTranslationRotation2D,
@ref AbstractBasicTranslationRotation3D,
@ref BasicRigidMatrixTransformation2D, @ref BasicDualComplexTransformation
*/

4
src/Magnum/SceneGraph/AbstractTranslationRotation3D.h

@ -36,7 +36,9 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for three-dimensional scenes supporting translation and rotation
@see @ref AbstractTranslationRotation3D @ref scenegraph,
See @ref scenegraph-features-transformation for more information.
@see @ref scenegraph, @ref AbstractTranslationRotation3D,
@ref AbstractBasicTranslationRotation2D,
@ref BasicRigidMatrixTransformation3D,
@ref BasicDualQuaternionTransformation

4
src/Magnum/SceneGraph/AbstractTranslationRotationScaling2D.h

@ -36,7 +36,9 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for two-dimensional scenes supporting translation, rotation and scaling
@see @ref AbstractTranslationRotationScaling2D, @ref scenegraph,
See @ref scenegraph-features-transformation for more information.
@see @ref scenegraph, @ref AbstractTranslationRotationScaling2D,
@ref AbstractBasicTranslationRotationScaling2D,
@ref BasicMatrixTransformation2D
*/

4
src/Magnum/SceneGraph/AbstractTranslationRotationScaling3D.h

@ -36,7 +36,9 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for three-dimensional scenes supporting translation, rotation and scaling
@see @ref AbstractTranslationRotationScaling3D, @ref scenegraph,
See @ref scenegraph-features-transformation for more information.
@see @ref scenegraph, @ref AbstractTranslationRotationScaling3D,
@ref AbstractBasicTranslationRotationScaling2D,
@ref BasicMatrixTransformation3D
*/

21
src/Magnum/SceneGraph/Animable.h

@ -78,22 +78,25 @@ typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;
class AnimableObject: public Object3D, SceneGraph::Animable3D {
public:
AnimableObject(Object* parent = nullptr, SceneGraph::DrawableGroup3D* group = nullptr): Object3D(parent), SceneGraph::Animable3D(*this, group) {
AnimableObject(Object3D* parent = nullptr, SceneGraph::DrawableGroup3D* group = nullptr): Object3D{parent}, SceneGraph::Animable3D{*this, group} {
setDuration(10.0f);
// ...
}
private:
void animationStep(Float time, Float delta) override {
rotateX(15.0_degf*delta); // rotate at 15 degrees per second
}
}
@endcode
Then add the object to your scene and some animation group. You can also use
@ref AnimableGroup::add() and @ref AnimableGroup::remove() instead of passing
the group in the constructor. The animation is initially in stopped state and
without repeat, see @ref setState(), @ref setRepeated() and
@ref setRepeatCount() for more information.
Similarly to @ref Drawable feature, there is no way to just animate all the
objects in the scene. You need to create animable group and use it to control
given set of animations. You can also use @ref AnimableGroup::add() and
@ref AnimableGroup::remove() instead of passing the group in the constructor.
The animation is initially in stopped state and without repeat, see
@ref setState(), @ref setRepeated() and @ref setRepeatCount() for more
information.
@code
Scene3D scene;
SceneGraph::AnimableGroup3D animables;
@ -120,13 +123,13 @@ void MyApplication::drawEvent() {
}
@endcode
## Using animable groups to improve performance
## Using multiple animable groups to improve performance
@ref AnimableGroup is optimized for case when no animation is running -- it
just puts itself to rest and waits until some animation changes its state to
@ref AnimationState::Running again. If you put animations which are not
pernamently running to separate group, they will not be always traversed when
calling @ref AnimableGroup::step(), saving precious frame time.
pernamently running into separate group, they will not be traversed every time
the @ref AnimableGroup::step() gets called, saving precious frame time.
## Explicit template specializations

8
src/Magnum/SceneGraph/Camera2D.h

@ -36,11 +36,11 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Camera for two-dimensional scenes
See Drawable documentation for introduction. The camera by default displays
OpenGL unit cube `[(-1, -1, -1); (1, 1, 1)]` and doesn't do any aspect ratio
correction. Common setup example:
See @ref Drawable documentation for complete introduction. The camera by
default displays OpenGL unit cube `[(-1, -1, -1); (1, 1, 1)]` and doesn't do
any aspect ratio correction. Common setup example:
@code
SceneGraph::Camera2D camera(&cameraObject);
SceneGraph::Camera2D camera{&cameraObject};
camera.setProjection({4.0f/3.0f, 1.0f})
.setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend);
@endcode

10
src/Magnum/SceneGraph/Camera3D.h

@ -41,12 +41,12 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Camera for three-dimensional scenes
See Drawable documentation for introduction. The camera by default displays
OpenGL unit cube `[(-1, -1, -1); (1, 1, 1)]` with orthographic projection and
doesn't do any aspect ratio correction. Common setup example:
See @ref Drawable documentation for complete introduction. The camera by
default displays OpenGL unit cube `[(-1, -1, -1); (1, 1, 1)]` with orthographic
projection and doesn't do any aspect ratio correction. Common setup example:
@code
SceneGraph::Camera3D camera(&cameraObject);
camera.setPerspective({}, 0.001f, 100.0f)
SceneGraph::Camera3D camera{&cameraObject};
camera.setPerspective(35.0_degf, 1.0f, 0.001f, 100.0f)
.setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend);
@endcode

77
src/Magnum/SceneGraph/Drawable.h

@ -36,62 +36,94 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Drawable
Adds drawing function to the object. Each Drawable is part of some
@ref DrawableGroup and the whole group is drawn with particular camera using
@ref AbstractCamera::draw().
Adds drawing functionality to the object. Each Drawable is part of some
@ref DrawableGroup and the whole group can be drawn with particular camera
using @ref AbstractCamera::draw().
## Usage
First thing is to add @ref Drawable feature to some object and implement
@ref draw(). You can do it conveniently using multiple inheritance (see
@ref scenegraph-features for introduction). Example:
@ref draw() function. You can do it conveniently using multiple inheritance
(see @ref scenegraph-features for introduction). Example drawable object that
draws blue sphere:
@code
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;
class DrawableObject: public Object3D, SceneGraph::Drawable3D {
class RedCube: public Object3D, SceneGraph::Drawable3D {
public:
DrawableObject(Object* parent = nullptr, SceneGraph::DrawableGroup3D* group = nullptr): Object3D(parent), SceneGraph::Drawable3D(*this, group) {
// ...
RedCube(Object3D* parent, SceneGraph::DrawableGroup3D* group): Object3D{parent}, SceneGraph::Drawable3D{*this, group} {
std::tie(_mesh, _vertices, _indices) = MeshTools::compile(Primitives::UVSPhere::solid(16, 32));
}
private:
void draw(const Matrix4& transformationMatrix, AbstractCamera3D& camera) override {
// ...
_shader.setDiffuseColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f))
.setLightPosition({5.0f, 5.0f, 7.0f})
.setTransformationMatrix(transformationMatrix)
.setNormalMatrix(transformationMatrix.rotation())
.setProjectionMatrix(camera.projectionMatrix());
_mesh.draw(_shader);
}
Mesh _mesh;
std::unique_ptr<Buffer> _vertices, _indices;
Shaders::Phong _shader;
}
@endcode
Then you add these objects to your scene and some drawable group and transform
them as you like. You can also use @ref DrawableGroup::add() and
@ref DrawableGroup::remove().
The @p transformationMatrix parameter in @ref draw() function contains
transformation of the object (to which the drawable is attached) relative to
@p camera. The camera contains projection matrix. Some shaders (like the
@ref Shaders::Phong used in the example) have separate functions for setting
transformation and projection matrix, but some (such as @ref Shaders::Flat)
have single function to set composite transformation and projection matrix. In
that case you need to combine the two matrices manually like in the following
code. Some shaders have additional requirements for various transformation
matrices, see their respective documentation for details.
@code
Shaders::Flat3D shader;
shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix);
@endcode
There is no way to just draw all the drawables in the scene, you need to create
some drawable group and add the drawable objects to both the scene and the
group. You can also use @ref DrawableGroup::add() and
@ref DrawableGroup::remove() instead of passing the group in the constructor.
@code
Scene3D scene;
SceneGraph::DrawableGroup3D drawables;
(new DrawableObject(&scene, &drawables))
(new RedCube(&scene, &drawables))
->translate(Vector3::yAxis(-0.3f))
.rotateX(30.0_degf);
(new AnotherDrawableObject(&scene, &drawables))
->translate(Vector3::zAxis(0.5f));
// ...
@endcode
The last thing you need is camera attached to some object (thus using its
transformation) and with it you can perform drawing in your draw event
transformation). Using the camera and the drawable group you can perform
drawing in your @ref Platform::Sdl2Application::drawEvent() "drawEvent()"
implementation. See @ref Camera2D and @ref Camera3D documentation for more
information.
@code
Camera3D camera(&cameraObject);
auto cameraObject = new Object3D(&scene);
cameraObject->translate(Vector3::zAxis(5.0f));
auto camera = new SceneGraph::Camera3D(&cameraObject);
camera->setPerspective(35.0_degf, 1.0f, 0.001f, 100.0f);
// ...
void MyApplication::drawEvent() {
camera.draw(drawables);
camera->draw(drawables);
swapBuffers();
// ...
swapBuffers();
}
@endcode
## Using drawable groups to improve performance
## Using multiple drawable groups to improve performance
You can organize your drawables to multiple groups to minimize OpenGL state
changes -- for example put all objects using the same shader, the same light
@ -158,9 +190,8 @@ template<UnsignedInt dimensions, class T> class Drawable: public AbstractGrouped
/**
* @brief Draw the object using given camera
* @param transformationMatrix Object transformation relative
* to camera
* @param camera Camera
* @param transformationMatrix Object transformation relative to camera
* @param camera Camera
*
* Projection matrix can be retrieved from
* @ref SceneGraph::AbstractCamera::projectionMatrix() "AbstractCamera::projectionMatrix()".

2
src/Magnum/SceneGraph/DualComplexTransformation.h

@ -40,7 +40,7 @@ namespace Magnum { namespace SceneGraph {
This class allows only rigid transformation (i.e. only rotation and
translation). Uses @ref Math::DualComplex as underlying transformation type.
@see @ref DualComplexTransformation, @ref scenegraph,
@see @ref scenegraph, @ref DualComplexTransformation,
@ref BasicDualQuaternionTransformation
*/
template<class T> class BasicDualComplexTransformation: public AbstractBasicTranslationRotation2D<T> {

2
src/Magnum/SceneGraph/DualQuaternionTransformation.h

@ -40,7 +40,7 @@ namespace Magnum { namespace SceneGraph {
This class allows only rigid transformation (i.e. only rotation and
translation). Uses @ref Math::DualQuaternion as underlying transformation type.
@see @ref DualQuaternionTransformation @ref scenegraph,
@see @ref scenegraph, @ref DualQuaternionTransformation,
@ref BasicDualComplexTransformation
*/
template<class T> class BasicDualQuaternionTransformation: public AbstractBasicTranslationRotation3D<T> {

2
src/Magnum/SceneGraph/MatrixTransformation2D.h

@ -39,7 +39,7 @@ namespace Magnum { namespace SceneGraph {
@brief Two-dimensional transformation implemented using matrices
Uses @ref Math::Matrix3 as underlying transformation type.
@see @ref MatrixTransformation2D, @ref scenegraph,
@see @ref scenegraph, @ref MatrixTransformation2D,
@ref BasicRigidMatrixTransformation2D, @ref BasicMatrixTransformation3D
*/
template<class T> class BasicMatrixTransformation2D: public AbstractBasicTranslationRotationScaling2D<T> {

3
src/Magnum/SceneGraph/MatrixTransformation3D.h

@ -39,7 +39,8 @@ namespace Magnum { namespace SceneGraph {
@brief Three-dimensional transformation implemented using matrices
Uses @ref Math::Matrix4 as underlying transformation type.
@see @ref MatrixTransformation3D, @ref scenegraph, @ref BasicRigidMatrixTransformation3D, @ref BasicMatrixTransformation2D
@see @ref scenegraph, @ref MatrixTransformation3D,
@ref BasicRigidMatrixTransformation3D, @ref BasicMatrixTransformation2D
*/
template<class T> class BasicMatrixTransformation3D: public AbstractBasicTranslationRotationScaling3D<T> {
public:

5
src/Magnum/SceneGraph/Object.h

@ -335,7 +335,7 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
/**
* @{ @name Transformation caching
*
* See @ref scenegraph-caching for more information.
* See @ref scenegraph-features-caching for more information.
*/
/**
@ -381,7 +381,8 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
* See also @ref setClean(std::vector<std::reference_wrapper<Object<Transformation>>>),
* which cleans given set of objects more efficiently than when calling
* @ref setClean() on each object individually.
* @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty()
* @see @ref scenegraph-features-caching, @ref setDirty(),
* @ref isDirty()
*/
/* note: doc verbatim copied from AbstractObject::setClean() */
void setClean();

2
src/Magnum/SceneGraph/RigidMatrixTransformation2D.h

@ -43,7 +43,7 @@ Unlike @ref BasicMatrixTransformation2D this class allows only rotation,
reflection and translation (no scaling or setting arbitrary transformations).
This allows to use @ref Math::Matrix3::invertedRigid() for faster computation
of inverse transformations.
@see @ref RigidMatrixTransformation2D, @ref scenegraph,
@see @ref scenegraph, @ref RigidMatrixTransformation2D,
@ref BasicRigidMatrixTransformation3D
*/
template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTranslationRotation2D<T> {

3
src/Magnum/SceneGraph/RigidMatrixTransformation3D.h

@ -43,7 +43,8 @@ Unlike @ref BasicMatrixTransformation3D this class allows only rotation,
reflection and translation (no scaling or setting arbitrary transformations).
This allows to use @ref Math::Matrix4::invertedRigid() for faster computation
of inverse transformations.
@see @ref RigidMatrixTransformation3D, @ref scenegraph, @ref BasicRigidMatrixTransformation2D
@see @ref scenegraph, @ref RigidMatrixTransformation3D,
@ref BasicRigidMatrixTransformation2D
*/
template<class T> class BasicRigidMatrixTransformation3D: public AbstractBasicTranslationRotation3D<T> {
public:

10
src/Magnum/SceneGraph/TranslationTransformation.h

@ -44,13 +44,9 @@ the translation is stored with the same underlying type as resulting
transformation matrix, but it's possible to store translation in e.g. integral
coordinates while having floating-point transformation matrix.
Note that translation is commutative, so all @ref TransformationType parameters
have no effect and are included only for compatibility with other
transformation implementations.
@see @ref BasicTranslationTransformation2D, @ref BasicTranslationTransformation3D,
@ref TranslationTransformation2D, @ref TranslationTransformation3D,
@ref scenegraph
@see @ref scenegraph, @ref BasicTranslationTransformation2D,
@ref BasicTranslationTransformation3D, @ref TranslationTransformation2D,
@ref TranslationTransformation3D
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T, class TranslationType = T>

Loading…
Cancel
Save