Browse Source

SceneTools: flattenTransformHierarchy*D() -> absoluteFieldTransform*D().

That's a second deprecation of this API in a short while, sorry. This
variant is hopefully the final one, with the previous one I still had
the problem that it contained a verb, which implied that it'd
*transform* the SceneData in some way which (unlike combineFields(),
filterFields() etc.) it didn't, it just extracts some data in a certain
way. This would all cause problems when there are APIs that actually do
perform hierarchy flattening.

It's also moved to a new, more general Hierarchy.h header which will
contain other hierarchy-related APIs. It doesn't make sense to have a
tiny header with just a single function, especially given it doesn't
depend on any heavy headers on its own.

Besides that it also makes the UnsignedInt overloads the main ones, and
the Trade::SceneField secondary, as is already done everywhere else (and
the opposite way was just bad inheritance from flattenMeshHierarchy()
it seems).
pull/620/head
Vladimír Vondruš 3 years ago
parent
commit
4a92ccfadd
  1. 14
      doc/snippets/MagnumSceneTools.cpp
  2. 2
      modules/FindMagnum.cmake
  3. 8
      src/Magnum/SceneTools/CMakeLists.txt
  4. 10
      src/Magnum/SceneTools/FlattenMeshHierarchy.cpp
  5. 26
      src/Magnum/SceneTools/FlattenMeshHierarchy.h
  6. 237
      src/Magnum/SceneTools/FlattenTransformationHierarchy.h
  7. 94
      src/Magnum/SceneTools/Hierarchy.cpp
  8. 237
      src/Magnum/SceneTools/Hierarchy.h
  9. 2
      src/Magnum/SceneTools/Test/CMakeLists.txt
  10. 14
      src/Magnum/SceneTools/Test/FlattenMeshHierarchyTest.cpp
  11. 146
      src/Magnum/SceneTools/Test/HierarchyTest.cpp
  12. 10
      src/Magnum/SceneTools/sceneconverter.cpp

14
doc/snippets/MagnumSceneTools.cpp

@ -32,7 +32,7 @@
#include "Magnum/Math/Matrix4.h"
#include "Magnum/MeshTools/Concatenate.h"
#include "Magnum/MeshTools/Transform.h"
#include "Magnum/SceneTools/FlattenTransformationHierarchy.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/SceneTools/OrderClusterParents.h"
#include "Magnum/Trade/SceneData.h"
#include "Magnum/Trade/MeshData.h"
@ -43,14 +43,14 @@ using namespace Magnum;
int main() {
{
/* [flattenTransformationHierarchy2D-mesh-concatenate] */
/* [absoluteFieldTransformations2D-mesh-concatenate] */
Trade::SceneData scene = DOXYGEN_ELLIPSIS(Trade::SceneData{{}, 0, nullptr, {}});
Containers::Array<Trade::MeshData> meshes = DOXYGEN_ELLIPSIS({});
Containers::Array<Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>>
meshesMaterials = scene.meshesMaterialsAsArray();
Containers::Array<Matrix3> transformations =
SceneTools::flattenTransformationHierarchy2D(scene, Trade::SceneField::Mesh);
SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Mesh);
/* Since a mesh can be referenced multiple times, we can't operate in-place */
Containers::Array<Trade::MeshData> flattenedMeshes;
@ -60,16 +60,16 @@ for(std::size_t i = 0; i != meshesMaterials.size(); ++i) {
}
Trade::MeshData concatenated = MeshTools::concatenate(flattenedMeshes);
/* [flattenTransformationHierarchy2D-mesh-concatenate] */
/* [absoluteFieldTransformations2D-mesh-concatenate] */
} {
/* [flattenTransformationHierarchy3D-mesh-concatenate] */
/* [absoluteFieldTransformations3D-mesh-concatenate] */
Trade::SceneData scene = DOXYGEN_ELLIPSIS(Trade::SceneData{{}, 0, nullptr, {}});
Containers::Array<Trade::MeshData> meshes = DOXYGEN_ELLIPSIS({});
Containers::Array<Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>>
meshesMaterials = scene.meshesMaterialsAsArray();
Containers::Array<Matrix4> transformations =
SceneTools::flattenTransformationHierarchy3D(scene, Trade::SceneField::Mesh);
SceneTools::absoluteFieldTransformations3D(scene, Trade::SceneField::Mesh);
/* Since a mesh can be referenced multiple times, we can't operate in-place */
Containers::Array<Trade::MeshData> flattenedMeshes;
@ -79,7 +79,7 @@ for(std::size_t i = 0; i != meshesMaterials.size(); ++i) {
}
Trade::MeshData concatenated = MeshTools::concatenate(flattenedMeshes);
/* [flattenTransformationHierarchy3D-mesh-concatenate] */
/* [absoluteFieldTransformations3D-mesh-concatenate] */
}
{

2
modules/FindMagnum.cmake

@ -910,7 +910,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
# SceneTools library
elseif(_component STREQUAL SceneTools)
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES FlattenTransformationHierarchy.h)
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Hierarchy.h)
# ShaderTools library
elseif(_component STREQUAL ShaderTools)

8
src/Magnum/SceneTools/CMakeLists.txt

