Skip to content

Commit

Permalink
SceneGraph: clarify transformation calculation.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Oct 21, 2019
1 parent c1800d9 commit 8c7c2c5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 23 deletions.
12 changes: 7 additions & 5 deletions src/Magnum/SceneGraph/AbstractObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,16 @@ template<UnsignedInt dimensions, class T> class AbstractObject
/**
* @brief Transformation matrices of given set of objects relative to this object
*
* All transformations are premultiplied with @p initialTransformationMatrix,
* if specified.
* All transformations are post-multiplied with
* @p finalTransformationMatrix, if specified (it gets applied on the
* left-most side, suitable for example for an inverse camera
* transformation or a projection matrix).
* @warning This function cannot check if all objects are of the same
* @ref Object type, use typesafe @ref Object::transformationMatrices()
* when possible.
*/
std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const {
return doTransformationMatrices(objects, initialTransformationMatrix);
std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& finalTransformationMatrix = MatrixType()) const {
return doTransformationMatrices(objects, finalTransformationMatrix);
}

/*@}*/
Expand Down Expand Up @@ -248,7 +250,7 @@ template<UnsignedInt dimensions, class T> class AbstractObject

virtual MatrixType doTransformationMatrix() const = 0;
virtual MatrixType doAbsoluteTransformationMatrix() const = 0;
virtual std::vector<MatrixType> doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& initialTransformationMatrix) const = 0;
virtual std::vector<MatrixType> doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& finalTransformationMatrix) const = 0;

virtual bool doIsDirty() const = 0;
virtual void doSetDirty() = 0;
Expand Down
20 changes: 12 additions & 8 deletions src/Magnum/SceneGraph/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,22 +248,26 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
/**
* @brief Transformation matrices of given set of objects relative to this object
*
* All transformations are premultiplied with @p initialTransformationMatrix,
* if specified.
* All transformations are post-multiplied with
* @p finalTransformationMatrix, if specified (it gets applied on the
* left-most side, suitable for example for an inverse camera
* transformation or a projection matrix).
* @see @ref transformations()
*/
std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<Object<Transformation>>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const;
std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<Object<Transformation>>>& objects, const MatrixType& finalTransformationMatrix = MatrixType()) const;

/**
* @brief Transformations of given group of objects relative to this object
*
* All transformations can be premultiplied with @p initialTransformation,
* if specified.
* All transformations are post-multiplied with
* @p finalTransformation, if specified (it gets applied on the
* left-most side, suitable for example for an inverse camera
* transformation).
* @see @ref transformationMatrices()
*/
/* `objects` passed by copy intentionally (to allow move from
transformationMatrices() and avoid copy in the function itself) */
std::vector<typename Transformation::DataType> transformations(std::vector<std::reference_wrapper<Object<Transformation>>> objects, const typename Transformation::DataType& initialTransformation =
std::vector<typename Transformation::DataType> transformations(std::vector<std::reference_wrapper<Object<Transformation>>> objects, const typename Transformation::DataType& finalTransformation =
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* I hate this inconsistency */
typename Transformation::DataType()
#else
Expand Down Expand Up @@ -346,9 +350,9 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
return absoluteTransformationMatrix();
}

std::vector<MatrixType> doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<Transformation::Dimensions, typename Transformation::Type>>>& objects, const MatrixType& initialTransformationMatrix) const override final;
std::vector<MatrixType> doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<Transformation::Dimensions, typename Transformation::Type>>>& objects, const MatrixType& finalTransformationMatrix) const override final;

typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector<std::reference_wrapper<Object<Transformation>>>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const;
typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector<std::reference_wrapper<Object<Transformation>>>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& finalTransformation) const;

bool MAGNUM_SCENEGRAPH_LOCAL doIsDirty() const override final { return isDirty(); }
void MAGNUM_SCENEGRAPH_LOCAL doSetDirty() override final { setDirty(); }
Expand Down
20 changes: 10 additions & 10 deletions src/Magnum/SceneGraph/Object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,17 @@ template<class Transformation> void Object<Transformation>::setClean() {
}
}

