They're each a totally different beast and putting them into the same
test file doesn't really make sense:
- We want to link certain plugins statically on static builds to test
certain code paths in the implementation. However this is
counter-productive for the executable tests because there we are
checking for plugin presence from the test with the assumption that
the executable and the test have the exact same set of plugins
available (or linked statically).
- The executable tests are implemented on Unix only at the moment,
thus it's wasteful to try to build it on any other platforms. Having
it in a separate file makes it much easier to deal with.
Because storing arbitrary data as a string was not good:
- It *never* followed alignment requirements due to the last byte being
used for size. Instead the size is now stored before the data, and
thus the data is always on the 64 byte boundary.
- As it could contain arbitrary binary data, it could cause
magnum-sceneconverter --material-info to print garbage, corrupt the
terminal or, worst case, crash. Not good.
- It stored an implicit \0, which was unnecessary.
Makes a lot of use cases significantly simpler -- apart from the trivial
"convert an OBJ to a glTF" scenario, many processing steps are about
passing most data through but only doing a pass on meshes, or images, or
materials. And this simplifies that use case quite a lot.
This is only "driver" code, with no new interfaces for the plugins. For
them it still looks like all data, their names and related metadata were
added one by one.
Also, a suprisingly large amount of code for this feature.
Funny/sad that this possibility took me so long to realize. Until now it
was "you can have command-line utilities or static plugins but never
both", and only with CMake 3.13+ it was possible to link static plugins
to these executables from outside. Now it's a builtin and supported
option.
For some reason, it was adding also the magnum / magnum-d directory,
which isn't really useful, especially in cases where the directory is
not at all or it's desired to pick a debug plugin from a release
executable and vice versa.
Also the distancefieldconverter was still attempting to join with an
absolute path -- somehow 7fb63a9434 missed
this one.
I really need to write regression tests for all this, sigh.
It was quite a pile, and all of it was written just once, relying only
on hopefully-available model files that would hopefully touch most code
paths. Which means, extremely annoying to make changes in.
I extracted the code to a header that can be tested with a mocked-up
importer and without having to execute the utility itself, deduplicated
the image info printing code, fixed various inconsistencies (such as
data/field flags sometimes denoted with superfluous "flags:" and
sometimes not) and TODOs (such as 2D/3D skins, where there was no format
whatsoever that would have 2D skin support, so the code couldn't get
written).
Now it's finally possible to easily add the remaining missing features,
such as printing camera info.
This happened because I made an early implementation of the batch
AbstractSceneConverter APIs, stashed it away, then implemented image
flags and then continued working on the stash, unaware that it's
outdated.
The enum-to-string conversion was just a private API and we need to use
it in various material filtering code. It was also a private class member
for some reason, even though it has no relation to / dependency on the
MaterialData class. So it's made a free function instead.
The MeshData and SceneData find APIs had the complexity documented, do
the same for MaterialData too. Plus cross-link this API from
hasAttribute() / hasField() so it's easier to find.
Unlike most other options, where a plugin can support 3D but not 2D or
compressed but not uncompressed data, the "levels" option is orthogonal
to the rest -- if a format supports multi-level data, it obviously also
supports a case where there is just a single level, and if it supports
multi-level images, then it likely supports them for 1D, 2D and 3D, not
just some.
I used the same reasoning for the new SceneConverterFeatures interfaces
already, just "backporting" it here as well.
The bit pattern actually followed this already, but for some reason I
still went ahead and stamped out all possible combinations. Because
of that, nothing really changes on the ABI side either and the
deprecated aliases are now exactly as they were before, so no need to
bump the plugin interface version.
And properly test the behavior as well. While it's rare that a batch
and immediate conversions would be mixed on a single converter instance,
if it happens by accident it should not lead to unexpected internal
state.
Initially I thought there was no reason for this to fail, but then
realized AnySceneConverter would need it. And also any other plugin
relying on something external that might fail during initialization --
there's no other moment after plugin instantiation where it could
signalize a failure, and deferring that to the first add() call,
whichever would it be, is really not a sane idea.
Wasn't really possible to split this into multiple commits, so here's
the whole thing including delegation from and to the single-mesh APIs.
What's not done here and postponed for later is:
- an ability to feed the whole importer to it, filtering away data that
aren't supported by the converter
- corresponding changes in AbstractImageConverter, where it would now
primarily accept ImageData to future-proof for arbitrary extra
key/value data
Because it somewhat confusingly may have implied that it's really
composed of 8-bit bools, and not bits. The same reasoning was used to
pick the name for Corrade's Containers::BitArray.
Backwards compatibility aliases are in place as usual, however the
internal BoolVectorConverter is now BitVectorConverter and there
unfortunately cannot be any backwards compatibility. This breaks only
GLM and Eigen integration in the magnum-integration repo, which I'm
fixing immediately. I don't expect any user code to use this internal
helper. For regular vectors maybe, for this one definitely not.
They are required to have the same format already, so flags make sense
as well -- what's the point of saving a multi-level cube map with one of
the levels being just a 2D array, anyway?
With the intention that those will eventually contain also things like
YUp / YDown, PremultipliedAlpha and such.
This commit is mostly just busywork, wiring this into [Compressed]Image,
[Compressed]ImageView and Trade::ImageData and ensuring the flags get
correctly propagated during moves and conversions. Unfortunately in case
of Trade::ImageData it meant deprecating the current set of constructor
in order to insert an ImageFlags parameter before the importer state
pointer.
The only non-trivial piece of logic is when a 2D
[Compressed]ImageView gets converted to a 3D one, then the Array bit is
implicitly dropped, as 2D arrays of 1D images are not really a thing.
Instead, it's now possible to add new flags when doing the conversion --
for example to turn a 2D image to a (single-layer) 2D array image.
For consistency with how VertexFormat and other enum helpers are named.
The compressedBlockSize() and compressedBlockDataSize() is also renamed
to compressedPixelFormatBlockSize() and
compressedPixelFormatBlockDataSize().
While backwards compatibility aliases are in place, a breaking change
is that Image classes now look for pixelFormatSize() instead of
pixelSize(). This is used e.g. when passing GL::PixelFormat /
GL::PixelType to the image classes, instead of the generic PixelFormat.
While useful, it's unlikely that any project was defining their own
pixel format enum and pixelSize() for a D3D or Metal renderer or
whatnot, so the breakage should have no practical impact.
Allows creating a StridedArrayView slice on the sizes to feed them to
various algorithms, instead of first having to copy the sizes out to a
freshly allocated array.
This is what commit ca722eac6e should
have been.
Sorry for breaking a non-deprecated MSVC build once again. The reason it
"appeared to work" for me was that on deprecated builds, Manager.h
includes Manager.hpp for backwards compatibility. On non-deprecated it
doesn't and MSVC ends up dying on a linker error. But the problem was
not related to extern templates, the problem was that there was a
compiler-specific ifdef in the cpp file which exported the class for all
compilers but MSVC, somehow. And so when I removed extern template from
the header, it still worked everywhere, except MSVC and except a
non-deprecated build.
Similar to the change done in Corrade, see the commit for details:
878624ac36
Wow, this is probably the most backwards-compatibility code I've ever
written. Can't wait until I can drop all that.
The boring dry usage info grew significantly, and listing it as the
first thing on the page would scare people off. Put the examples first
instead, and for the imageconverter and sceneconverter add --info
listing examples, as that's what is eye-catchy.
Mirrors what's done in sceneconverter already. Use case is for example
resizing an image for a concrete mip level, then passing it through a
BC7 compressor, and finally exporting into a KTX2 container.