@ -45,13 +45,13 @@ set(MagnumSceneTools_SRCS )
set(MagnumSceneTools_GracefulAssert_SRCS
Combine.cpp
Filter.cpp
FlattenTransformationHierarchy.cpp
Hierarchy.cpp
OrderClusterParents.cpp)
set(MagnumSceneTools_HEADERS
Combine.h
Filter.h
FlattenTransformationHierarchy.h
Hierarchy.h
OrderClusterParents.h
visibility.h)
@ -63,7 +63,9 @@ set(MagnumSceneTools_PRIVATE_HEADERS
if(MAGNUM_BUILD_DEPRECATED)
list(APPEND MagnumSceneTools_GracefulAssert_SRCS FlattenMeshHierarchy.cpp)
list(APPEND MagnumSceneTools_HEADERS FlattenMeshHierarchy.h)
list(APPEND MagnumSceneTools_HEADERS
FlattenMeshHierarchy.h
FlattenTransformationHierarchy.h)
endif()
## Objects shared between main and test library

10
src/Magnum/SceneTools/FlattenMeshHierarchy.cpp

@ -34,7 +34,7 @@
#include "Magnum/DimensionTraits.h"
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h"
#include "Magnum/SceneTools/FlattenTransformationHierarchy.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/Trade/SceneData.h"
namespace Magnum { namespace SceneTools {
@ -44,18 +44,18 @@ namespace {
template<UnsignedInt> struct DimensionTraits;
template<> struct DimensionTraits<2> {
static Containers::Array<Matrix3> flatten(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix3& globalTransformation) {
return flattenTransformationHierarchy2D(scene, fieldId, globalTransformation);
return absoluteFieldTransformations2D(scene, fieldId, globalTransformation);
}
static void flattenInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation) {
return flattenTransformationHierarchy2DInto(scene, fieldId, transformations, globalTransformation);
return absoluteFieldTransformations2DInto(scene, fieldId, transformations, globalTransformation);
}
};
template<> struct DimensionTraits<3> {
static Containers::Array<Matrix4> flatten(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix4& globalTransformation) {
return flattenTransformationHierarchy3D(scene, fieldId, globalTransformation);
return absoluteFieldTransformations3D(scene, fieldId, globalTransformation);
}
static void flattenInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation) {
return flattenTransformationHierarchy3DInto(scene, fieldId, transformations, globalTransformation);
return absoluteFieldTransformations3DInto(scene, fieldId, transformations, globalTransformation);
}
};

26
src/Magnum/SceneTools/FlattenMeshHierarchy.h

@ -28,9 +28,9 @@
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file
* @brief Function @ref Magnum::SceneTools::flattenMeshHierarchy2D(), @ref Magnum::SceneTools::flattenMeshHierarchy2DInto(), @ref Magnum::SceneTools::flattenMeshHierarchy3D(), @ref Magnum::SceneTools::flattenMeshHierarchy3DInto()
* @m_deprecated_since_latest Use @ref Magnum/SceneTools/FlattenTransformationHierarchy.h
* and the @relativeref{Magnum,SceneTools::flattenTransformationHierarchy2D()} /
* @relativeref{Magnum,SceneTools::flattenTransformationHierarchy3D()}
* @m_deprecated_since_latest Use @ref Magnum/SceneTools/Hierarchy.h and the
* @relativeref{Magnum,SceneTools::absoluteFieldTransformations2D()} /
* @relativeref{Magnum,SceneTools::absoluteFieldTransformations3D()}
* functions instead.
*/
#endif
@ -47,7 +47,7 @@
#include "Magnum/Trade/Trade.h"
#ifndef _MAGNUM_NO_DEPRECATED_FLATTENMESHHIERARCHY
CORRADE_DEPRECATED_FILE("use Magnum/SceneTools/FlattenTransformationHierarchy.h and the SceneTools::flattenTransformationHierarchy*D() functions instead")
CORRADE_DEPRECATED_FILE("use Magnum/SceneTools/Hierarchy.h and the SceneTools::absoluteFieldTransformations*D() functions instead")
#endif
namespace Magnum { namespace SceneTools {
@ -55,11 +55,11 @@ namespace Magnum { namespace SceneTools {
/**
@brief Flatten a 2D mesh hierarchy
@m_deprecated_since_latest Use @ref flattenTransformationHierarchy2D(const Trade::SceneData&, Trade::SceneField, const Matrix3& globalTransformation)
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2D(const Trade::SceneData&, Trade::SceneField, const Matrix3&)
with @ref Trade::SceneField::Mesh together with
@ref Trade::SceneData::meshesMaterialsAsArray() instead.
*/
CORRADE_DEPRECATED("use flattenTransformationHierarchy2D() instead") MAGNUM_SCENETOOLS_EXPORT Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix3>> flattenMeshHierarchy2D(const Trade::SceneData& scene, const Matrix3& globalTransformation = {});
CORRADE_DEPRECATED("use absoluteFieldTransformations2D() instead") MAGNUM_SCENETOOLS_EXPORT Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix3>> flattenMeshHierarchy2D(const Trade::SceneData& scene, const Matrix3& globalTransformation = {});
/**
@brief Flatten a 2D mesh hierarchy into an existing array
@ -67,19 +67,19 @@ CORRADE_DEPRECATED("use flattenTransformationHierarchy2D() instead") MAGNUM_SCEN
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_deprecated_since_latest Use @ref flattenTransformationHierarchy2DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
with @ref Trade::SceneField::Mesh instead.
*/
CORRADE_DEPRECATED("use flattenTransformationHierarchy2DInto() instead") MAGNUM_SCENETOOLS_EXPORT void flattenMeshHierarchy2DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
CORRADE_DEPRECATED("use absoluteFieldTransformations2DInto() instead") MAGNUM_SCENETOOLS_EXPORT void flattenMeshHierarchy2DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
/**
@brief Flatten a 3D mesh hierarchy
@m_deprecated_since_latest Use @ref flattenTransformationHierarchy3D(const Trade::SceneData&, Trade::SceneField, const Matrix4&)
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3D(const Trade::SceneData&, Trade::SceneField, const Matrix4&)
with @ref Trade::SceneField::Mesh together with
@ref Trade::SceneData::meshesMaterialsAsArray() instead.
*/
CORRADE_DEPRECATED("use flattenTransformationHierarchy3D() instead") MAGNUM_SCENETOOLS_EXPORT Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix4>> flattenMeshHierarchy3D(const Trade::SceneData& scene, const Matrix4& globalTransformation = {});
CORRADE_DEPRECATED("use absoluteFieldTransformations3D() instead") MAGNUM_SCENETOOLS_EXPORT Containers::Array<Containers::Triple<UnsignedInt, Int, Matrix4>> flattenMeshHierarchy3D(const Trade::SceneData& scene, const Matrix4& globalTransformation = {});
/**
@brief Flatten a 3D mesh hierarchy into an existing array
@ -87,14 +87,14 @@ CORRADE_DEPRECATED("use flattenTransformationHierarchy3D() instead") MAGNUM_SCEN
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_deprecated_since_latest Use @ref flattenTransformationHierarchy3DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
with @ref Trade::SceneField::Mesh instead.
*/
CORRADE_DEPRECATED("use flattenTransformationHierarchy3DInto() instead") MAGNUM_SCENETOOLS_EXPORT void flattenMeshHierarchy3DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
CORRADE_DEPRECATED("use absoluteFieldTransformations3DInto() instead") MAGNUM_SCENETOOLS_EXPORT void flattenMeshHierarchy3DInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
}}
#else
#error use Magnum/SceneTools/FlattenTransformationHierarchy.h and the SceneTools::flattenTransformationHierarchy*D() functions instead
#error use Magnum/SceneTools/FlattenTransformationHierarchy.h and the SceneTools::absoluteFieldTransformations*D() functions instead
#endif
#endif

237
src/Magnum/SceneTools/FlattenTransformationHierarchy.h

@ -25,219 +25,108 @@
DEALINGS IN THE SOFTWARE.
*/
#ifdef MAGNUM_BUILD_DEPRECATED
/** @file
* @brief Function @ref Magnum::SceneTools::flattenTransformationHierarchy2D(), @ref Magnum::SceneTools::flattenTransformationHierarchy2DInto(), @ref Magnum::SceneTools::flattenTransformationHierarchy3D(), @ref Magnum::SceneTools::flattenTransformationHierarchy3DInto()
* @m_since_latest
* @m_deprecated_since_latest Use @ref Magnum/SceneTools/Hierarchy.h and the
* @relativeref{Magnum,SceneTools::absoluteFieldTransformations2D()} /
* @relativeref{Magnum,SceneTools::absoluteFieldTransformations3D()}
* functions instead.
*/
#endif
#include "Magnum/Magnum.h"
#include "Magnum/SceneTools/visibility.h"
#include "Magnum/Trade/Trade.h"
namespace Magnum { namespace SceneTools {
/**
@brief Flatten a 2D transformation hierarchy for given field
@m_since_latest
For all entries of given @p field in @p scene returns an absolute
transformation of the object they're attached to in the scene with
@p globalTransformation prepended. The @ref Trade::SceneField::Parent field is
expected to be contained in the scene, having no cycles or duplicates, and the
scene is expected to be 2D. The @p field is expected to be present, if it's
empty, the function returns an empty array.
#include "Magnum/configure.h"
The operation is done in an @f$ \mathcal{O}(m + n) @f$ execution time and
memory complexity, with @f$ m @f$ being size of @p field and @f$ n @f$ being
@ref Trade::SceneData::mappingBound(). The function calls
@ref orderClusterParents() internally.
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Macros.h>
The returned data are in the same order as object mapping entries in @p field.
Fields attached to objects without a @ref Trade::SceneField::Parent or to
objects in loose hierarchy subtrees will have their transformation set to an
unspecified value.
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/Trade/Trade.h"
This function can be used for example to flatten a mesh hierarchy, bake
the transformations to actual meshes and then concatenate them together into a
single mesh:
CORRADE_DEPRECATED_FILE("use Magnum/SceneTools/Hierarchy.h and the SceneTools::absoluteFieldTransformations*D() functions instead")
@snippet MagnumSceneTools.cpp flattenTransformationHierarchy2D-mesh-concatenate
namespace Magnum { namespace SceneTools {
@experimental
/* Made header-only to not have to maintain a deprecated source file */
@see @ref flattenTransformationHierarchy2D(const Trade::SceneData&, UnsignedInt, const Matrix3&),
@ref flattenTransformationHierarchy2DInto(),
@ref flattenTransformationHierarchy3D(), @ref Trade::SceneData::hasField(),
@ref Trade::SceneData::is2D()
/**
@brief Flatten a 2D transformation hierarchy for given field
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2D(const Trade::SceneData&, Trade::SceneField, const Matrix3&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, Trade::SceneField field);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations2D() instead") Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation = {}) {
return absoluteFieldTransformations2D(scene, field, globalTransformation);
}
/**
@brief Flatten a 2D transformation hierarchy for given field ID
@m_since_latest
A variant of @ref flattenTransformationHierarchy2D(const Trade::SceneData&, Trade::SceneField, const Matrix3&)
that takes a field ID instead of name. Useful for example in combination with
@ref Trade::SceneData::findFieldId() to avoid a double lookup if it isn't clear
if a field exists at all. The @p fieldId is expected to be smaller than
@ref Trade::SceneData::fieldCount().
@experimental
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2D(const Trade::SceneData&, UnsignedInt, const Matrix3&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, UnsignedInt fieldId);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations2D() instead") Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation = {}) {
return absoluteFieldTransformations2D(scene, fieldId, globalTransformation);
}
/**
@brief Flatten a 2D transformation hierarchy for given field into an existing array
@param[in] scene Input scene
@param[in] field Field to calculate the transformations for
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_since_latest
A variant of @ref flattenTransformationHierarchy2D(const Trade::SceneData&, Trade::SceneField, const Matrix3&)
that fills existing memory instead of allocating a new array. The
@p transformations array is expected to have the same size as the @p field.
@experimental
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations2DInto() instead") void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {}) {
return absoluteFieldTransformations2DInto(scene, field, transformations, globalTransformation);
}
/**
@brief Flatten a 2D transformation hierarchy for given field ID into an existing array
@m_since_latest
A variant of @ref flattenTransformationHierarchy2DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
that takes a field ID instead of name. Useful for example in combination with
@ref Trade::SceneData::findFieldId() to avoid a double lookup if it isn't clear
if a field exists at all. The @p fieldId is expected to be smaller than
@ref Trade::SceneData::fieldCount().
@experimental
@m_deprecated_since_latest Use @ref absoluteFieldTransformations2DInto(const Trade::SceneData&, UnsignedInt, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations2DInto() instead") void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {}) {
return absoluteFieldTransformations2DInto(scene, fieldId, transformations, globalTransformation);
}
/**
@brief Flatten a 3D transformation hierarchy for given field
@m_since_latest
For all entries of given @p field in @p scene returns an absolute
transformation of the object they're attached to in the scene with
@p globalTransformation prepended. The @ref Trade::SceneField::Parent field is
expected to be contained in the scene, having no cycles or duplicates, and the
scene is expected to be 3D. The @p field is expected to be present, if it's
empty, the function returns an empty array.
The operation is done in an @f$ \mathcal{O}(m + n) @f$ execution time and
memory complexity, with @f$ m @f$ being size of @p field and @f$ n @f$ being
@ref Trade::SceneData::mappingBound(). The function calls
@ref orderClusterParents() internally.
The returned data are in the same order as object mapping entries in @p field.
Fields attached to objects without a @ref Trade::SceneField::Parent or to
objects in loose hierarchy subtrees will have their transformation set to an
unspecified value.
This function can be used for example to flatten a mesh hierarchy, bake
the transformations to actual meshes and then concatenate them together into a
single mesh:
@snippet MagnumSceneTools.cpp flattenTransformationHierarchy3D-mesh-concatenate
@experimental
@see @ref flattenTransformationHierarchy3D(const Trade::SceneData&, UnsignedInt, const Matrix4&),
@ref flattenTransformationHierarchy3DInto(),
@ref flattenTransformationHierarchy2D(), @ref Trade::SceneData::hasField(),
@ref Trade::SceneData::is3D()
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3D(const Trade::SceneData&, Trade::SceneField, const Matrix4&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, Trade::SceneField field);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations3D() instead") Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation = {}) {
return absoluteFieldTransformations3D(scene, field, globalTransformation);
}
/**
@brief Flatten a 3D transformation hierarchy for given field ID
@m_since_latest
A variant of @ref flattenTransformationHierarchy3D(const Trade::SceneData&, Trade::SceneField, const Matrix4&)
that takes a field ID instead of name. Useful for example in combination with
@ref Trade::SceneData::findFieldId() to avoid a double lookup if it isn't clear
if a field exists at all. The @p fieldId is expected to be smaller than
@ref Trade::SceneData::fieldCount().
@experimental
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3D(const Trade::SceneData&, UnsignedInt, const Matrix4&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix34 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, UnsignedInt fieldId);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations3D() instead") Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation = {}) {
return absoluteFieldTransformations3D(scene, fieldId, globalTransformation);
}
/**
@brief Flatten a 3D transformation hierarchy for given field into an existing array
@param[in] scene Input scene
@param[in] field Field to calculate the transformations for
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_since_latest
A variant of @ref flattenTransformationHierarchy3D(const Trade::SceneData&, Trade::SceneField, const Matrix4&)
that fills existing memory instead of allocating a new array. The
@p transformations array is expected to have the same size as the @p field.
@experimental
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations3DInto() instead") void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {}) {
return absoluteFieldTransformations3DInto(scene, field, transformations, globalTransformation);
}
/**
@brief Flatten a 3D transformation hierarchy for given field into an existing array
@m_since_latest
A variant of @ref flattenTransformationHierarchy3DInto(const Trade::SceneData&, Trade::SceneField, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
that takes a field ID instead of name. Useful for example in combination with
@ref Trade::SceneData::findFieldId() to avoid a double lookup if it isn't clear
if a field exists at all. The @p fieldId is expected to be smaller than
@ref Trade::SceneData::fieldCount().
@experimental
@brief Flatten a 3D transformation hierarchy for given field ID into an existing array
@m_deprecated_since_latest Use @ref absoluteFieldTransformations3DInto(const Trade::SceneData&, UnsignedInt, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
instead.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations);
#endif
inline CORRADE_DEPRECATED("use absoluteFieldTransformations3DInto() instead") void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {}) {
return absoluteFieldTransformations3DInto(scene, fieldId, transformations, globalTransformation);
}
}}
#else
#error use Magnum/SceneTools/Hierarchy.h and the SceneTools::absoluteFieldTransformations*D() functions instead
#endif
#endif

94
src/Magnum/SceneTools/FlattenTransformationHierarchy.cpp → src/Magnum/SceneTools/Hierarchy.cpp

@ -23,7 +23,7 @@
DEALINGS IN THE SOFTWARE.
*/
#include "FlattenTransformationHierarchy.h"
#include "Hierarchy.h"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayTuple.h>
@ -59,16 +59,16 @@ template<> struct SceneDataDimensionTraits<3> {
}
};
template<UnsignedInt dimensions> void flattenTransformationHierarchyIntoImplementation(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<MatrixTypeFor<dimensions, Float>>& outputTransformations, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
template<UnsignedInt dimensions> void absoluteFieldTransformationsIntoImplementation(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<MatrixTypeFor<dimensions, Float>>& outputTransformations, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
CORRADE_ASSERT(SceneDataDimensionTraits<dimensions>::isDimensions(scene),
"SceneTools::flattenTransformationHierarchy(): the scene is not" << dimensions << Debug::nospace << "D", );
"SceneTools::absoluteFieldTransformations(): the scene is not" << dimensions << Debug::nospace << "D", );
CORRADE_ASSERT(fieldId < scene.fieldCount(),
"SceneTools::flattenTransformationHierarchy(): index" << fieldId << "out of range for" << scene.fieldCount() << "fields", );
"SceneTools::absoluteFieldTransformations(): index" << fieldId << "out of range for" << scene.fieldCount() << "fields", );
const Containers::Optional<UnsignedInt> parentFieldId = scene.findFieldId(Trade::SceneField::Parent);
CORRADE_ASSERT(parentFieldId,
"SceneTools::flattenTransformationHierarchy(): the scene has no hierarchy", );
"SceneTools::absoluteFieldTransformations(): the scene has no hierarchy", );
CORRADE_ASSERT(outputTransformations.size() == scene.fieldSize(fieldId),
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected" << scene.fieldSize(fieldId) << "but got" << outputTransformations.size(), );
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected" << scene.fieldSize(fieldId) << "but got" << outputTransformations.size(), );
/* Allocate a single storage for all temporary data */
Containers::ArrayView<Containers::Pair<UnsignedInt, Int>> orderedClusteredParents;
@ -118,97 +118,97 @@ template<UnsignedInt dimensions> void flattenTransformationHierarchyIntoImplemen
}
}
template<UnsignedInt dimensions> void flattenTransformationHierarchyIntoImplementation(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<MatrixTypeFor<dimensions, Float>>& outputTransformations, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
template<UnsignedInt dimensions> void absoluteFieldTransformationsIntoImplementation(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<MatrixTypeFor<dimensions, Float>>& outputTransformations, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field);
CORRADE_ASSERT(fieldId,
"SceneTools::flattenTransformationHierarchyInto(): field" << field << "not found", );
"SceneTools::absoluteFieldTransformationsInto(): field" << field << "not found", );
flattenTransformationHierarchyIntoImplementation<dimensions>(scene, *fieldId, outputTransformations, globalTransformation);
absoluteFieldTransformationsIntoImplementation<dimensions>(scene, *fieldId, outputTransformations, globalTransformation);
}
template<UnsignedInt dimensions> Containers::Array<MatrixTypeFor<dimensions, Float>> flattenTransformationHierarchyImplementation(const Trade::SceneData& scene, const UnsignedInt fieldId, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
template<UnsignedInt dimensions> Containers::Array<MatrixTypeFor<dimensions, Float>> absoluteFieldTransformationsImplementation(const Trade::SceneData& scene, const UnsignedInt fieldId, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
CORRADE_ASSERT(fieldId < scene.fieldCount(),
"SceneTools::flattenTransformationHierarchy(): index" << fieldId << "out of range for" << scene.fieldCount() << "fields", {});
"SceneTools::absoluteFieldTransformations(): index" << fieldId << "out of range for" << scene.fieldCount() << "fields", {});
Containers::Array<MatrixTypeFor<dimensions, Float>> out{NoInit, scene.fieldSize(fieldId)};
flattenTransformationHierarchyIntoImplementation<dimensions>(scene, fieldId, out, globalTransformation);
absoluteFieldTransformationsIntoImplementation<dimensions>(scene, fieldId, out, globalTransformation);
return out;
}
template<UnsignedInt dimensions> Containers::Array<MatrixTypeFor<dimensions, Float>> flattenTransformationHierarchyImplementation(const Trade::SceneData& scene, const Trade::SceneField field, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
template<UnsignedInt dimensions> Containers::Array<MatrixTypeFor<dimensions, Float>> absoluteFieldTransformationsImplementation(const Trade::SceneData& scene, const Trade::SceneField field, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field);
CORRADE_ASSERT(fieldId,
"SceneTools::flattenTransformationHierarchy(): field" << field << "not found", {});
"SceneTools::absoluteFieldTransformations(): field" << field << "not found", {});
Containers::Array<MatrixTypeFor<dimensions, Float>> out{NoInit, scene.fieldSize(*fieldId)};
flattenTransformationHierarchyIntoImplementation<dimensions>(scene, *fieldId, out, globalTransformation);
absoluteFieldTransformationsIntoImplementation<dimensions>(scene, *fieldId, out, globalTransformation);
return out;
}
}
Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, const Trade::SceneField field, const Matrix3& globalTransformation) {
return flattenTransformationHierarchyImplementation<2>(scene, field, globalTransformation);
Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, const Trade::SceneField field, const Matrix3& globalTransformation) {
return absoluteFieldTransformationsImplementation<2>(scene, field, globalTransformation);
}
Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, const Trade::SceneField field) {
return flattenTransformationHierarchyImplementation<2>(scene, field, {});
Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, const Trade::SceneField field) {
return absoluteFieldTransformationsImplementation<2>(scene, field, {});
}
Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix3& globalTransformation) {
return flattenTransformationHierarchyImplementation<2>(scene, fieldId, globalTransformation);
Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix3& globalTransformation) {
return absoluteFieldTransformationsImplementation<2>(scene, fieldId, globalTransformation);
}
Containers::Array<Matrix3> flattenTransformationHierarchy2D(const Trade::SceneData& scene, const UnsignedInt fieldId) {
return flattenTransformationHierarchyImplementation<2>(scene, fieldId, {});
Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, const UnsignedInt fieldId) {
return absoluteFieldTransformationsImplementation<2>(scene, fieldId, {});
}
void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation) {
return flattenTransformationHierarchyIntoImplementation<2>(scene, field, transformations, globalTransformation);
void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation) {
return absoluteFieldTransformationsIntoImplementation<2>(scene, field, transformations, globalTransformation);
}
void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations) {
return flattenTransformationHierarchyIntoImplementation<2>(scene, field, transformations, {});
void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations) {
return absoluteFieldTransformationsIntoImplementation<2>(scene, field, transformations, {});
}
void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation) {
return flattenTransformationHierarchyIntoImplementation<2>(scene, fieldId, transformations, globalTransformation);
void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation) {
return absoluteFieldTransformationsIntoImplementation<2>(scene, fieldId, transformations, globalTransformation);
}
void flattenTransformationHierarchy2DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations) {
return flattenTransformationHierarchyIntoImplementation<2>(scene, fieldId, transformations, {});
void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations) {
return absoluteFieldTransformationsIntoImplementation<2>(scene, fieldId, transformations, {});
}
Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, const Trade::SceneField field, const Matrix4& globalTransformation) {
return flattenTransformationHierarchyImplementation<3>(scene, field, globalTransformation);
Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, const Trade::SceneField field, const Matrix4& globalTransformation) {
return absoluteFieldTransformationsImplementation<3>(scene, field, globalTransformation);
}
Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, const Trade::SceneField field) {
return flattenTransformationHierarchyImplementation<3>(scene, field, {});
Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, const Trade::SceneField field) {
return absoluteFieldTransformationsImplementation<3>(scene, field, {});
}
Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix4& globalTransformation) {
return flattenTransformationHierarchyImplementation<3>(scene, fieldId, globalTransformation);
Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, const UnsignedInt fieldId, const Matrix4& globalTransformation) {
return absoluteFieldTransformationsImplementation<3>(scene, fieldId, globalTransformation);
}
Containers::Array<Matrix4> flattenTransformationHierarchy3D(const Trade::SceneData& scene, const UnsignedInt fieldId) {
return flattenTransformationHierarchyImplementation<3>(scene, fieldId, {});
Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, const UnsignedInt fieldId) {
return absoluteFieldTransformationsImplementation<3>(scene, fieldId, {});
}
void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation) {
return flattenTransformationHierarchyIntoImplementation<3>(scene, field, transformations, globalTransformation);
void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation) {
return absoluteFieldTransformationsIntoImplementation<3>(scene, field, transformations, globalTransformation);
}
void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations) {
return flattenTransformationHierarchyIntoImplementation<3>(scene, field, transformations, {});
void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, const Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations) {
return absoluteFieldTransformationsIntoImplementation<3>(scene, field, transformations, {});
}
void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation) {
return flattenTransformationHierarchyIntoImplementation<3>(scene, fieldId, transformations, globalTransformation);
void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation) {
return absoluteFieldTransformationsIntoImplementation<3>(scene, fieldId, transformations, globalTransformation);
}
void flattenTransformationHierarchy3DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations) {
return flattenTransformationHierarchyIntoImplementation<3>(scene, fieldId, transformations, {});
void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, const UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations) {
return absoluteFieldTransformationsIntoImplementation<3>(scene, fieldId, transformations, {});
}
}}

