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
*
* 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);
}
/*@}*/
@ -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;

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
*
* 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
@ -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(); }

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;
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]);
@ -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 */
@ -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 */
@ -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
@ -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 {

Loading…
Cancel
Save