Browse Source

AnySceneConverter: support whole scene conversion.

pull/592/head
Vladimír Vondruš 4 years ago
parent
commit
89763380e1
  1. 3
      doc/changelog.dox
  2. 186
      src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp
  3. 55
      src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h
  4. 236
      src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp

3
doc/changelog.dox

@ -287,7 +287,8 @@ See also:
well as support in @ref Trade::AnySceneImporter "AnySceneImporter"
- The @ref Trade::AbstractSceneConverter plugin interface gained support for
batch conversion of whole scenes --- meshes, hierarchies, materials,
textures, animations and other data
textures, animations and other data; @relativeref{Trade,AnySceneConverter}
is updated to support batch conversion as well
- 1D and 3D image support in @ref Trade::AbstractImageConverter
- @ref Trade::LightData got extended to support light attenuation and range
parameters as well and spot light inner and outer angle

186
src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp

@ -25,15 +25,19 @@
#include "AnySceneConverter.h"
#include <Corrade/Containers/Iterable.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/PluginManager/PluginMetadata.h>
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/DebugStl.h> /* for PluginMetadata::name() */
#include <Corrade/Utility/Macros.h> /* CORRADE_UNUSED */
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/String.h>
#include "Magnum/Trade/ImageData.h"
#include "Magnum/Trade/MeshData.h"
#include "Magnum/Trade/SceneData.h"
#include "MagnumPlugins/Implementation/propagateConfiguration.h"
namespace Magnum { namespace Trade {
@ -47,7 +51,26 @@ AnySceneConverter::AnySceneConverter(PluginManager::AbstractManager& manager, co
AnySceneConverter::~AnySceneConverter() = default;
SceneConverterFeatures AnySceneConverter::doFeatures() const {
return SceneConverterFeature::ConvertMeshToFile;
/* Report that we can convert meshes and scenes to files, because that the
plugin can do always as it dispatches there. But everything else is
reported only once an actual converter plugin is loaded -- i.e., after beginFile() is called.
Additionally, to allow using beginFile() + add(MeshData) + endFile()
with converters that only support ConvertMeshToFile, we "fake" report
AddMesh supported as well. If we wouldn't, the base class would try to
go through convertToFile() instead, causing the mesh to not be delegated
to _converter->add() but instead supplied to a whole new plugin
instance. Then, upon delegating to _converter->endFile(), it would fail
due to having 0 meshes. */
SceneConverterFeatures delegatedFeatures =
_converter ? _converter->features() : SceneConverterFeatures{};
if(delegatedFeatures & SceneConverterFeature::ConvertMeshToFile)
delegatedFeatures |= SceneConverterFeature::AddMeshes;
return SceneConverterFeature::ConvertMeshToFile|
SceneConverterFeature::ConvertMultipleToFile|
delegatedFeatures;
}
bool AnySceneConverter::doConvertToFile(const MeshData& mesh, const Containers::StringView filename) {
@ -94,6 +117,165 @@ bool AnySceneConverter::doConvertToFile(const MeshData& mesh, const Containers::
return converter->convertToFile(mesh, filename);
}
void AnySceneConverter::doAbort() {
_converter->abort();
_converter = {};
}
bool AnySceneConverter::doBeginFile(const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager());
/* We don't detect any double extensions yet, so we can normalize just the
extension. In case we eventually might, it'd have to be split() instead
to save at least by normalizing just the filename and not the path. */
const Containers::String normalizedExtension = Utility::String::lowercase(Utility::Path::splitExtension(filename).second());
/* Detect the plugin from extension */
Containers::StringView plugin;
if(normalizedExtension == ".ply"_s)
plugin = "StanfordSceneConverter"_s;
else {
Error{} << "Trade::AnySceneConverter::beginFile(): cannot determine the format of" << filename;
return false;
}
/* Try to load the plugin */
if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) {
Error{} << "Trade::AnySceneConverter::beginFile(): cannot load the" << plugin << "plugin";
return false;
}
const PluginManager::PluginMetadata* const metadata = manager()->metadata(plugin);
CORRADE_INTERNAL_ASSERT(metadata);
if(flags() & SceneConverterFlag::Verbose) {
Debug d;
d << "Trade::AnySceneConverter::beginFile(): using" << plugin;
if(plugin != metadata->name())
d << "(provided by" << metadata->name() << Debug::nospace << ")";
}
/* Instantiate the plugin, propagate flags */
Containers::Pointer<AbstractSceneConverter> converter = static_cast<PluginManager::Manager<AbstractSceneConverter>*>(manager())->instantiate(plugin);
converter->setFlags(flags());
/* Propagate configuration */
Magnum::Implementation::propagateConfiguration("Trade::AnySceneConverter::beginFile():", {}, metadata->name(), configuration(), converter->configuration());
/* Try to begin the file (error output should be printed by the plugin
itself) */
if(!converter->beginFile(filename)) return false;
/* Success, save the instance */
_converter = std::move(converter);
return true;
}
bool AnySceneConverter::doEndFile(Containers::StringView) {
/* Destroy the converter instance after the operation finishes to avoid
keeping now-useless state around */
const bool out = _converter->endFile();
_converter = {};
return out;
}
/* It's easier to use CORRADE_UNUSED than to have #ifndef CORRADE_NO_ASSERT */
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const SceneData& scene, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->sceneCount());
return !!_converter->add(scene, name);
}
void AnySceneConverter::doSetSceneFieldName(const UnsignedInt field, const Containers::StringView name) {
return _converter->setSceneFieldName(sceneFieldCustom(field), name);
}
void AnySceneConverter::doSetObjectName(const UnsignedLong object, const Containers::StringView name) {
return _converter->setObjectName(object, name);
}
void AnySceneConverter::doSetDefaultScene(const UnsignedInt id) {
return _converter->setDefaultScene(id);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const AnimationData& animation, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->animationCount());
return !!_converter->add(animation, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const LightData& light, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->lightCount());
return !!_converter->add(light, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const CameraData& camera, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->cameraCount());
return !!_converter->add(camera, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const SkinData2D& skin, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->skin2DCount());
return !!_converter->add(skin, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const SkinData3D& skin, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->skin3DCount());
return !!_converter->add(skin, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const MeshData& mesh, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->meshCount());
return !!_converter->add(mesh, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const Containers::Iterable<const MeshData> meshLevels, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->meshCount());
return !!_converter->add(meshLevels, name);
}
void AnySceneConverter::doSetMeshAttributeName(const UnsignedShort attribute, const Containers::StringView name) {
return _converter->setMeshAttributeName(meshAttributeCustom(attribute), name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const MaterialData& material, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->materialCount());
return !!_converter->add(material, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const TextureData& texture, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->textureCount());
return !!_converter->add(texture, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const ImageData1D& image, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image1DCount());
return !!_converter->add(image, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const Containers::Iterable<const ImageData1D> imageLevels, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image1DCount());
return !!_converter->add(imageLevels, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const ImageData2D& image, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image2DCount());
return !!_converter->add(image, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const Containers::Iterable<const ImageData2D> imageLevels, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image2DCount());
return !!_converter->add(imageLevels, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const ImageData3D& image, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image3DCount());
return !!_converter->add(image, name);
}
bool AnySceneConverter::doAdd(CORRADE_UNUSED const UnsignedInt id, const Containers::Iterable<const ImageData3D> imageLevels, const Containers::StringView name) {
CORRADE_INTERNAL_ASSERT(id == _converter->image3DCount());
return !!_converter->add(imageLevels, name);
}
}}
CORRADE_PLUGIN_REGISTER(AnySceneConverter, Magnum::Trade::AnySceneConverter,

55
src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h

@ -30,6 +30,8 @@
* @m_since{2020,06}
*/
#include <Corrade/Containers/Pointer.h>
#include "Magnum/Trade/AbstractSceneConverter.h"
#include "MagnumPlugins/AnySceneConverter/configure.h"
@ -96,14 +98,20 @@ information.
@section Trade-AnySceneConverter-proxy Interface proxying and option propagation
On a call to @ref convertToFile(), a target file format is detected from the
extension and a corresponding plugin is loaded. After that, flags set via
@ref setFlags() and options set through @ref configuration() are propagated to
the concrete implementation, with a warning emitted in case given option is not
present in the default configuration of the target plugin.
On a call to @ref convertToFile() or @ref beginFile(), a target file format is
detected from the extension and a corresponding plugin is loaded. After that,
flags set via @ref setFlags() and options set through @ref configuration() are
propagated to the concrete implementation. A warning is emitted in case an
option set is not present in the default configuration of the target plugin.
The @ref features() initially report just
@ref SceneConverterFeature::ConvertMeshToFile and @relativeref{SceneConverterFeature,ConvertMultipleToFile} --- i.e., not
advertising support for any actual data types. These are included only once
@ref beginFile() is called, taken from the concrete plugin implementation.
The output of the @ref convertToFile() function called on the concrete
implementation is then proxied back.
Calls to the @ref endFile(), @ref add() and related functions are then proxied
to the concrete implementation. The @ref abort() function aborts and destroys
the internally instantiated plugin; @ref isConverting() works as usual.
*/
class MAGNUM_ANYSCENECONVERTER_EXPORT AnySceneConverter: public AbstractSceneConverter {
public:
@ -118,6 +126,39 @@ class MAGNUM_ANYSCENECONVERTER_EXPORT AnySceneConverter: public AbstractSceneCon
private:
MAGNUM_ANYSCENECONVERTER_LOCAL SceneConverterFeatures doFeatures() const override;
MAGNUM_ANYSCENECONVERTER_LOCAL bool doConvertToFile(const MeshData& mesh, Containers::StringView filename) override;
void doAbort() override;
bool doBeginFile(Containers::StringView filename) override;
bool doEndFile(Containers::StringView filename) override;
bool doAdd(UnsignedInt id, const SceneData& scene, Containers::StringView name) override;
void doSetSceneFieldName(UnsignedInt field, Containers::StringView name) override;
void doSetObjectName(UnsignedLong object, Containers::StringView name) override;
void doSetDefaultScene(UnsignedInt id) override;
bool doAdd(UnsignedInt id, const AnimationData& animation, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const LightData& light, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const CameraData& camera, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const SkinData2D& skin, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const SkinData3D& skin, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const MeshData& mesh, Containers::StringView name) override;
bool doAdd(UnsignedInt id, Containers::Iterable<const MeshData> meshLevels, Containers::StringView name) override;
void doSetMeshAttributeName(UnsignedShort attribute, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const MaterialData& material, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const TextureData& texture, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const ImageData1D& image, Containers::StringView name) override;
bool doAdd(UnsignedInt id, Containers::Iterable<const ImageData1D> imageLevels, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const ImageData2D& image, Containers::StringView name) override;
bool doAdd(UnsignedInt id, Containers::Iterable<const ImageData2D> imageLevels, Containers::StringView name) override;
bool doAdd(UnsignedInt id, const ImageData3D& image, Containers::StringView name) override;
bool doAdd(UnsignedInt id, Containers::Iterable<const ImageData3D> imageLevels, Containers::StringView name) override;
Containers::Pointer<AbstractSceneConverter> _converter;
};
}}