237
src/Magnum/SceneTools/Hierarchy.h

@ -0,0 +1,237 @@
#ifndef Magnum_SceneTools_Hierarchy_h
#define Magnum_SceneTools_Hierarchy_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Function @ref Magnum::SceneTools::absoluteFieldTransformations2D(), @ref Magnum::SceneTools::absoluteFieldTransformations2DInto(), @ref Magnum::SceneTools::absoluteFieldTransformations3D(), @ref Magnum::SceneTools::absoluteFieldTransformations3DInto()
* @m_since_latest
*/
#include "Magnum/Magnum.h"
#include "Magnum/SceneTools/visibility.h"
#include "Magnum/Trade/Trade.h"
namespace Magnum { namespace SceneTools {
/**
@brief Calculate absolute 2D transformations for given field
@m_since_latest
For all entries of given field in @p scene returns an absolute transformation
of the object they're attached to in the scene with @p globalTransformation
prepended. The @ref Trade::SceneField::Parent field is expected to be contained
in the scene, having no cycles or duplicates, the scene is expected to be 2D
and @p fieldId is expected to be less than @ref Trade::SceneData::fieldCount().
If the field is empty, the function returns an empty array.
The operation is done in an @f$ \mathcal{O}(m + n) @f$ execution time and
memory complexity, with @f$ m @f$ being size of @p fieldId and @f$ n @f$ being
@ref Trade::SceneData::mappingBound(). The function calls
@ref orderClusterParents() internally.
The returned data are in the same order as object mapping entries in
@p fieldId. Fields attached to objects without a @ref Trade::SceneField::Parent
or to objects in loose hierarchy subtrees will have their transformation set to
an unspecified value.
This function can be used for example to flatten a mesh hierarchy, bake
the transformations to actual meshes and then concatenate them together into a
single mesh:
@snippet MagnumSceneTools.cpp absoluteFieldTransformations2D-mesh-concatenate
@experimental
@see @ref absoluteFieldTransformations2D(const Trade::SceneData&, UnsignedInt, const Matrix3&),
@ref absoluteFieldTransformations2DInto(),
@ref absoluteFieldTransformations3D(), @ref Trade::SceneData::hasField(),
@ref Trade::SceneData::is2D()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, UnsignedInt fieldId);
#endif
/**
@brief Calculate absolute 2D transformations for given named field
@m_since_latest
Translates @p field to a field ID using @ref Trade::SceneData::fieldId() and
delegates to @ref absoluteFieldTransformations2D(const Trade::SceneData&, UnsignedInt, const Matrix3&).
The @p field is expected to exist in @p scene.
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix3> absoluteFieldTransformations2D(const Trade::SceneData& scene, Trade::SceneField field);
#endif
/**
@brief Calculate absolute 2D transformations for given field into an existing array
@param[in] scene Input scene
@param[in] fieldId Field to calculate the transformations for
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_since_latest
A variant of @ref absoluteFieldTransformations2D(const Trade::SceneData&, UnsignedInt, const Matrix3&)
that fills existing memory instead of allocating a new array. The
@p transformations array is expected to have the same size as the @p fieldId.
@see @ref Trade::SceneData::fieldSize()
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix3>& transformations);
#endif
/**
@brief Calculate absolute 2D transformations for given named field into an existing array
@m_since_latest
Translates @p field to a field ID using @ref Trade::SceneData::fieldId() and
delegates to @ref absoluteFieldTransformations2DInto(const Trade::SceneData&, UnsignedInt, const Containers::StridedArrayView1D<Matrix3>&, const Matrix3&)
The @p field is expected to exist in @p scene.
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation = {});
#else
/* To avoid including Matrix3 */
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations, const Matrix3& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations2DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix3>& transformations);
#endif
/**
@brief Calculate absolute 2D transformations for given field
@m_since_latest
For all entries of given field in @p scene returns an absolute transformation
of the object they're attached to in the scene with @p globalTransformation
prepended. The @ref Trade::SceneField::Parent field is expected to be contained
in the scene, having no cycles or duplicates, the scene is expected to be 3D
and @p fieldId is expected to be less than @ref Trade::SceneData::fieldCount().
If the field is empty, the function returns an empty array.
The operation is done in an @f$ \mathcal{O}(m + n) @f$ execution time and
memory complexity, with @f$ m @f$ being size of @p fieldId and @f$ n @f$ being
@ref Trade::SceneData::mappingBound(). The function calls
@ref orderClusterParents() internally.
The returned data are in the same order as object mapping entries in
@p fieldId. Fields attached to objects without a @ref Trade::SceneField::Parent
or to objects in loose hierarchy subtrees will have their transformation set to
an unspecified value.
This function can be used for example to flatten a mesh hierarchy, bake
the transformations to actual meshes and then concatenate them together into a
single mesh:
@snippet MagnumSceneTools.cpp absoluteFieldTransformations3D-mesh-concatenate
@experimental
@see @ref absoluteFieldTransformations3D(const Trade::SceneData&, UnsignedInt, const Matrix4&),
@ref absoluteFieldTransformations3DInto(),
@ref absoluteFieldTransformations2D(), @ref Trade::SceneData::hasField(),
@ref Trade::SceneData::is3D()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, UnsignedInt fieldId);
#endif
/**
@brief Calculate absolute 3D transformations for given named field
@m_since_latest
Translates @p field to a field ID using @ref Trade::SceneData::fieldId() and
delegates to @ref absoluteFieldTransformations3D(const Trade::SceneData&, UnsignedInt, const Matrix4&).
The @p field is expected to exist in @p scene.
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT Containers::Array<Matrix4> absoluteFieldTransformations3D(const Trade::SceneData& scene, Trade::SceneField field);
#endif
/**
@brief Calculate absolute 3D transformations for given field into an existing array
@param[in] scene Input scene
@param[in] fieldId Field to calculate the transformations for
@param[out] transformations Where to put the calculated transformations
@param[in] globalTransformation Global transformation to prepend
@m_since_latest
A variant of @ref absoluteFieldTransformations3D(const Trade::SceneData&, UnsignedInt, const Matrix4&)
that fills existing memory instead of allocating a new array. The
@p transformations array is expected to have the same size as the @p fieldId.
@see @ref Trade::SceneData::fieldSize()
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, UnsignedInt fieldId, const Containers::StridedArrayView1D<Matrix4>& transformations);
#endif
/**
@brief Calculate absolute 3D transformations for given named field into an existing array
@m_since_latest
Translates @p field to a field ID using @ref Trade::SceneData::fieldId() and
delegates to @ref absoluteFieldTransformations3DInto(const Trade::SceneData&, UnsignedInt, const Containers::StridedArrayView1D<Matrix4>&, const Matrix4&)
The @p field is expected to exist in @p scene.
@experimental
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation = {});
#else
/* To avoid including Matrix4 */
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations, const Matrix4& globalTransformation);
MAGNUM_SCENETOOLS_EXPORT void absoluteFieldTransformations3DInto(const Trade::SceneData& scene, Trade::SceneField field, const Containers::StridedArrayView1D<Matrix4>& transformations);
#endif
}}
#endif

