Browse Source

SceneTools: use a single temp allocation in flattenMeshHierarchy().

pull/542/merge
Vladimír Vondruš 4 years ago
parent
commit
8ed08d7733
  1. 41
      src/Magnum/SceneTools/FlattenMeshHierarchy.cpp

41
src/Magnum/SceneTools/FlattenMeshHierarchy.cpp

@ -26,7 +26,9 @@
#include "FlattenMeshHierarchy.h" #include "FlattenMeshHierarchy.h"
#include <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Containers/GrowableArray.h> #include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h> #include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/Triple.h> #include <Corrade/Containers/Triple.h>
@ -45,16 +47,16 @@ template<> struct SceneDataDimensionTraits<2> {
static bool isDimensions(const Trade::SceneData& scene) { static bool isDimensions(const Trade::SceneData& scene) {
return scene.is2D(); return scene.is2D();
} }
static Containers::Array<Containers::Pair<UnsignedInt, Matrix3>> transformationsAsArray(const Trade::SceneData& scene) { static void transformationsInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<UnsignedInt>& mappingDestination, const Containers::StridedArrayView1D<Matrix3>& transformationDestination) {
return scene.transformations2DAsArray(); return scene.transformations2DInto(mappingDestination, transformationDestination);
} }
}; };
template<> struct SceneDataDimensionTraits<3> { template<> struct SceneDataDimensionTraits<3> {
static bool isDimensions(const Trade::SceneData& scene) { static bool isDimensions(const Trade::SceneData& scene) {
return scene.is3D(); return scene.is3D();
} }
static Containers::Array<Containers::Pair<UnsignedInt, Matrix4>> transformationsAsArray(const Trade::SceneData& scene) { static void transformationsInto(const Trade::SceneData& scene, const Containers::StridedArrayView1D<UnsignedInt>& mappingDestination, const Containers::StridedArrayView1D<Matrix4>& transformationDestination) {
return scene.transformations3DAsArray(); return scene.transformations3DInto(mappingDestination, transformationDestination);
} }
}; };
@ -62,7 +64,8 @@ template<UnsignedInt dimensions>
Containers::Array<Containers::Triple<UnsignedInt, Int, MatrixTypeFor<dimensions, Float>>> flattenMeshHierarchyImplementation(const Trade::SceneData& scene, const MatrixTypeFor<dimensions, Float>& globalTransformation) { Containers::Array<Containers::Triple<UnsignedInt, Int, MatrixTypeFor<dimensions, Float>>> flattenMeshHierarchyImplementation(const Trade::SceneData& scene, const MatrixTypeFor<dimensions, Float>& globalTransformation) {
CORRADE_ASSERT(SceneDataDimensionTraits<dimensions>::isDimensions(scene), CORRADE_ASSERT(SceneDataDimensionTraits<dimensions>::isDimensions(scene),
"SceneTools::flattenMeshHierarchy(): the scene is not" << dimensions << Debug::nospace << "D", {}); "SceneTools::flattenMeshHierarchy(): the scene is not" << dimensions << Debug::nospace << "D", {});
CORRADE_ASSERT(scene.hasField(Trade::SceneField::Parent), const Containers::Optional<UnsignedInt> parentFieldId = scene.findFieldId(Trade::SceneField::Parent);
CORRADE_ASSERT(parentFieldId,
"SceneTools::flattenMeshHierarchy(): the scene has no hierarchy", {}); "SceneTools::flattenMeshHierarchy(): the scene has no hierarchy", {});
/* If there's no mesh field in the file, nothing to do. Another case is /* If there's no mesh field in the file, nothing to do. Another case is
@ -70,16 +73,32 @@ Containers::Array<Containers::Triple<UnsignedInt, Int, MatrixTypeFor<dimensions,
go through everything. */ go through everything. */
if(!scene.hasField(Trade::SceneField::Mesh)) return {}; if(!scene.hasField(Trade::SceneField::Mesh)) return {};
Containers::Array<Containers::Pair<UnsignedInt, Int>> orderedClusteredParents = orderClusterParents(scene); /* Allocate a single storage for all temporary data */
Containers::ArrayView<Containers::Pair<UnsignedInt, Int>> orderedClusteredParents;
Containers::ArrayView<Containers::Pair<UnsignedInt, MatrixTypeFor<dimensions, Float>>> transformations;
Containers::ArrayView<MatrixTypeFor<dimensions, Float>> absoluteTransformations;
Containers::ArrayTuple storage{
/* Output of orderClusterParentsInto() */
{NoInit, scene.fieldSize(*parentFieldId), orderedClusteredParents},
/* Output of scene.transformationsXDInto() */
{NoInit, scene.transformationFieldSize(), transformations},
/* Above transformations but indexed by object ID */
{ValueInit, std::size_t(scene.mappingBound() + 1), absoluteTransformations}
};
/* Explicit slice() template parameters needed by GCC 4.8 and MSVC 2015 */
orderClusterParentsInto(scene,
stridedArrayView(orderedClusteredParents).slice<UnsignedInt>(&Containers::Pair<UnsignedInt, Int>::first),
stridedArrayView(orderedClusteredParents).slice<Int>(&Containers::Pair<UnsignedInt, Int>::second));
SceneDataDimensionTraits<dimensions>::transformationsInto(scene,
stridedArrayView(transformations).template slice<UnsignedInt>(&Containers::Pair<UnsignedInt, MatrixTypeFor<dimensions, Float>>::first),
stridedArrayView(transformations).template slice<MatrixTypeFor<dimensions, Float>>(&Containers::Pair<UnsignedInt, MatrixTypeFor<dimensions, Float>>::second));
/* Retrieve transformations of all objects, indexed by object ID. Since not /* Retrieve transformations of all objects, indexed by object ID. Since not
all nodes in the hierarchy may have a transformation assigned, all nodes in the hierarchy may have a transformation assigned, the whole
initialize the whole array to identity first. */ array got initialized to identity first. */
/** @todo switch to a hashmap eventually? */ /** @todo switch to a hashmap eventually? */
Containers::Array<MatrixTypeFor<dimensions, Float>> absoluteTransformations{DefaultInit, scene.mappingBound() + 1};
absoluteTransformations[0] = globalTransformation; absoluteTransformations[0] = globalTransformation;
/** @todo switch to *Into() in a loop to avoid temp allocations */ for(const Containers::Pair<UnsignedInt, MatrixTypeFor<dimensions, Float>>& transformation: transformations) {
for(const Containers::Pair<UnsignedInt, MatrixTypeFor<dimensions, Float>>& transformation: SceneDataDimensionTraits<dimensions>::transformationsAsArray(scene)) {
CORRADE_INTERNAL_ASSERT(transformation.first() < scene.mappingBound()); CORRADE_INTERNAL_ASSERT(transformation.first() < scene.mappingBound());
absoluteTransformations[transformation.first() + 1] = transformation.second(); absoluteTransformations[transformation.first() + 1] = transformation.second();
} }

Loading…
Cancel
Save