template<class Transformation> auto Object<Transformation>::doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<Transformation::Dimensions, typename Transformation::Type>>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector<MatrixType> {
template<class Transformation> auto Object<Transformation>::doTransformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<Transformation::Dimensions, typename Transformation::Type>>>& objects, const MatrixType& finalTransformationMatrix) const -> std::vector<MatrixType> {
std::vector<std::reference_wrapper<Object<Transformation>>> castObjects;
castObjects.reserve(objects.size());
/** @todo Ensure this doesn't crash, somehow */
for(auto o: objects) castObjects.push_back(static_cast<Object<Transformation>&>(o.get()));

return transformationMatrices(std::move(castObjects), initialTransformationMatrix);
return transformationMatrices(std::move(castObjects), finalTransformationMatrix);
}

template<class Transformation> auto Object<Transformation>::transformationMatrices(const std::vector<std::reference_wrapper<Object<Transformation>>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector<MatrixType> {
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Implementation::Transformation<Transformation>::fromMatrix(initialTransformationMatrix));
template<class Transformation> auto Object<Transformation>::transformationMatrices(const std::vector<std::reference_wrapper<Object<Transformation>>>& objects, const MatrixType& finalTransformationMatrix) const -> std::vector<MatrixType> {
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Implementation::Transformation<Transformation>::fromMatrix(finalTransformationMatrix));
std::vector<MatrixType> transformationMatrices(transformations.size());
for(std::size_t i = 0; i != objects.size(); ++i)
transformationMatrices[i] = Implementation::Transformation<Transformation>::toMatrix(transformations[i]);
Expand All @@ -202,7 +202,7 @@ Then for all joints their transformation (relative to parent joint) is
computed and recursively concatenated together. Resulting transformations for
joints which were originally in `object` list is then returned.
*/
template<class Transformation> std::vector<typename Transformation::DataType> Object<Transformation>::transformations(std::vector<std::reference_wrapper<Object<Transformation>>> objects, const typename Transformation::DataType& initialTransformation) const {
template<class Transformation> std::vector<typename Transformation::DataType> Object<Transformation>::transformations(std::vector<std::reference_wrapper<Object<Transformation>>> objects, const typename Transformation::DataType& finalTransformation) const {
CORRADE_ASSERT(objects.size() < 0xFFFFu, "SceneGraph::Object::transformations(): too large scene", {});

/* Remember object count for later */
Expand Down Expand Up @@ -274,7 +274,7 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob

/* Compute transformations for all joints */
for(std::size_t i = 0; i != jointTransformations.size(); ++i)
computeJointTransformation(jointObjects, jointTransformations, i, initialTransformation);
computeJointTransformation(jointObjects, jointTransformations, i, finalTransformation);

/* Copy transformation for second or next occurences from first occurence
of duplicate object */
Expand All @@ -297,7 +297,7 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
return jointTransformations;
}

template<class Transformation> typename Transformation::DataType Object<Transformation>::computeJointTransformation(const std::vector<std::reference_wrapper<Object<Transformation>>>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const {
template<class Transformation> typename Transformation::DataType Object<Transformation>::computeJointTransformation(const std::vector<std::reference_wrapper<Object<Transformation>>>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& finalTransformation) const {
std::reference_wrapper<Object<Transformation>> o = jointObjects[joint];

/* Transformation already computed ("unvisited" by this function before
Expand All @@ -315,16 +315,16 @@ template<class Transformation> typename Transformation::DataType Object<Transfor

Object<Transformation>* parent = o.get().parent();

/* Root object, compose transformation with initial, done */
/* Root object, compose transformation with final, done */
if(!parent) {
CORRADE_INTERNAL_ASSERT(o.get().isScene());
return (jointTransformations[joint] =
Implementation::Transformation<Transformation>::compose(initialTransformation, jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(finalTransformation, jointTransformations[joint]));

/* Joint object, compose transformation with the joint, done */
} else if(parent->flags & Flag::Joint) {
return (jointTransformations[joint] =
Implementation::Transformation<Transformation>::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, initialTransformation), jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, finalTransformation), jointTransformations[joint]));

/* Else compose transformation with parent, go up the hierarchy */
} else {
Expand Down

0 comments on commit 8c7c2c5

Please sign in to comment.