2
src/Magnum/SceneTools/Test/CMakeLists.txt

@ -53,7 +53,7 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/configure.h
corrade_add_test(SceneToolsCombineTest CombineTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsConvertToSingleFunc___Test ConvertToSingleFunctionObjectsTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsFilterTest FilterTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsFlattenTra___HierarchyTest FlattenTransformationHierarchyTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsHierarchyTest HierarchyTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsOrderClusterParentsTest OrderClusterParentsTest.cpp LIBRARIES MagnumSceneToolsTestLib)
corrade_add_test(SceneToolsSceneConverterImple___Test SceneConverterImplementationTest.cpp

14
src/Magnum/SceneTools/Test/FlattenMeshHierarchyTest.cpp

@ -311,7 +311,7 @@ void FlattenMeshHierarchyTest::not2DNot3D() {
CORRADE_SKIP_IF_NO_ASSERT();
/* Used to assert even on an empty scene, now it does an early-out if the
mesh field doesn't exist because flattenTransformationHierarchy() would
mesh field doesn't exist because absoluteFieldTransformations() would
assert instead. That behavioral change is fine for a deprecated API. */
Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, 0, nullptr, {
Trade::SceneFieldData{Trade::SceneField::Mesh, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::UnsignedInt, nullptr},
@ -324,15 +324,15 @@ void FlattenMeshHierarchyTest::not2DNot3D() {
flattenMeshHierarchy3D(scene);
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchy(): the scene is not 2D\n"
"SceneTools::flattenTransformationHierarchy(): the scene is not 3D\n");
"SceneTools::absoluteFieldTransformations(): the scene is not 2D\n"
"SceneTools::absoluteFieldTransformations(): the scene is not 3D\n");
}
void FlattenMeshHierarchyTest::noParentField() {
CORRADE_SKIP_IF_NO_ASSERT();
/* Used to assert even on an empty scene, now it does an early-out if the
mesh field doesn't exist because flattenTransformationHierarchy() would
mesh field doesn't exist because absoluteFieldTransformations() would
assert instead. That behavioral change is fine for a deprecated API. */
Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, 0, nullptr, {
Trade::SceneFieldData{Trade::SceneField::Mesh, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::UnsignedInt, nullptr},
@ -345,7 +345,7 @@ void FlattenMeshHierarchyTest::noParentField() {
flattenMeshHierarchy2D(scene);
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchy(): the scene has no hierarchy\n");
"SceneTools::absoluteFieldTransformations(): the scene has no hierarchy\n");
}
void FlattenMeshHierarchyTest::noMeshField() {
@ -499,8 +499,8 @@ void FlattenMeshHierarchyTest::intoInvalidSize() {
flattenMeshHierarchy3DInto(scene3D, transformations3D);
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 6\n"
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 4\n");
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 6\n"
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 4\n");
}
}}}}

