So far this was only possible by creating a temporary MeshView, while
everything else (index/vertex count, base vertex, base instance, ...)
was changeable directly on the Mesh.
The web isn't broken enough yet, apparently. Support for both of those
extensions was added in early 2020 (and I think I remember even seeing
them listed as supported in some browsers), one of them was renamed
mere two months later, one in January 2023.
And I discovered just by accident, the browsers *of course* don't even
bother advertising both to have some transition period. Or maybe that
transition period happened, for 3 weeks in January, and if some
developer didn't notice in that time, "it's their fault". Or maybe it's
my fault, for attempting to use an extension that was stuck in a "draft
status" for four years. THE WHOLE WEB IS EITHER IN A "DRAFT STATUS" OR
"DEPRECATED", THERE'S NOTHING IN BETWEEN, FFS!
Constant needless churn, UGH.
As this is now documented, it means 3rd party code can now directly make
use of these without having to reinvent the same logic, or worse,
rediscover the same driver bugs.
The compatibility.glsl file however stays private -- I don't expect
real-world projects needing *that much* diversity in their supported
GLSL versions, often the baseline is GLES 3.0 which makes a large part
of the file unnecessary, and the projects might choose to for example
always have implicitly queried uniform locations to not have to
maintain two code paths.
It should be returning twice the value, this is the half-angle. Sad that
this went unnoticed for so long, extra bad points for me to have a
complicated test but not actually verifying that the returned value
makes sense, sigh.
A *nasty* option would be to just fix it, but -- even though there's a
chance nonbody ever used it since nobody ever complained -- it would
introduce breakages to any code that fixed it and that's something to
definitely not do in a trusted codebase. So it's instead deprecated,
firing an annoying warning to whoever might have called it, and there's
a (temporary) replacement called halfAngle() that does exactly the same
but is named appropriately.
Then, once the deprecated angle() is removed (the usual deprecation
period, so a year or the span of two releases, whichever takes longer)
and enough time passes (so another year at least), I'll reintroduce it
with a correct return value.
Same as the corresponding Corrade change. Should make
MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS working also in cases where Magnum is
linked to just DLLs but not the main application executable. Such as
various plugins or native Python modules.
It isn't a nice UX to force users to hardcode a DLL name of their own
application when building a *dependency library*, but is a simple enough
middle ground between global symbol deduplication not working at all and
having to loop through all possible DLLs with EnumProcessModules() until
a symbol is found.
Originally it was just assuming that any Vector3ub or Color3ub is a
normalized format. That was kinda enough for many cases, but it started
to get annoying with sRGB image comparisons, as those had to be
manually reinterpret with a sRGB-less format in order to pass.
Now the pixel format detection looks at the expected image format as
well, and if the underlying type and component count matches, it
inherits the sRGB and normalized property from it as well. If not, it
falls back to an integer format for vectors, and normalized format for
colors. For vectors this is different from previous behavior but
shouldn't cause any problem in practice -- the only result will be that
the image comparison fails with a different message for pixel format
mismatch than before.
This now also properly and fully tests the pixelFormatFor() helper, and
adds a missing Color3 specialization of it.
Most of the testing scaffolding here is a preparation for the actually
complex formats like BC6/7 or ASTC. Also, it's great to be able to use
Magnum from Python to prepare data for testing the C++ Magnum APIs.
A bit sad it took me three years to invent the right name for this
utility, heh. Also moving it together with others to a new
MeshTools/Copy.h header because *this* is the mainly useful API, not
reference() / mutableReference().
MaterialTools and SceneTools will get similar copy() APIs doing the same
thing.
The new filterAttributes() API takes a BitArray, which makes the
internals a lot simpler -- no O(n^2) lookup, no growable arrays, and no
need to duplicate the same code in the ID- and name-based variants.
For consistency with MaterialTools and soon MeshTools, the APIs are
moved to a new Filter.h header, with the deprecated variants kept only
in the original FilterAttributes.h.
This is now the preferrable way to set options to plugins that get
delegated to from other plugins, instead of
Until now there wasn't a general command line interface to pass options
to plugins that get delegated to from other plugins, such as image
converters used by scene converters. Due to that limitation, e.g.
GltfSceneConverter had to add an [imageConverter] configuration group
that it then copied over to the chosen image converter. But such
approach obviously doesn't scale -- every converter would have to do the
same, would have to repeat the whole testing process, and basically the
same would need to be done for all importers delegating to image
plugins. Nightmare.
So there's now --set, which allows arbitrary options to be set for
arbitrary plugins, and that's the preferrable way now. To avoid having
to maintain two ways to do the same, the [imageConverter] group will get
removed eventually.
The main use case is being able to specify what concrete plugin gets
used for a particular alias, e.g. to be able to use SpngImporter instead
of PngImporter for faster PNG image loading.
So far the option is implemented only here, as the imageconverter,
shaderconverter and other tools don't really deal with plugins
that delegate to other plugins. Yet.
Useful for creating pixel formats with different channel count,
adding/removing the sRGB bit and such. Counterpart to
vertexFormat(VertexFormat, UnsignedInt, bool) that got added back in
2020.06 already.
The perf cost is just too great for these to be enabled always. The only
place where the assertions are kept always is in the batch APIs -- there
it's assumed the function is called on large enough data to offset this
overhead, plus since it's often dealing with large blocks of data the
memory safety is more important than various FP drifts which were the
usual case why other assertions were firing.
It compiles on GLES2 as well, but there it hits the massive PITA of
being unable to render to LUMINANXCE formats and GL_RED formats not
really being available everywhere.
I don't have the patience to fix that, and almost nobody needs to use
ES2 platforms nowadays, so this isn't really a priority.
So one can directly read it back on GLES without having to wrap the
texture in a framebuffer again.
This change also puts the framebuffer completeness check *before* the
clear() and bind() which makes it no longer emit a GL error. The error
is still silent though, which isn't nice. Gotta fix that eventually as
well.
This means I (and people making their own plugins) don't need to go and
update each and every plugin once the version in the interface string
gets bumped after a (silent) ABI break. Such as when new virtual
functions get added, as those often lead to strange crashes if the
plugins don't get rebuilt after.
The plugins will now use this macro, which means they'll
automatically embed an interface string that was present in the base
class header at build time. However, when the base class updates, the
previous string is still embedded in the plugin binary, which will then
fail to load -- this being automatic doesn't mean the original purpose
is lost. Subsequently rebuilding the plugins from source will make them
pick up the updated interface string again.
The article this API was originally based on assumes a scenario which
just *isn't* matching usual practices here, giving wrong results. Too
bad I didn't spend more time questioning the proof there and just
blindly assumed it's correct because everyone said so.
Won't be typing all that reasoning again in the commit message, see the
changelog entry and the comment in the test for details.
Taking Animation::TrackViewStorage wasn't really a good idea, as it
wasn't solving anything -- in order to create it, there needs to be a
TrackView of a concrete type first anyway, and even then it required a
lot of additional verbose typing.
The new constructors take basically what TrackView takes, plus there's
additionally a constructor that takes a typeless value view together
with explicitly specified value and result types, allowing a truly
type-erased usage. On the other hand, the templated variants directly
deduce the types without any additional typing, making the construction
similarly straightforward to e.g. SceneFieldData.
In case of the type-erased constructors, if the interpolator function
isn't supplied explicitly, an implicit one is picked based on the value
type, result type and interpolation. Not all combinations make sense of
course, so this is a new assertion point, however compared to the
previous way where the interpolator was picked from a *typed* TrackView,
this doesn't add any new restriction -- what asserted there, asserts now
as well, and additionally you can't have e.g. a Quaternion track with a
boolean result. I may also be eventually adding assertions to check that
the target name matches the result type -- so e.g. a rotation isn't
specified as an integer and such. Compared to newer APIs like MeshData,
MaterialData or SceneData the AnimationData API has a significant lack
of sanity asserts like this.
The `Type` was suggesting it'd be some C++ type, definitely not values
like Scaling3D or Translation2D, resulting in a significant "brain
autocompletion error" every time I was using that type.
Unfortunately on AnimationData the trackTargetType() couldn't similarly
get renamed to trackTarget() as there's already trackTarget() that
contains the node ID the target points to, so it's trackTargetName()
instead. Renaming trackTarget() to trackTargetId() wasn't an option as
that would be inconsistent with everything else (TextureTools::image(),
MaterialAttribute::BaseColorTexture, SceneField::Mesh are all IDs but
they don't have an `Id` suffix); renaming to AnimationTrackTargetName
would keep it insanely long and wouldn't make it consistent either
(MeshAttribute, SceneFIeld, MaterialAttribute are all referred to as
"names" yet they don't have a `Name` suffix).
So it has 32k values for custom targets, instead of just 127. This
makes it consistent with MeshAttribute, which also provides 32k values,
while SceneField has a whole 31-bit range to make it possible to store
arbitrary ECS identifiers as well.
Since this is an ABI break, I'm also shifting the values by 1 to have
zero used for an invalid value, consistently with SceneField,
MeshAttribute etc.