Browse Source

[wip] Trade: ability to feed a whole importer to a scene converter.

TOOD: all the TODOs
sceneconverter
Vladimír Vondruš 4 years ago
parent
commit
575bbb1dec
  1. 109
      src/Magnum/Trade/AbstractSceneConverter.cpp
  2. 76
      src/Magnum/Trade/AbstractSceneConverter.h

109
src/Magnum/Trade/AbstractSceneConverter.cpp

@ -39,7 +39,9 @@
#include "Magnum/Trade/ArrayAllocator.h" #include "Magnum/Trade/ArrayAllocator.h"
#include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/ImageData.h"
#include "Magnum/Trade/MeshData.h" #include "Magnum/Trade/MeshData.h"
#include "Magnum/Trade/MaterialData.h"
#include "Magnum/Trade/SceneData.h" #include "Magnum/Trade/SceneData.h"
#include "Magnum/Trade/TextureData.h"
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/* needed by deprecated convertToFile() that takes a std::string */ /* needed by deprecated convertToFile() that takes a std::string */
@ -1224,6 +1226,113 @@ Containers::Optional<UnsignedInt> AbstractSceneConverter::add(const Containers::
// return add(Containers::arrayView(imageLevels), {}); // return add(Containers::arrayView(imageLevels), {});
// } // }
bool AbstractSceneConverter::addImporterContents(AbstractImporter& importer, const SceneConverterContents contents) {
// TODO assert if begin called
// TODO assert if importer opened
// TODO assert about features? or leave that on the called funs
if(contents & SceneConverterContent::Scenes) {
/* Propagate object names, skip ones that are empty */
for(UnsignedLong i = 0, iMax = importer.objectCount(); i != iMax; ++i) {
if(const Containers::String name = importer.objectName(i))
setObjectName(i, name);
}
for(UnsignedInt i = 0, iMax = importer.sceneCount(); i != iMax; ++i) {
Containers::Optional<Trade::SceneData> scene = importer.scene(i);
if(!scene) return false;
for(UnsignedInt j = 0; j != scene->fieldCount(); ++j) {
// TODO how to filter them to not call the name again and again?!
const Trade::SceneField name = scene->fieldName(j);
if(!isSceneFieldCustom(name)) continue;
if(const Containers::String nameString = importer.sceneFieldName(name)) {
!Debug{};
setSceneFieldName(name, nameString);
}
}
if(!scene || !add(*scene, importer.sceneName(i)))
return false;
}
}
if(contents & SceneConverterContent::Meshes) {
// TODO levels?!
for(UnsignedInt i = 0, iMax = importer.meshCount(); i != iMax; ++i) {
// TODO attribute names, how to filter them to not call the name again
// and again?!
Containers::Optional<Trade::MeshData> mesh = importer.mesh(i);
if(!mesh || !add(*mesh, importer.meshName(i)))
return false;
}
}
if(contents & (SceneConverterContent::Images3D|SceneConverterContent::CompressedImages3D)) {
// TODO levels?!
for(UnsignedInt i = 0, iMax = importer.image3DCount(); i != iMax; ++i) {
// TODO skip what's compressed (and converter doesn't support) and
// vice versa
Containers::Optional<Trade::ImageData3D> image = importer.image3D(i);
if(!image || !add(*image, importer.image3DName(i)))
return false;
}
}
if(contents & SceneConverterContent::Textures) {
for(UnsignedInt i = 0, iMax = importer.textureCount(); i != iMax; ++i) {
Containers::Optional<Trade::TextureData> texture = importer.texture(i);
if(!texture || !add(*texture, importer.textureName(i)))
return false;
}
}
if(contents & SceneConverterContent::Materials) {
for(UnsignedInt i = 0, iMax = importer.materialCount(); i != iMax; ++i) {
// TODO attribute names, how to filter them to not call the name again
// and again?!
Containers::Optional<Trade::MaterialData> material = importer.material(i);
if(!material || !add(*material, importer.materialName(i)))
return false;
}
}
// TODO rest
return true;
}
bool AbstractSceneConverter::addSupportedImporterContents(AbstractImporter& importer, const SceneConverterContents contents) {
SceneConverterContents filteredContents;
const SceneConverterFeatures features = this->features();
#define _c(name) \
if(features & SceneConverterFeature::Add ## name) \
filteredContents |= SceneConverterContent::name;
_c(Scenes)
_c(Animations)
_c(Lights)
_c(Cameras)
_c(Skins2D)
_c(Skins3D)
_c(Meshes)
_c(Materials)
_c(Textures)
_c(Images1D)
_c(Images2D)
_c(Images3D)
_c(CompressedImages1D)
_c(CompressedImages2D)
_c(CompressedImages2D)
#undef _c
if(features & SceneConverterFeature::MeshLevels)
filteredContents |= SceneConverterContent::ExtraMeshLevels;
if(features & SceneConverterFeature::ImageLevels)
filteredContents |= SceneConverterContent::ExtraImageLevels;
// TODO be sure to test this
return addImporterContents(importer, filteredContents & contents);
}
Debug& operator<<(Debug& debug, const SceneConverterFeature value) { Debug& operator<<(Debug& debug, const SceneConverterFeature value) {
debug << "Trade::SceneConverterFeature" << Debug::nospace; debug << "Trade::SceneConverterFeature" << Debug::nospace;

76
src/Magnum/Trade/AbstractSceneConverter.h

@ -311,6 +311,49 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneConverterFlag value);
*/ */
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneConverterFlags value); MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneConverterFlags value);
/**
@brief Contents to use for scene conversion
@m_since_latest
@see @ref SceneConverterContents,
@ref AbstractSceneConverter::addImporterContents(),
@ref AbstractSceneConverter::addSupportedImporterContents()
*/
enum class SceneConverterContent: UnsignedInt {
Scenes = 1 << 0, // TODO ... and default scene?
Animations = 1 << 1,
Lights = 1 << 2,
Cameras = 1 << 3,
Skins2D = 1 << 4,
Skins3D = 1 << 5,
Meshes = 1 << 6,
Materials = 1 << 7,
Textures = 1 << 8,
Images1D = 1 << 9,
Images2D = 1 << 10,
Images3D = 1 << 11,
CompressedImages1D = 1 << 12,
CompressedImages2D = 1 << 13,
CompressedImages3D = 1 << 14,
ExtraMeshLevels = 1 << 15, // TODO what to do here? just the first one if not?
ExtraImageLevels = 1 << 16
// TODO Names ?! or, rather, NoNames?!
// TODO or have that as a global flag, IgnoreNames, for smaller output?
// TODO what about scene parts? "only mesh and material assignment", "no custom fields", ...? i guess better done separately
};
/**
@brief Parts to import for scene conversion
@m_since_latest
@see @ref AbstractSceneConverter::addImporterContents(),
@ref AbstractSceneConverter::addSupportedImporterContents()
*/
typedef Containers::EnumSet<SceneConverterContent> SceneConverterContents;
CORRADE_ENUMSET_OPERATORS(SceneConverterContents)
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
namespace Implementation { namespace Implementation {
/* Could be a concrete type as it's always only char, but that would mean /* Could be a concrete type as it's always only char, but that would mean
@ -1687,6 +1730,39 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract
// Containers::Optional<UnsignedInt> add(std::initializer_list<CompressedImageView3D> imageLevels); // Containers::Optional<UnsignedInt> add(std::initializer_list<CompressedImageView3D> imageLevels);
// #endif // #endif
/**
* @brief Add importer contents
* @m_since_latest
*
* Convenience function for querying @p importer for particular data
* and feeding them to various `add*()` and `set*()` functions.
*
* Expects that a conversion is currently in progress and for every
* @ref SceneConverterContent in @p contents a corresponding feature is
* supported.
* @see @ref addSupportedImporterContents()
*/
bool addImporterContents(AbstractImporter& importer, SceneConverterContents contents);
// TODO mention that Count gets updated after (?!)
// TODO document behavior if something fails -- continue or abruptly fail? uhhh
// take this as a convenience feature and if more detailed behavior is
// needed, use the functions directly?!
// TODO some doAddImporter() thing for e.g. glTF JSON
// being directly reused (or not)? or not at all?
// seems like needless pain, honestly :(
// TODO or maybe if it would just get some importer-specific extras
// and leave the rest on the base implementation?
/**
* @brief Add supported importer contents
* @m_since_latest
*
* Filters @p contents based on supported @ref features() and delegates
* to @ref addImporterContents().
*/
bool addSupportedImporterContents(AbstractImporter& importer, SceneConverterContents contents = ~SceneConverterContents{});
protected: protected:
/** /**
* @brief Implementation for @ref convertToFile(const MeshData&, Containers::StringView) * @brief Implementation for @ref convertToFile(const MeshData&, Containers::StringView)

Loading…
Cancel
Save