diff --git a/doc/features.dox b/doc/features.dox
index eb8eccef4..e9328c959 100644
--- a/doc/features.dox
+++ b/doc/features.dox
@@ -26,10 +26,146 @@
namespace Magnum {
/** @page features Feature guide
-@brief Fundamental principles and design goals.
+@brief High-level introduction to design of the Magnum library and basic building blocks.
-Overview and tutorials of high-level feature groups in Magnum. It's not
-necessary to read through everything, pick only what you need.
+@tableofcontents
+
+@todoc FUCK OFF doxygen, why are you not able to link to Corrade, Corrade::Utility and Magnum/Math/ you dumb shit?!
+
+Before you continue further, here are the essential bits of knowledge to help
+you around.
+
+@section features-naming Library organization and naming scheme
+
+The @ref Magnum project consists of a library with core functionality and
+optional sub-libraries. Each library is in its own namespace, which corresponds
+to a sub-folder on the include path -- so e.g. things from @ref Magnum::Math
+are included from @m_class{m-doc} [Magnum/Math/](dir_d816e7cf853e6723911731706bcab386.html).
+@ref Magnum builds upon
+@m_class{m-doc-external} [Corrade](https://doc.magnum.graphics/corrade/), which
+provides platform abstraction, basic utilities and containers.
+
+To reduce redundant verbosity, references throughout the documentation and
+code in example snippets have the the root @ref Magnum and
+@m_class{m-doc-external} [Corrade](https://doc.magnum.graphics/corrade/namespaceCorrade.html)
+namespaces omitted. In other words, as if the following was done:
+
+@snippet Magnum.cpp features-using-namespace
+
+If Magnum is the primary library you're building your project on, it's
+recommended that you do the same --- we're careful to not pollute the root
+namespace with overly generic names. However, except for `Literals` namespaces,
+@cpp using @ce the subnamespaces is *not recommended*, as naming in those is
+deliberately picked short and may introduce conflicts (such as
+@relativeref{Corrade,Containers::String} vs
+@relativeref{Corrade,Utility::String} or @ref GL::PixelFormat vs
+@ref Vk::PixelFormat).
+
+If you frown upon the thought of @cpp using namespace Magnum @ce yet don't want
+to wear your fingers off by repeatedly writing @cpp Magnum:: @ce everywhere, a
+common shorthand that projects go with is the following --- similarly in spirit
+to @cb{.py} import numpy as np @ce:
+
+@snippet Magnum.cpp features-using-namespace-alias
+
+@section features-includes Include files and forward declarations
+
+Depending on where you come from, the @cpp #include @ce policy used by Magnum
+might either make you happy or freak you out. In short, there's no "include the
+world" file, and instead you're supposed to include dedicated headers for APIs
+you want to use. The main reason is compile times, and the speed gain from
+doing it this way is too great to be ignored.
+
+The general rule is that each top-level class has a corresponding include, so
+for example @ref Math::Matrix4 is included as @ref Magnum/Math/Matrix4.h. It's
+not always like that though, and to help you out, documentation of each
+namespace and class tells you what to include, and if particular namespace
+members are defined in different headers, then detailed docs of each has a
+corresponding @cpp #include @ce directive listed as well, ready to be copied.
+
+In order to have the includes actually independent of each other, most Magnum
+types are forward-declared, and where possible, the header only relies on
+forward declarations. Which means that often the type already exists as a
+declaration, and in order to actually use it, you have to include the concrete
+definition of it. If you don't, the compiler will complain about use of an
+incomplete type. For example:
+
+@snippet Magnum.cpp features-forward-declaration-use
+
+Of course not all headers can be written with just forward declarations, so
+there still are some transitive dependencies between headers (for example, the
+@ref Magnum/Math/Matrix4.h header pulls in @ref Magnum/Math/Vector4.h as well).
+But from most part this is an implementation detail and as such shouldn't be
+relied on.
+
+For happy compile times you're encouraged to rely on forward declarations in
+your code as well. See @ref compilation-forward-declarations for more
+information.
+
+@section features-debug-output Debug output
+
+One of the essential debugging workflows is inspection of variable contents by
+printing them out. Magnum defines a lot of new math types, enums and
+containers and it would be very painful if you had to loop over their contents
+or perform manual enum-to-string conversion every time you want to see what's
+inside.
+
+Because writing to standard output and printing values for debugging purposes
+are *distinct* use cases with potentially conflicting requirements (should an
+enum value get written as a number? or as a name? a fully qualified name?),
+Magnum *doesn't* provide @cpp operator<< @ce overloads for @ref std::ostream.
+
+Instead, there's @relativeref{Corrade,Utility::Debug}, for your typing
+convenience also aliased to just @ref Debug directly in the @ref Magnum
+namespace. On its own it's able to print builtin types, all usual C++
+containers as well as their Corrade equivalents. Magnum then implements debug
+printers for its own math types, basic structures and most enums, which get
+printed as fully-qualified names. For example:
+
+@m_class{m-code-figure}
+
+@parblock
+
+@snippet Magnum.cpp features-debug-output
+
+
+
+@m_class{m-nopad}
+
+@code{.shell-session}
+Image format is PixelFormat::RGBA8Srgb and size Vector(256, 192)
+Color of the bottom-left pixel is #33b27f
+@endcode
+
+@endparblock
+
+The main goal of this utility is convenience and readability --- values are
+implicitly delimited by spaces and ended with a newline, container contents
+written with commas etc. Check out the class documentation for advanced
+features like colors, output redirection or printing file/line info.
+
+@section features-examples Learn by example
+
+Before you do a deep dive into the documentation, and if you haven't done
+already, it's recommended to go through the Getting Started Guide and check out
+at least the first example:
+
+@m_class{m-row}
+
+@parblock
+
+@m_div{m-col-m-6} @m_div{m-button m-primary} @m_div{m-big}Getting Started@m_enddiv @m_div{m-small} bootstrap a basic project structure @m_enddiv @m_enddiv @m_enddiv
+
+@m_div{m-col-m-6} @m_div{m-button m-success} @m_div{m-big}Your First Triangle@m_enddiv @m_div{m-small} a step-by-step tutorial @m_enddiv @m_enddiv @m_enddiv
+
+@endparblock
+
+@section features-building-blocks Learn through documentation
+
+Each of the following pages provides a high-level description of a certain area
+of the library. It's recommended to read through these first to understand the
+overall principles and only then go to documentation of each concrete class and
+function.
- @subpage platform --- @copybrief platform
- @subpage types --- @copybrief types
diff --git a/doc/getting-started.dox b/doc/getting-started.dox
index 544bc2eb5..6d4f10506 100644
--- a/doc/getting-started.dox
+++ b/doc/getting-started.dox
@@ -345,11 +345,19 @@ See @ref platform for more information.
@section getting-started-tutorials Follow tutorials and learn the principles
Now that you have your first application up and running, the best way to
-continue is to render your first triangle. Then you can dig deeper and try
-other examples, read about @ref features "fundamental principles" in the
-documentation and start experimenting on your own!
+continue is to get familiar with the basic workflows and render your first
+triangle. Then you can dig deeper and try other examples, read about basic
+building blocks in the documentation and start experimenting on your own!
-@m_div{m-button m-success} @m_div{m-big}Your First Triangle@m_enddiv @m_div{m-small} a step-by-step tutorial @m_enddiv @m_enddiv
+@m_class{m-row}
+
+@parblock
+
+@m_div{m-col-m-6} @m_div{m-button m-info} @m_div{m-big}The Fundamentals@m_enddiv @m_div{m-small} make yourself comfortable first @m_enddiv @m_enddiv @m_enddiv
+
+@m_div{m-col-m-6} @m_div{m-button m-success} @m_div{m-big}Your First Triangle@m_enddiv @m_div{m-small} a step-by-step tutorial @m_enddiv @m_enddiv @m_enddiv
+
+@endparblock
@section getting-started-more Additional information
diff --git a/doc/snippets/Magnum.cpp b/doc/snippets/Magnum.cpp
index b76710945..67b66c8de 100644
--- a/doc/snippets/Magnum.cpp
+++ b/doc/snippets/Magnum.cpp
@@ -26,6 +26,7 @@
#include
#include "Magnum/Math/Color.h"
+#include "Magnum/Math/Matrix4.h"
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
@@ -37,6 +38,8 @@
#include "Magnum/GL/Texture.h"
#endif
+#define DOXYGEN_IGNORE(...) __VA_ARGS__
+
using namespace Magnum;
using namespace Magnum::Math::Literals;
@@ -64,6 +67,42 @@ class MeshResourceLoader: public AbstractResourceLoader {
int main() {
+{
+/* [features-using-namespace] */
+using namespace Corrade;
+using namespace Magnum;
+/* [features-using-namespace] */
+}
+
+{
+/* [features-using-namespace-alias] */
+namespace Cr = Corrade;
+namespace Mn = Magnum;
+/* [features-using-namespace-alias] */
+}
+
+{
+/* The same #include is already above so this shouldn't hurt */
+/* [features-forward-declaration-use] */
+#include /* only a Matrix4 forward declaration */
+#include /* the actual definition */
+
+DOXYGEN_IGNORE()
+
+Matrix4 a = Matrix4::translation({3.0f, 1.0f, 0.5f});
+/* [features-forward-declaration-use] */
+static_cast(a);
+}
+
+{
+/* [features-debug-output] */
+Image2D image = DOXYGEN_IGNORE(Image2D{{}, {}, {}});
+
+Debug{} << "Image format is" << image.format() << "and size" << image.size();
+Debug{} << "Color of the first pixel is" << image.pixels()[0][0];
+/* [features-debug-output] */
+}
+
{
std::nullptr_t data{};
/* [Image-pixels] */
diff --git a/doc/types.dox b/doc/types.dox
index 6831fec4b..6b055bb46 100644
--- a/doc/types.dox
+++ b/doc/types.dox
@@ -31,15 +31,19 @@ namespace Magnum {
@m_footernavigation
@m_keyword{Type system,,}
-The root @ref Magnum namespace defines a few aliases for essential math types.
-See its documentation for more information about usage.
+Magnum defines a variety of scalar, vector and matrix types. Most of the
+functionality is implemented using template classes in the @ref Math library,
+with the most common variants brought as typedefs into the root @ref Magnum
+namespace.
@section types-builtin Builtin types
-Magnum provides typedefs for builtin integral and floating-point arithmetic
-types to ensure portability (e.g. @ref Int is *always* 32bit), maintain
-consistency and reduce confusion (e.g. @ref std::int32_t, @cpp int @ce and
-@cpp GLint @ce all refer to the same type).
+Magnum provides its own typedefs for builtin integral and floating-point
+arithmetic types to ensure portability, maintain consistency and reduce
+confusion. E.g., the @ref Int typedef is guaranteed to *always* be 32-bit and
+Magnum's own code and documentation prefers to use it over a wild mixture of
+@ref std::int32_t, @cpp int @ce, @cpp GLint @ce and @cpp ALint @ce that all
+refer to the same type.
| Magnum type | Size | Equivalent GLSL type |
| ------------------ | -------------- | ----------------------- |
@@ -56,8 +60,8 @@ consistency and reduce confusion (e.g. @ref std::int32_t, @cpp int @ce and
| @ref Double | 64bit | @glsl double @ce |
Types not meant to be used in arithmetic (such as @cpp bool @ce or
-@cpp std::size_t @ce) or types which cannot be directly passed to GLSL shaders
-(such as @cpp long double @ce) have no typedefs.
+@cpp std::size_t @ce) or types which have no use in GPU computations (such as
+@cpp long double @ce) have no typedefs.
Types from the above table are then used to define other types. All following
types are aliases of corresponding types in @ref Math namespace. No suffix
@@ -121,11 +125,11 @@ about the differences.
@section types-binary Binary representation
-Scalar types with GLSL equivalent are verified to be exactly the same as
-corresponding `GL*` types. Matrix and vector classes have the same binary
-representation as corresponding array of numeric values without any additional
-data or padding (e.g. @cpp sizeof(Vector3i) == sizeof(Int[3]) @ce), all
-matrices are stored in column-major order.
+Scalar types with a GLSL equivalent are guaranteed to have exactly the same
+binary representation. Consequently, matrix and vector classes also have the
+same binary representation as corresponding array of numeric values without any
+additional data or padding (e.g. @cpp sizeof(Vector3i) == sizeof(Int[3]) @ce),
+all matrices are stored in column-major order.
This means that all scalar, matrix and vector types can be used directly for
filling GPU buffers and textures without any need for data extraction or