The conversion is done implicitly, thus this seemingly innocent code
would be allowed:
ImageReference2D reference = Image2D(...);
foo(reference.data()); // crash on access, data already deleted
Advantages:
* The enums were large (600-800 lines) and they polluted the header,
now they are in separate files (except for BufferTexture, which has
the enum small enough to be left in the same file).
* Image classes now don't need to include OpenGL headers, as they were
needed only for the enum values. With advantage of C++11's forward
enum declarations there is no need to include the enum headers
anywhere in implementation, only when particular values are needed.
* The values are now less verbose:
AbstractTexture::InternalFormat::RGB8 // before
TextureFormat::RGB8 // now
* Resolved another "trivial choice" problem (thanks @JanDupal for
introducing this term to me): how to specify the format if there are
ten ways to do it (some being massively confusing):
Image2D::Format f = AbstractImage::Format::RGB; // too long...
Image2D::Format f = Image3D::Format::RGBA; // why 3D? this works?
Image2D::Format f = BufferImage1D::Format::RGBA; // wat?
It is even worse (and more verbose) with textures:
Texture2D::InternalFormat f =
CubeMapTextureArray::InternalFormat::RGB8; // this is allowed?
To have consistent naming this change was done also with
BufferTexture::InternalFormat (now BufferTextureFormat), although there
were no trivial choice issues and the enum isn't too large. But at least
it is now less typing.
* They are now deinlined into source files, as most of the classes have
either heavy members (std::vector) or virtual methods.
* All of them are explicit now (that should be already done, don't know
why not).
* Passing huge classes by value and using move constructors to avoid
unnecessary copying.
In most cases the names aren't even supported/used and thus it is
wasteful to have them in all *Data classes. If the importer wants to
support them, it would reimplement *name() functions instead.
Buffered* hinted that it has something to do with caching, streaming or
whatever. "Buffer texture" is now also consistent with naming in
specification.
It is now ambiguous whether data passed as `std::int8_t` are of
Type::Byte, Type::ByteInteger or whatnot. The user now must explicitly
specify both format and type.
Thanks to DimensionTraits it is now possible to e.g. conveniently access
components by name or pass size as combination of vector and scalar:
GLsizei width = image.size().x();
image.setData({xy, 1}, ...);
Instead of previous inconvenient ways:
GLsizei width = image.size()[0];
Math::Vector2<GLsizei> size(xy, 1);
image.setData(size, ...);
Not using the specialized type for internal functions and storage, as it
wouldn't cause any other improvements. This way it is virtually possible
to forward-declare the specialized types without including them in the
headers.
Magnum.h now doesn't include anything except OpenGL headers, thus
changes in Math library don't trigger recompilation of everything, but
only of things really depending on it.
Math constants moved to separate file for similar reasons, de-inlined
some functions to remove the need for some #includes.
Sometimes something needs to modify the data (in similar way it modifies
e.g. MeshData) and there is no reason to forbid that, as the data must
be non-const for delete[] operator anyway. There might be slight problem
with ImageWrapper, which should be able to wrap const data, but
currently nothing needs it.
Long-standing TODO. It is better to have size first, because it is more
significant than type (e.g. because there are Vector4<T> specializations
and not VectorT<4> specializations). It is also IMHO easier for user to
distinguish/read the type than before:
Vector<float, 4> -> Vector4<float> // before
Vector<4, float> -> Vector4<float> // now
* Framebuffer related functions moved to Framebuffer class, thus
simplifying the data setting functions - removed setDimensions(),
more flexible setData() function.
* Allow to set data with explicit format specification, reorganized
function parameters to make these two setData() more similar.
* Now using new AbstractType::ComponentType enum instead of basic Type,
updated TypeTraits to return the new enum from imageType() function.
Checking whether given type can be used for mesh indices or image data
was always done like this, because it was also needed to get OpenGL type
ID for the type:
TypeTraits<typename TypeTraits<T>::IndexType>::glType()
This was cumbersome, now the check is done using function, which
returns the OpenGL type ID directly:
TypeTraits<T>::indexType()
Also replaced TextureType with imageType() and renamed glType() to just
type().
These classes are meant to be used in the same texture updating
functions as Trade::ImageData due to static polymorphism. In addition to
Trade::ImageData, which is read-only, these classes support updating the
dimensions and data. Image2D and ImageBuffer2D can update the data also
from framebuffer.
AbstractImporter now provides access to the data directly and doesn't
attempt to do any OpenGL stuff, thus making everything more transparent
and testable.
Start of AbstractImporter rework - Trade namespace will contain simple
classes usable for exchanging data with other formats, importers will
not depend on any OpenGL functionality, they will just provide access to
plain data.
Not using macro this time, as some classes could want only to disable
either copy or move and with macros this would become unintuitive and
error-prone.