146
src/Magnum/SceneTools/Test/FlattenTransformationHierarchyTest.cpp → src/Magnum/SceneTools/Test/HierarchyTest.cpp

@ -31,24 +31,24 @@
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h"
#include "Magnum/SceneTools/FlattenTransformationHierarchy.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/Trade/SceneData.h"
namespace Magnum { namespace SceneTools { namespace Test { namespace {
struct FlattenTransformationHierarchyTest: TestSuite::Tester {
explicit FlattenTransformationHierarchyTest();
struct HierarchyTest: TestSuite::Tester {
explicit HierarchyTest();
void test2D();
void test3D();
void absoluteFieldTransformations2D();
void absoluteFieldTransformations3D();
void fieldNotFound();
void not2DNot3D();
void noParentField();
void absoluteFieldTransformationsFieldNotFound();
void absoluteFieldTransformationsNot2DNot3D();
void absoluteFieldTransformationsNoParentField();
void into2D();
void into3D();
void intoInvalidSize();
void absoluteFieldTransformationsInto2D();
void absoluteFieldTransformationsInto3D();
void absoluteFieldTransformationsIntoInvalidSize();
};
using namespace Math::Literals;
@ -102,20 +102,20 @@ const struct {
5},
};
FlattenTransformationHierarchyTest::FlattenTransformationHierarchyTest() {
addInstancedTests({&FlattenTransformationHierarchyTest::test2D,
&FlattenTransformationHierarchyTest::test3D},
HierarchyTest::HierarchyTest() {
addInstancedTests({&HierarchyTest::absoluteFieldTransformations2D,
&HierarchyTest::absoluteFieldTransformations3D},
Containers::arraySize(TestData));
addTests({&FlattenTransformationHierarchyTest::fieldNotFound,
&FlattenTransformationHierarchyTest::not2DNot3D,
&FlattenTransformationHierarchyTest::noParentField});
addTests({&HierarchyTest::absoluteFieldTransformationsFieldNotFound,
&HierarchyTest::absoluteFieldTransformationsNot2DNot3D,
&HierarchyTest::absoluteFieldTransformationsNoParentField});
addInstancedTests({&FlattenTransformationHierarchyTest::into2D,
&FlattenTransformationHierarchyTest::into3D},
addInstancedTests({&HierarchyTest::absoluteFieldTransformationsInto2D,
&HierarchyTest::absoluteFieldTransformationsInto3D},
Containers::arraySize(IntoData));
addTests({&FlattenTransformationHierarchyTest::intoInvalidSize});
addTests({&HierarchyTest::absoluteFieldTransformationsIntoInvalidSize});
}
const struct Scene {
@ -198,7 +198,7 @@ const struct Scene {
{16, 113}}
}};
void FlattenTransformationHierarchyTest::test2D() {
void HierarchyTest::absoluteFieldTransformations2D() {
auto&& data = TestData[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -230,14 +230,14 @@ void FlattenTransformationHierarchyTest::test2D() {
/* To test all overloads */
if(data.globalTransformation2D != Matrix3{}) {
if(data.fieldIdInsteadOfName)
out = flattenTransformationHierarchy2D(scene, 2, data.globalTransformation2D);
out = SceneTools::absoluteFieldTransformations2D(scene, 2, data.globalTransformation2D);
else
out = flattenTransformationHierarchy2D(scene, Trade::SceneField::Mesh, data.globalTransformation2D);
out = SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Mesh, data.globalTransformation2D);
} else {
if(data.fieldIdInsteadOfName)
out = flattenTransformationHierarchy2D(scene, 2);
out = SceneTools::absoluteFieldTransformations2D(scene, 2);
else
out = flattenTransformationHierarchy2D(scene, Trade::SceneField::Mesh);
out = SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Mesh);
}
CORRADE_COMPARE_AS(out, Containers::arrayView({
@ -257,7 +257,7 @@ void FlattenTransformationHierarchyTest::test2D() {
}).prefix(data.expectedOutputSize), TestSuite::Compare::Container);
}
void FlattenTransformationHierarchyTest::test3D() {
void HierarchyTest::absoluteFieldTransformations3D() {
auto&& data = TestData[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -289,14 +289,14 @@ void FlattenTransformationHierarchyTest::test3D() {
/* To test all overloads */
if(data.globalTransformation3D != Matrix4{}) {
if(data.fieldIdInsteadOfName)
out = flattenTransformationHierarchy3D(scene, 2, data.globalTransformation3D);
out = SceneTools::absoluteFieldTransformations3D(scene, 2, data.globalTransformation3D);
else
out = flattenTransformationHierarchy3D(scene, Trade::SceneField::Mesh, data.globalTransformation3D);
out = SceneTools::absoluteFieldTransformations3D(scene, Trade::SceneField::Mesh, data.globalTransformation3D);
} else {
if(data.fieldIdInsteadOfName)
out = flattenTransformationHierarchy3D(scene, 2);
out = SceneTools::absoluteFieldTransformations3D(scene, 2);
else
out = flattenTransformationHierarchy3D(scene, Trade::SceneField::Mesh);
out = SceneTools::absoluteFieldTransformations3D(scene, Trade::SceneField::Mesh);
}
CORRADE_COMPARE_AS(out, Containers::arrayView({
@ -316,7 +316,7 @@ void FlattenTransformationHierarchyTest::test3D() {
}).prefix(data.expectedOutputSize), TestSuite::Compare::Container);
}
void FlattenTransformationHierarchyTest::fieldNotFound() {
void HierarchyTest::absoluteFieldTransformationsFieldNotFound() {
CORRADE_SKIP_IF_NO_ASSERT();
Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, 0, nullptr, {
@ -326,18 +326,18 @@ void FlattenTransformationHierarchyTest::fieldNotFound() {
std::ostringstream out;
Error redirectError{&out};
flattenTransformationHierarchy2D(scene, Trade::SceneField::Mesh);
flattenTransformationHierarchy3D(scene, Trade::SceneField::Mesh);
flattenTransformationHierarchy2D(scene, 2);
flattenTransformationHierarchy3D(scene, 2);
SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Mesh);
SceneTools::absoluteFieldTransformations3D(scene, Trade::SceneField::Mesh);
SceneTools::absoluteFieldTransformations2D(scene, 2);
SceneTools::absoluteFieldTransformations3D(scene, 2);
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchy(): field Trade::SceneField::Mesh not found\n"
"SceneTools::flattenTransformationHierarchy(): field Trade::SceneField::Mesh not found\n"
"SceneTools::flattenTransformationHierarchy(): index 2 out of range for 2 fields\n"
"SceneTools::flattenTransformationHierarchy(): index 2 out of range for 2 fields\n");
"SceneTools::absoluteFieldTransformations(): field Trade::SceneField::Mesh not found\n"
"SceneTools::absoluteFieldTransformations(): field Trade::SceneField::Mesh not found\n"
"SceneTools::absoluteFieldTransformations(): index 2 out of range for 2 fields\n"
"SceneTools::absoluteFieldTransformations(): index 2 out of range for 2 fields\n");
}
void FlattenTransformationHierarchyTest::not2DNot3D() {
void HierarchyTest::absoluteFieldTransformationsNot2DNot3D() {
CORRADE_SKIP_IF_NO_ASSERT();
Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, 0, nullptr, {
@ -346,18 +346,18 @@ void FlattenTransformationHierarchyTest::not2DNot3D() {
std::ostringstream out;
Error redirectError{&out};
flattenTransformationHierarchy2D(scene, Trade::SceneField::Parent);
flattenTransformationHierarchy2D(scene, 0);
flattenTransformationHierarchy3D(scene, Trade::SceneField::Parent);
flattenTransformationHierarchy3D(scene, 0);
SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Parent);
SceneTools::absoluteFieldTransformations2D(scene, 0);
SceneTools::absoluteFieldTransformations3D(scene, Trade::SceneField::Parent);
SceneTools::absoluteFieldTransformations3D(scene, 0);
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchy(): the scene is not 2D\n"
"SceneTools::flattenTransformationHierarchy(): the scene is not 2D\n"
"SceneTools::flattenTransformationHierarchy(): the scene is not 3D\n"
"SceneTools::flattenTransformationHierarchy(): the scene is not 3D\n");
"SceneTools::absoluteFieldTransformations(): the scene is not 2D\n"
"SceneTools::absoluteFieldTransformations(): the scene is not 2D\n"
"SceneTools::absoluteFieldTransformations(): the scene is not 3D\n"
"SceneTools::absoluteFieldTransformations(): the scene is not 3D\n");
}
void FlattenTransformationHierarchyTest::noParentField() {
void HierarchyTest::absoluteFieldTransformationsNoParentField() {
CORRADE_SKIP_IF_NO_ASSERT();
Trade::SceneData scene{Trade::SceneMappingType::UnsignedInt, 0, nullptr, {
@ -366,14 +366,14 @@ void FlattenTransformationHierarchyTest::noParentField() {
std::ostringstream out;
Error redirectError{&out};
flattenTransformationHierarchy2D(scene, Trade::SceneField::Transformation);
flattenTransformationHierarchy2D(scene, 0);
SceneTools::absoluteFieldTransformations2D(scene, Trade::SceneField::Transformation);
SceneTools::absoluteFieldTransformations2D(scene, 0);
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchy(): the scene has no hierarchy\n"
"SceneTools::flattenTransformationHierarchy(): the scene has no hierarchy\n");
"SceneTools::absoluteFieldTransformations(): the scene has no hierarchy\n"
"SceneTools::absoluteFieldTransformations(): the scene has no hierarchy\n");
}
void FlattenTransformationHierarchyTest::into2D() {
void HierarchyTest::absoluteFieldTransformationsInto2D() {
auto&& data = IntoData[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -403,14 +403,14 @@ void FlattenTransformationHierarchyTest::into2D() {
/* To test all overloads */
if(data.globalTransformation2D != Matrix3{}) {
if(data.fieldIdInsteadOfName)
flattenTransformationHierarchy2DInto(scene, 2, out, data.globalTransformation2D);
absoluteFieldTransformations2DInto(scene, 2, out, data.globalTransformation2D);
else
flattenTransformationHierarchy2DInto(scene, Trade::SceneField::Mesh, out, data.globalTransformation2D);
absoluteFieldTransformations2DInto(scene, Trade::SceneField::Mesh, out, data.globalTransformation2D);
} else {
if(data.fieldIdInsteadOfName)
flattenTransformationHierarchy2DInto(scene, 2, out);
absoluteFieldTransformations2DInto(scene, 2, out);
else
flattenTransformationHierarchy2DInto(scene, Trade::SceneField::Mesh, out);
absoluteFieldTransformations2DInto(scene, Trade::SceneField::Mesh, out);
}
CORRADE_COMPARE_AS(out, Containers::arrayView<Matrix3>({
@ -430,7 +430,7 @@ void FlattenTransformationHierarchyTest::into2D() {
}), TestSuite::Compare::Container);
}
void FlattenTransformationHierarchyTest::into3D() {
void HierarchyTest::absoluteFieldTransformationsInto3D() {
auto&& data = IntoData[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -460,14 +460,14 @@ void FlattenTransformationHierarchyTest::into3D() {
/* To test all overloads */
if(data.globalTransformation3D != Matrix4{}) {
if(data.fieldIdInsteadOfName)
flattenTransformationHierarchy3DInto(scene, 2, out, data.globalTransformation3D);
absoluteFieldTransformations3DInto(scene, 2, out, data.globalTransformation3D);
else
flattenTransformationHierarchy3DInto(scene, Trade::SceneField::Mesh, out, data.globalTransformation3D);
absoluteFieldTransformations3DInto(scene, Trade::SceneField::Mesh, out, data.globalTransformation3D);
} else {
if(data.fieldIdInsteadOfName)
flattenTransformationHierarchy3DInto(scene, 2, out);
absoluteFieldTransformations3DInto(scene, 2, out);
else
flattenTransformationHierarchy3DInto(scene, Trade::SceneField::Mesh, out);
absoluteFieldTransformations3DInto(scene, Trade::SceneField::Mesh, out);
}
CORRADE_COMPARE_AS(out, Containers::arrayView<Matrix4>({
@ -487,7 +487,7 @@ void FlattenTransformationHierarchyTest::into3D() {
}), TestSuite::Compare::Container);
}
void FlattenTransformationHierarchyTest::intoInvalidSize() {
void HierarchyTest::absoluteFieldTransformationsIntoInvalidSize() {
CORRADE_SKIP_IF_NO_ASSERT();
struct Data {
@ -515,17 +515,17 @@ void FlattenTransformationHierarchyTest::intoInvalidSize() {
std::ostringstream out;
Error redirectError{&out};
flattenTransformationHierarchy2DInto(scene2D, Trade::SceneField::Mesh, transformations2D);
flattenTransformationHierarchy2DInto(scene2D, 1, transformations2D);
flattenTransformationHierarchy3DInto(scene3D, Trade::SceneField::Mesh, transformations3D);
flattenTransformationHierarchy3DInto(scene3D, 1, transformations3D);
absoluteFieldTransformations2DInto(scene2D, Trade::SceneField::Mesh, transformations2D);
absoluteFieldTransformations2DInto(scene2D, 1, transformations2D);
absoluteFieldTransformations3DInto(scene3D, Trade::SceneField::Mesh, transformations3D);
absoluteFieldTransformations3DInto(scene3D, 1, transformations3D);
CORRADE_COMPARE(out.str(),
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 6\n"
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 6\n"
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 4\n"
"SceneTools::flattenTransformationHierarchyInto(): bad output size, expected 5 but got 4\n");
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 6\n"
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 6\n"
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 4\n"
"SceneTools::absoluteFieldTransformationsInto(): bad output size, expected 5 but got 4\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::SceneTools::Test::FlattenTransformationHierarchyTest)
CORRADE_TEST_MAIN(Magnum::SceneTools::Test::HierarchyTest)

10
src/Magnum/SceneTools/sceneconverter.cpp

@ -38,7 +38,7 @@
#include "Magnum/MeshTools/Reference.h"
#include "Magnum/MeshTools/RemoveDuplicates.h"
#include "Magnum/MeshTools/Transform.h"
#include "Magnum/SceneTools/FlattenTransformationHierarchy.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/MeshData.h"
#include "Magnum/Trade/AbstractImageConverter.h"
@ -311,9 +311,9 @@ on meshes and materials before passing them to any converter.
If `--concatenate-meshes` is given, all meshes of the input file are
first concatenated into a single mesh using @ref MeshTools::concatenate(), with
the scene hierarchy transformation baked in using
@ref SceneTools::flattenTransformationHierarchy3D(), and then passed through
the remaining operations. Only attributes that are present in the first mesh
are taken, if `--only-mesh-attributes` is specified as well, the IDs reference
@ref SceneTools::absoluteFieldTransformations3D(), and then passed through the
remaining operations. Only attributes that are present in the first mesh are
taken, if `--only-mesh-attributes` is specified as well, the IDs reference
attributes of the first mesh.
*/
@ -820,7 +820,7 @@ well, the IDs reference attributes of the first mesh.)")
Containers::Array<Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>>
meshesMaterials = scene->meshesMaterialsAsArray();
Containers::Array<Matrix4> transformations =
SceneTools::flattenTransformationHierarchy3D(*scene, Trade::SceneField::Mesh);
SceneTools::absoluteFieldTransformations3D(*scene, Trade::SceneField::Mesh);
Containers::Array<Trade::MeshData> flattenedMeshes;
{
Trade::Implementation::Duration d{conversionTime};

Loading…
Cancel
Save