At first I attempted to make the whole thing reinterpret_cast-able from
a blob of memory (i.e., truly zero-overhead), but while that sounded
cool and all, it moved the overhead to basically all other code -- each
function had to special-case access to attribute/vertex/index data as
the pointers were no longer pointers, the binary representation had
various weird unexplainable gaps ("here an array deleter is stored, set
that to null and don't ask"), release*() functions got more complicated
and when I got to issues with move construction/assignment I knew this
was not the right path.
Now the MeshData internals are packed to a much more compact
representation (with the first attempt it was 128 bytes, now it's just
64) and the serialization doesn't make everything else slower, more
complex or harder to test, which is a win.
Put the pointer that differs in size on 32 and 64bit platforms last so
we have at least the prefix always stable. This also makes it possible
to extend the class to store 8/16 bytes of arbitrary data in there
(bounds etc.). Not doing that yet, just preparing for possible
extension.
This code was apparently done before the batch casters were a thing. Now
it's no reason to do the same in two places, additionally in the future
the castInto() could get SIMD-optimized and this can benefit from that.
Originally wanted to offload this to someone else, but then realized I
need those for generic vertex attribute definitions, which I need for
instancing, which I need now. So here it is, at the bottom of the
dependency chain.
It now supports both color+texture (instead of just one or the other)
which made it much simpler to use (and implement as well), also can
reference normal maps and specify texture coordinate transformation now.
The old APIs are depecated, but no tests or other code is updated yet in
order to ensure everything continues to work as before.
Until now, except for an attribute-less index-less mesh, the vertex
count was only implicitly taken from passed attributes, but it was
severely limiting:
- There was no way to set vertex count for an attribute-less
indexed mesh, which didn't make sense
- All code that made non-owning MeshData instances referencing another
MeshData had to explicitly handle the attribute-less corner case to
avoid vertex count getting lost
- Offset-only attributes couldn't be used to specify static layout of
meshes with dynamic vertex count, causing unnecessary extra
allocations especially in the Primitives library.
Similar to image mip level import, but this is largely left to be
importer-specific. For example PLY defines per-face data and sometimes
one might want to import them as-is, without them being turned into a
per-vertex property.
Originally this was done in order to make handling of deserialized data
much simpler (as for those attributes also need to only contain an
offset into some unknown data array), but seems this could be very
useful elsewhere as well -- for example when the layout is known
beforehand but the actual data not yet -- such as in the Line and
Gradient primitives (going to switch them to this in the next commit).
What still unfortunately has to be known in advance is the actual vertex
count (as supplying it directly to MeshData would mean adding 6 new
constructor overloads, and there's enough of those already). Might
revisit later.