236
src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp

@ -24,6 +24,7 @@
*/
#include <sstream>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Tester.h>
@ -45,13 +46,21 @@ struct AnySceneConverterTest: TestSuite::Tester {
explicit AnySceneConverterTest();
void convert();
void detect();
void convertBeginEnd();
void unknown();
void detectConvert();
void detectBeginEnd();
void propagateFlags();
void propagateConfiguration();
void propagateConfigurationUnknown();
void unknownConvert();
void unknownBeginEnd();
void propagateFlagsConvert();
void propagateFlagsBeginEnd();
void propagateConfigurationConvert();
void propagateConfigurationBeginEnd();
void propagateConfigurationUnknownConvert();
void propagateConfigurationUnknownBeginEnd();
/* configuration propagation fully tested in AnySceneImporter, as there the
plugins have configuration subgroups as well */
@ -63,23 +72,42 @@ constexpr struct {
const char* name;
const char* filename;
const char* plugin;
} DetectData[]{
} DetectConvertData[]{
{"Stanford PLY", "bunny.ply", "StanfordSceneConverter"},
/* Have at least one test case with uppercase */
{"Stanford PLY uppercase", "ARMADI~1.PLY", "StanfordSceneConverter"}
};
constexpr struct {
const char* name;
const char* filename;
const char* plugin;
} DetectBeginEndData[]{
{"Stanford PLY", "bunny.ply", "StanfordSceneConverter"},
/* Have at least one test case with uppercase */
{"Stanford PLY uppercase", "ARMADI~1.PLY", "StanfordSceneConverter"}
};
AnySceneConverterTest::AnySceneConverterTest() {
addTests({&AnySceneConverterTest::convert});
addTests({&AnySceneConverterTest::convert,
&AnySceneConverterTest::convertBeginEnd});
addInstancedTests({&AnySceneConverterTest::detectConvert},
Containers::arraySize(DetectConvertData));
addInstancedTests({&AnySceneConverterTest::detectBeginEnd},
Containers::arraySize(DetectBeginEndData));
addInstancedTests({&AnySceneConverterTest::detect},
Containers::arraySize(DetectData));
addTests({&AnySceneConverterTest::unknownConvert,
&AnySceneConverterTest::unknownBeginEnd,
addTests({&AnySceneConverterTest::unknown,
&AnySceneConverterTest::propagateFlagsConvert,
&AnySceneConverterTest::propagateFlagsBeginEnd,
&AnySceneConverterTest::propagateFlags,
&AnySceneConverterTest::propagateConfiguration,
&AnySceneConverterTest::propagateConfigurationUnknown});
&AnySceneConverterTest::propagateConfigurationConvert,
&AnySceneConverterTest::propagateConfigurationBeginEnd,
&AnySceneConverterTest::propagateConfigurationUnknownConvert,
&AnySceneConverterTest::propagateConfigurationUnknownBeginEnd});
/* Load the plugin directly from the build tree. Otherwise it's static and
already loaded. */
@ -121,8 +149,41 @@ void AnySceneConverterTest::convert() {
CORRADE_COMPARE_AS(filename, Utility::Path::join(ANYSCENEIMPORTER_TEST_DIR, "triangle.ply"), TestSuite::Compare::File);
}
void AnySceneConverterTest::detect() {
auto&& data = DetectData[testCaseInstanceId()];
void AnySceneConverterTest::convertBeginEnd() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Catch also ABI and interface mismatch errors */
if(!(manager.load("StanfordSceneConverter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("StanfordSceneConverter plugin can't be loaded.");
Containers::String filename = Utility::Path::join(ANYSCENECONVERTER_TEST_OUTPUT_DIR, "file.ply");
if(Utility::Path::exists(filename))
CORRADE_VERIFY(Utility::Path::remove(filename));
const Vector3 positions[] {
{-0.5f, -0.5f, 0.0f},
{ 0.5f, -0.5f, 0.0f},
{ 0.0f, 0.5f, 0.0f}
};
const Trade::MeshData mesh{MeshPrimitive::Triangles, {}, positions, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(positions)}
}};
Containers::Pointer<AbstractSceneConverter> converter = manager.instantiate("AnySceneConverter");
CORRADE_VERIFY(converter->beginFile(filename));
CORRADE_COMPARE(converter->add(mesh), 0);
CORRADE_VERIFY(converter->endFile());
/* This file is reused in AnySceneImporter tests, so it's worth to save it
here */
CORRADE_COMPARE_AS(filename, Utility::Path::join(ANYSCENEIMPORTER_TEST_DIR, "triangle.ply"), TestSuite::Compare::File);
}
void AnySceneConverterTest::detectConvert() {
auto&& data = DetectConvertData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractSceneConverter> converter = _manager.instantiate("AnySceneConverter");
@ -143,7 +204,28 @@ void AnySceneConverterTest::detect() {
#endif
}
void AnySceneConverterTest::unknown() {
void AnySceneConverterTest::detectBeginEnd() {
auto&& data = DetectConvertData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractSceneConverter> converter = _manager.instantiate("AnySceneConverter");
std::ostringstream out;
Error redirectError{&out};
CORRADE_VERIFY(!converter->beginFile(data.filename));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
"Trade::AnySceneConverter::beginFile(): cannot load the {0} plugin\n",
data.plugin));
#else
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} was not found\n"
"Trade::AnySceneConverter::beginFile(): cannot load the {0} plugin\n", data.plugin));
#endif
}
void AnySceneConverterTest::unknownConvert() {
Containers::Pointer<AbstractSceneConverter> converter = _manager.instantiate("AnySceneConverter");
std::ostringstream out;
@ -152,7 +234,16 @@ void AnySceneConverterTest::unknown() {
CORRADE_COMPARE(out.str(), "Trade::AnySceneConverter::convertToFile(): cannot determine the format of mesh.obj\n");
}
void AnySceneConverterTest::propagateFlags() {
void AnySceneConverterTest::unknownBeginEnd() {
Containers::Pointer<AbstractSceneConverter> converter = _manager.instantiate("AnySceneConverter");
std::ostringstream out;
Error redirectError{&out};
CORRADE_VERIFY(!converter->beginFile("mesh.obj"));
CORRADE_COMPARE(out.str(), "Trade::AnySceneConverter::beginFile(): cannot determine the format of mesh.obj\n");
}
void AnySceneConverterTest::propagateFlagsConvert() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
@ -190,7 +281,47 @@ void AnySceneConverterTest::propagateFlags() {
CORRADE_SKIP("No plugin with verbose output available to test flag propagation.");
}
void AnySceneConverterTest::propagateConfiguration() {
void AnySceneConverterTest::propagateFlagsBeginEnd() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Catch also ABI and interface mismatch errors */
if(!(manager.load("StanfordSceneConverter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("StanfordSceneConverter plugin can't be loaded.");
Containers::String filename = Utility::Path::join(ANYSCENECONVERTER_TEST_OUTPUT_DIR, "file.ply");
const Vector3 positions[] {
{-0.5f, -0.5f, 0.0f},
{ 0.5f, -0.5f, 0.0f},
{ 0.0f, 0.5f, 0.0f}
};
const Trade::MeshData mesh{MeshPrimitive::Triangles, {}, positions, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(positions)}
}};
Containers::Pointer<AbstractSceneConverter> converter = manager.instantiate("AnySceneConverter");
converter->setFlags(SceneConverterFlag::Verbose);
std::ostringstream out;
{
Debug redirectOutput{&out};
CORRADE_VERIFY(converter->beginFile(filename));
}
CORRADE_VERIFY(converter->add(mesh));
CORRADE_VERIFY(converter->endFile());
CORRADE_VERIFY(Utility::Path::exists(filename));
CORRADE_COMPARE(out.str(),
"Trade::AnySceneConverter::beginFile(): using StanfordSceneConverter\n");
/* We tested AnySceneConverter's verbose output, but can't actually test
the flag propagation in any way yet */
CORRADE_SKIP("No plugin with verbose output available to test flag propagation.");
}
void AnySceneConverterTest::propagateConfigurationConvert() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
@ -223,7 +354,42 @@ void AnySceneConverterTest::propagateConfiguration() {
CORRADE_COMPARE_AS(filename, Utility::Path::join(ANYSCENECONVERTER_TEST_DIR, "objectid.ply"), TestSuite::Compare::File);
}
void AnySceneConverterTest::propagateConfigurationUnknown() {
void AnySceneConverterTest::propagateConfigurationBeginEnd() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Catch also ABI and interface mismatch errors */
if(!(manager.load("StanfordSceneConverter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("StanfordSceneConverter plugin can't be loaded.");
Containers::String filename = Utility::Path::join(ANYSCENECONVERTER_TEST_OUTPUT_DIR, "file.ply");
const struct Data {
Vector3 position;
UnsignedInt objectId;
} data[] {
{{-0.5f, -0.5f, 0.0f}, 4678},
{{ 0.5f, -0.5f, 0.0f}, 3232},
{{ 0.0f, 0.5f, 0.0f}, 1536}
};
const Trade::MeshData mesh{MeshPrimitive::Triangles, {}, data, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(data).slice(&Data::position)},
Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, Containers::stridedArrayView(data).slice(&Data::objectId)},
}};
Containers::Pointer<AbstractSceneConverter> converter = manager.instantiate("AnySceneConverter");
converter->configuration().setValue("objectIdAttribute", "OID");
CORRADE_VERIFY(converter->beginFile(filename));
CORRADE_VERIFY(converter->add(mesh));
CORRADE_VERIFY(converter->endFile());
/* Compare to an expected output to ensure the custom attribute name was
used */
CORRADE_COMPARE_AS(filename, Utility::Path::join(ANYSCENECONVERTER_TEST_DIR, "objectid.ply"), TestSuite::Compare::File);
}
void AnySceneConverterTest::propagateConfigurationUnknownConvert() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
@ -251,6 +417,38 @@ void AnySceneConverterTest::propagateConfigurationUnknown() {
CORRADE_COMPARE(out.str(), "Trade::AnySceneConverter::convertToFile(): option noSuchOption not recognized by StanfordSceneConverter\n");
}
void AnySceneConverterTest::propagateConfigurationUnknownBeginEnd() {
PluginManager::Manager<AbstractSceneConverter> manager{MAGNUM_PLUGINS_SCENECONVERTER_INSTALL_DIR};
#ifdef ANYSCENECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYSCENECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Catch also ABI and interface mismatch errors */
if(!(manager.load("StanfordSceneConverter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("StanfordSceneConverter plugin can't be loaded.");
const Vector3 positions[] {
{-0.5f, -0.5f, 0.0f},
{ 0.5f, -0.5f, 0.0f},
{ 0.0f, 0.5f, 0.0f}
};
const Trade::MeshData mesh{MeshPrimitive::Triangles, {}, positions, {
Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(positions)}
}};
Containers::Pointer<AbstractSceneConverter> converter = manager.instantiate("AnySceneConverter");
converter->configuration().setValue("noSuchOption", "isHere");
std::ostringstream out;
{
Warning redirectWarning{&out};
CORRADE_VERIFY(converter->beginFile(Utility::Path::join(ANYSCENECONVERTER_TEST_OUTPUT_DIR, "file.ply")));
}
CORRADE_VERIFY(converter->add(mesh));
CORRADE_VERIFY(converter->endFile());
CORRADE_COMPARE(out.str(), "Trade::AnySceneConverter::beginFile(): option noSuchOption not recognized by StanfordSceneConverter\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::Trade::Test::AnySceneConverterTest)

Loading…
Cancel
Save