Browse Source

SceneGraph: clarify transformation calculation.

pull/388/head
Vladimír Vondruš 7 years ago
parent
commit
8c7c2c5745
  1. 12
      src/Magnum/SceneGraph/AbstractObject.h
  2. 20
      src/Magnum/SceneGraph/Object.h
  3. 20
      src/Magnum/SceneGraph/Object.hpp

12
src/Magnum/SceneGraph/AbstractObject.h

@ -162,14 +162,16 @@ template<UnsignedInt dimensions, class T> class AbstractObject
/** /**
* @brief Transformation matrices of given set of objects relative to this object * @brief Transformation matrices of given set of objects relative to this object
* *
* All transformations are premultiplied with @p initialTransformationMatrix, * All transformations are post-multiplied with
* if specified. * @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 * @warning This function cannot check if all objects are of the same
* @ref Object type, use typesafe @ref Object::transformationMatrices() * @ref Object type, use typesafe @ref Object::transformationMatrices()
* when possible. * when possible.
*/ */
std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { std::vector<MatrixType> transformationMatrices(const std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>>& objects, const MatrixType& finalTransformationMatrix = MatrixType()) const {
return doTransformationMatrices(objects, initialTransformationMatrix); return doTransformationMatrices(objects, finalTransformationMatrix);
} }
/*@}*/ /*@}*/
@ -248,7 +250,7 @@ template<UnsignedInt dimensions, class T> class AbstractObject
virtual MatrixType doTransformationMatrix() const = 0; virtual MatrixType doTransformationMatrix() const = 0;
virtual MatrixType doAbsoluteTransformationMatrix() 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 bool doIsDirty() const = 0;
virtual void doSetDirty() = 0; virtual void doSetDirty() = 0;

20
src/Magnum/SceneGraph/Object.h

@ -248,22 +248,26 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
/** /**
* @brief Transformation matrices of given set of objects relative to this object * @brief Transformation matrices of given set of objects relative to this object
* *
* All transformations are premultiplied with @p initialTransformationMatrix, * All transformations are post-multiplied with
* if specified. * @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() * @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 * @brief Transformations of given group of objects relative to this object
* *
* All transformations can be premultiplied with @p initialTransformation, * All transformations are post-multiplied with
* if specified. * @p finalTransformation, if specified (it gets applied on the
* left-most side, suitable for example for an inverse camera
* transformation).
* @see @ref transformationMatrices() * @see @ref transformationMatrices()
*/ */
/* `objects` passed by copy intentionally (to allow move from /* `objects` passed by copy intentionally (to allow move from
transformationMatrices() and avoid copy in the function itself) */ 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 */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* I hate this inconsistency */
typename Transformation::DataType() typename Transformation::DataType()
#else #else
@ -346,9 +350,9 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
return absoluteTransformationMatrix(); 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(); } bool MAGNUM_SCENEGRAPH_LOCAL doIsDirty() const override final { return isDirty(); }
void MAGNUM_SCENEGRAPH_LOCAL doSetDirty() override final { setDirty(); } void MAGNUM_SCENEGRAPH_LOCAL doSetDirty() override final { setDirty(); }

20
src/Magnum/SceneGraph/Object.hpp

@ -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; std::vector<std::reference_wrapper<Object<Transformation>>> castObjects;
castObjects.reserve(objects.size()); castObjects.reserve(objects.size());
/** @todo Ensure this doesn't crash, somehow */ /** @todo Ensure this doesn't crash, somehow */
for(auto o: objects) castObjects.push_back(static_cast<Object<Transformation>&>(o.get())); 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> { 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(initialTransformationMatrix)); std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Implementation::Transformation<Transformation>::fromMatrix(finalTransformationMatrix));
std::vector<MatrixType> transformationMatrices(transformations.size()); std::vector<MatrixType> transformationMatrices(transformations.size());
for(std::size_t i = 0; i != objects.size(); ++i) for(std::size_t i = 0; i != objects.size(); ++i)
transformationMatrices[i] = Implementation::Transformation<Transformation>::toMatrix(transformations[i]); transformationMatrices[i] = Implementation::Transformation<Transformation>::toMatrix(transformations[i]);
@ -202,7 +202,7 @@ Then for all joints their transformation (relative to parent joint) is
computed and recursively concatenated together. Resulting transformations for computed and recursively concatenated together. Resulting transformations for
joints which were originally in `object` list is then returned. 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", {}); CORRADE_ASSERT(objects.size() < 0xFFFFu, "SceneGraph::Object::transformations(): too large scene", {});
/* Remember object count for later */ /* Remember object count for later */
@ -274,7 +274,7 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
/* Compute transformations for all joints */ /* Compute transformations for all joints */
for(std::size_t i = 0; i != jointTransformations.size(); ++i) 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 /* Copy transformation for second or next occurences from first occurence
of duplicate object */ of duplicate object */
@ -297,7 +297,7 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
return jointTransformations; 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]; std::reference_wrapper<Object<Transformation>> o = jointObjects[joint];
/* Transformation already computed ("unvisited" by this function before /* Transformation already computed ("unvisited" by this function before
@ -315,16 +315,16 @@ template<class Transformation> typename Transformation::DataType Object<Transfor
Object<Transformation>* parent = o.get().parent(); Object<Transformation>* parent = o.get().parent();
/* Root object, compose transformation with initial, done */ /* Root object, compose transformation with final, done */
if(!parent) { if(!parent) {
CORRADE_INTERNAL_ASSERT(o.get().isScene()); CORRADE_INTERNAL_ASSERT(o.get().isScene());
return (jointTransformations[joint] = 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 */ /* Joint object, compose transformation with the joint, done */
} else if(parent->flags & Flag::Joint) { } else if(parent->flags & Flag::Joint) {
return (jointTransformations[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 compose transformation with parent, go up the hierarchy */
} else { } else {

Loading…
Cancel
Save