Among oth­er high­lights is a new glTF play­er app, HiD­PI sup­port,
spline in­ter­po­la­tion, a Box2D ex­am­ple and pro­duc­tiv­i­ty im­prove­ments all
across the board.

When look­ing at the changel­og for the lat­est ver­sion, it’s hard to be­lieve that
on­ly six months passed since the last re­lease, 2018.04.
The list is — as usu­al — very long, so I’m on­ly cher­ry-pick­ing the most
in­ter­est­ing bits. Scroll way down for the full de­tailed change lists.

This long-await­ed fea­ture fi­nal­ly man­aged to rise to the top of the pri­or­i­ty
list and so the new re­lease con­tains a brand-new An­i­ma­tion names­pace.
Some de­sign ideas are bor­rowed from Ozz-An­i­ma­tion,
with one end goal be­ing high-per­for­mance play­back of an­i­ma­tions im­port­ed from
glTF files (with oth­er for­mats com­ing
lat­er). The oth­er goal is be­ing able to quick­ly it­er­ate on hand-craft­ed
an­i­ma­tions of ar­bi­trary val­ues when writ­ing a game­play or UI tran­si­tions.

The an­i­ma­tion li­brary sup­ports in­ter­leaved or sep­a­rate keyframe da­ta for
cache-op­ti­mized da­ta ac­cess; floats, std::chrono, frame in­dex
(or just any­thing) for rep­re­sent­ing time, and yes, you can al­so an­i­mate
strings, enum val­ues, bools or even the state of an­oth­er an­i­ma­tion —
and why not an­i­mat­ing a time val­ue to make the play­back non-lin­ear! There’s a
set of builtin in­ter­po­la­tion modes —
con­stant, lin­ear, spher­i­cal lin­ear and spline-based; but you can al­so sup­ply
your own in­ter­po­la­tor func­tion if you need some ease-in/ease-out, or, for
ex­am­ple, un­pack a quater­nion from a 10–10–10–2 rep­re­sen­ta­tion first.

At the mo­ment the An­i­ma­tion li­brary is marked as ex­per­i­men­tal
as its API is not set in stone yet. There’s a lot to ex­plain, so stay tuned for
de­tailed in­tro­duc­to­ry blog­posts (and ex­am­ples) for all fea­tures. For a brief
over­view, check the An­i­ma­tion::Track and An­i­ma­tion::Play­er class
docs.

An­i­ma­tion im­port is done through the new Trade::An­i­ma­tion­Da­ta class and
at the mo­ment the Trade::Ab­strac­tIm­porter in­ter­faces han­dle just ba­sic
ob­ject trans­for­ma­tion. Skin­ning and mor­ph­ing will need some more-or-less
break­ing changes to some Trade APIs and so these fea­tures are sched­uled
for next re­leas­es. Along with that, the goal for the Trade li­brary is
al­low­ing ze­ro-copy as­set im­port — for ex­am­ple play­ing back an an­i­ma­tion
di­rect­ly from a mem­o­ry-mapped glTF file, with no da­ta copies in be­tween. See
mosra/mag­num#240 for fur­ther work in this area.

The fun barely started!

I had to stop adding new fea­tures be­cause the re­lease would oth­er­wise nev­er
make it out. There’s al­ready more in the buf­fer — builtin eas­ing
func­tions, in­ter­po­la­tor chain­ing and more. See mosra/mag­num#101help want­ed for de­tails. There’s lot of small and
self-con­tained things to work on, so if you feel brave and want to help,
let us know!

While the An­i­ma­tion API it­self doesn’t have any ded­i­cat­ed ex­am­ple yet,
there’s now a new app, Mag­num Play­er, that can play back a scene file
you throw at it. The fi­nal goal for this app will be show­cas­ing the full Mag­num
fea­ture set — de­bug­ging and in­tro­spec­tion tools, ma­te­ri­al tweak­ing etc. Check
out the on­line ver­sion be­low — it sup­ports mul­ti-file drag&drop, so sim­ply
drop a glTF file on it to play it. If you don’t have any glTF file handy,
there’s the of­fi­cial Khronos glTF sam­ple mod­el re­pos­i­to­ry
on GitHub. Sketch­fab al­so has 1000s of mod­els
down­load­able as glTF.

Af­ter the hard work of re­mov­ing manda­to­ry OpenGL de­pen­den­cy was done in
2018.04, Mag­num is slow­ly gain­ing bits and pieces need­ed for Vulkan sup­port. In
June I took over a main­tain­er­ship of flextGL and added
Vulkan sup­port to it. Short­ly af­ter, Mag­num gained a Vk li­brary that
pro­vides plat­form-in­de­pen­dent func­tion point­er load­ing. It gives you a choice
whether you want glob­al func­tion point­ers (like with OpenGL) or man­age them
lo­cal­ly. See the orig­i­nal post about flextGL
for de­tails.

The Vk li­brary al­so pro­vides con­ver­sion of gener­ic Pix­elFor­mat,
Sam­pler­Fil­ter, Mesh­Prim­i­tive, … enums to Vulkan-spe­cif­ic
Vk­For­mat, Vk­Fil­ter, VkPrim­i­tive­Topol­o­gy, … val­ues.
That al­lows you to use Mag­num as­set man­age­ment APIs to load im­age and scene
da­ta and use them di­rect­ly with­out time-con­sum­ing man­u­al for­mat con­ver­sion.
There is al­so a new ex­am­ple fo­cused on ren­der­ing a sim­ple tri­an­gle to an
off­screen buf­fer us­ing a hand­craft­ed SPIR-V shad­er and then sav­ing it as a PNG
us­ing the Mag­num PngIm­age­Con­vert­er plug­in.

Vulkan API map­ping
Like with OpenGL, Mag­num doc­u­men­ta­tion pro­vides a help­ful map­ping
of Vulkan sym­bols to equiv­a­lent Mag­num APIs. Just search for them.

Vulkan Tri­an­gle
Di­rect­ly us­es Vulkan with hand-writ­ten SPIR-V to pro­duce a tri­an­gle
off­screen, with sRGB-cor­rect blend­ing. That all in just 500 lines.

There will be more

Fur­ther ad­di­tions like shad­er/SPIR-V tools, de­vice/in­stance ab­strac­tions
and ini­tial pieces of the Vulkan back­end are sched­uled for next re­leas­es.
Sub­scribe to mosra/mag­num#234 for up­dates.

Long gone are the days of a stan­dard 1024×768 res­o­lu­tion and fixed 96 DPI
— dense screens are now a com­mon fea­ture for high­er-end lap­tops and desk­tops.
In the 2018.10 re­lease, Mag­num is DPI-aware on mac­OS, iOS, Lin­ux and
Em­scripten. The us­abil­i­ty goal is that re­quest­ing an 800×600 win­dow will
make it the same phys­i­cal size as an 800×600 win­dow would have on a 96
DPI screen — so ba­si­cal­ly with no ex­tra in­volve­ment from the us­er. For web
and mo­bile, Mag­num sim­ply en­sures that for giv­en can­vas / screen size you’ll
get all the pix­els that are there, with no scal­ing on top. If you have a HiD­PI
screen, check out the We­bGL demos on the Show­case
page — ev­ery­thing should be nice­ly crisp. This top­ic is way more com­plex than
it might seem, see DPI aware­ness for a de­tailed over­view
of DPI-aware­ness on all plat­forms and what that means for you as a de­vel­op­er.

Un­for­tu­nate­ly out-of-the-box Win­dows sup­port didn’t make it to the re­lease
(though you are able to force ar­bi­trary scal­ing with a --magnum-dpi-scaling
pa­ram­e­ter). Full An­droid sup­port and ad­vanced things like DPI change events
when drag­ging a win­dow across dif­fer­ent­ly dense mon­i­tors are al­so wait­ing to be
done, see mosra/mag­num#243help want­ed for de­tails.

In­tro­duc­tion of the An­i­ma­tion li­brary re­quired quite a few ad­di­tions to
the Math li­brary — there’s a new Math::Cu­bicH­er­mite class for
Cu­bic Her­mite splines. As a gener­ic base for TCB curves and Cat­mull-Rom splines
they are eas­i­ly con­vert­ible to and from Math::Bezi­er.

Many projects ei­ther use or in­ter­face with the GLM
li­brary and so it made sense to be in­ter­op­er­a­ble with it. Sim­ply in­clude one of
the head­ers in the GlmInte­gra­tion li­brary and you’ll get con­ver­sion of
all vec­tor, ma­trix and quater­nion types and al­so an abil­i­ty to print the GLM
types us­ing Util­i­ty::De­bug:

We’re still un­sure if the up­com­ing Vulkan back­end will be able to do
sim­i­lar amount of work in such a terse ex­pres­sion. That could be both
a bad and a good thing.

Yes, it’s now pos­si­ble to get a GL::Mesh di­rect­ly from
Trade::Mesh­Da­tawith a sin­gle click —
just use the brand new Mesh­Tools::com­pile() reim­ple­men­ta­tion and it’ll
drag all GL::Buf­fer in­stances along with it­self, with­out you need­ing to
man­age them. Of course there are flex­i­bil­i­ty trade­offs, so when us­ing the mesh
APIs di­rect­ly, you have the op­tion of GL::Mesh::ad­dVer­texBuffer() ei­ther
tak­ing a non-own­ing ref­er­ence to the buf­fer or ful­ly tak­ing over its own­er­ship.

There’s a new Con­tain­ers::Sco­pe­dEx­it class that sim­ply calls a passed
ex­it / close / de­stroy func­tion on giv­en val­ue at the end of scope. Very use­ful
when in­ter­act­ing with low-lev­el C APIs and much eas­i­er than wrestling with
std::unique_p­tr, try­ing to con­vince it to do the same.

intfd=open("file.dat",O_RDONLY);Containers::ScopedExite{fd,close};

If you ev­er need to it­er­ate on a ar­ray of in­ter­leaved val­ues and take al­ways
the third val­ue, there’s now Con­tain­ers::StridedAr­rayView that ab­stracts
it away. It’s used in­ter­nal­ly by the An­i­ma­tion::Track­View APIs to al­low
for both flex­i­ble and cache-ef­fi­cient lay­out of keyframe da­ta.

There’s a new Util­i­ty::for­mat() fam­i­ly of
func­tions for Python-style type-safe string for­mat­ting. The rea­son I’m adding
this is be­cause std::os­tream (and to some ex­tent printf())
is no­to­ri­ous­ly in­ef­fi­cient, neg­a­tive­ly af­fect­ing ex­e­cutable size es­pe­cial­ly on
asm.js / We­bAssem­bly tar­gets. How­ev­er the full im­ple­men­ta­tion didn’t make it
in­to the re­lease, on­ly the sur­face APIs, Mag­num is not port­ed away from streams
just yet — there will be a de­tailed post about all this lat­er 😉

More of an in­ter­nal thing, the De­bug­Tools::Com­pareIm­age util­i­ty got a
Com­pareIm­ageToFile coun­ter­part,
to­geth­er with oth­er com­bi­na­tions. In sub­se­quent up­dates, these will get used
for fuzzy shad­er out­put ver­i­fi­ca­tion — very im­por­tant for im­ple­ment­ing PBR
shaders that are lat­er on the roadmap.

Shown above is a new Prim­i­tives::gra­di­en­t2D() func­tion (to­geth­er with
its 3D coun­ter­part), use­ful for sim­ple back­drops. The Shaders::Phong
shad­er got a long-re­quest­ed sup­port for mul­ti­ple lights and there’s now al­pha
mask­ing sup­port in both Shaders::Phong and Shaders::Flat —
use­ful for quick’n’dirty pro­to­typ­ing when you don’t want to both­er your­self
with depth sort­ing or OIT.

Since the TinyGlt­fIm­porter plug­in ini­tial
re­lease in 2018.04, it’s re­ceiv­ing an end­less stream of up­dates. While the
big­gest new fea­ture is an­i­ma­tion im­port, it al­so re­ceived sup­port for
mul­ti-prim­i­tive mesh­es, name map­ping for all da­ta, cam­era as­pect ra­tio im­port
and var­i­ous con­for­mance fix­es and per­for­mance im­prove­ments. It’s now eas­i­er to
ac­cess its in­ter­nal state, in case you
want to parse cus­tom glTF prop­er­ties or ac­cess da­ta that the im­porter does not
sup­port yet.

To sup­port load­ing da­ta from mem­o­ry, from AAssetManager on An­droid or
for ex­am­ple voa drag&drop on Em­scripten, all scene and im­age im­porters now
sup­port file load­ing call­backs.
For you it means you can con­tin­ue load­ing as­sets as usu­al — us­ing their
file­names — and on­ly set up a dif­fer­ent file call­back for each plat­form. The
im­ple­men­ta­tion was done in a way that makes all ex­ist­ing (and fu­ture) plug­ins
im­plic­it­ly work with file call­backs, more­over the
TinyGlt­fIm­porter,
As­simpIm­porter and
OpenGex­Im­porter al­so use pro­vid­ed file
call­backs for ex­ter­nal da­ta ref­er­enced from scene files (such as im­ages or da­ta
buf­fers).

There’s fi­nal­ly a JpegIm­age­Con­vert­er plug­in
for com­press­ing JPEG files, us­ing a lib­JPEG im­ple­men­ta­tion of your choice —
be it the vanil­la im­ple­men­ta­tion, lib­jpeg-tur­bo
or, for ex­am­ple, MozJPEG. Sim­i­lar­ly, the
stb_im­age-based StbIm­age­Con­vert­er
got up­dat­ed to sup­port JPEG out­put as well — and you can load ei­ther of them
us­ing the JpegImageConverter alias. Both plug­ins sup­port spec­i­fy­ing the
out­put qual­i­ty via a run­time set­ting; more en­cod­ing op­tions may be added in the
fu­ture.

Among oth­er things, the Stb­True­Type­Font was
up­dat­ed to a new ver­sion of stb_truetype, gain­ing OTF sup­port, and you can
now load it (along with the oth­er Harf­Buz­z­Font and
FreeType­Font im­ple­men­ta­tions) via the gener­ic
OpenTypeFont alias.

Mag­num is now over eight years old and it be­came ap­par­ent that some ear­ly
func­tion­al­i­ty didn’t stand the test of time — ei­ther be­cause it de­pend­ed on
a now-out­dat­ed tool­kit, be­cause the re­quired time in­vest­ment for con­tin­ued
main­te­nance was not worth it or sim­ply be­cause it was a de­sign ex­per­i­ment that
failed. The fol­low­ing li­braries are now marked as dep­re­cat­ed, are not built by
de­fault (in case they ev­er were) and will be com­plete­ly re­moved in about six
months time.

The Trade::Col­ladaIm­porterdep­re­cat­ed plug­in,
be­cause it’s based on an out­dat­ed Qt4 tool­kit. More­over, due to the sheer
com­plex­i­ty of the COL­LA­DA for­mat and poor con­for­mance of var­i­ous ex­porters
it’s not fea­si­ble to main­tain a builtin im­porter any­more. Con­sid­er ei­ther
us­ing As­simpIm­porter for COL­LA­DA im­port or
switch­ing to bet­ter-de­signed and bet­ter-sup­port­ed for­mats such as glTF or
OpenGEX us­ing TinyGlt­fIm­porter or
OpenGex­Im­porter. There’s al­so the of­fi­cial
COL­LADA2GLTF con­vert­er.

Visual Studio 2017

With a heavy heart I have to say that re­cent up­dates of MSVC 2017 were
re­gress­ing in­stead of im­prov­ing with their C++11 con­for­mance, crash­ing with
In­ter­nal Com­pil­er Er­ror on code in­volv­ing constexpr. While we
man­aged to re­pro­duce and work around all re­port­ed is­sues so far, it may
hap­pen that your code trig­gers some new cor­ner case. Try to up­date to the
lat­est ver­sion first and if the prob­lem per­sists,
let us know. Thank you and sor­ry for the bumps.

Two new ex­am­ples were con­trib­uted by our great com­mu­ni­ty, name­ly an in­te­gra­tion
of the Box2D physics en­gine and an ad­vanced depth-aware mouse in­ter­ac­tion
ex­am­ple. Both are port­ed to We­bGL and you can play with them right now:

Box2D Ex­am­ple wasmwe­bgl1physics
Builds a pyra­mid out of cubes and al­lows you to de­stroy it af­ter.

The Mag­num web­site is nev­er stor­ing any cook­ies or do­ing us­er track­ing (and
doesn’t plan to be do­ing that), so there’s no need to be wor­ried about your
da­ta be­ing com­pro­mised. Nev­er­the­less, it’s now served over HTTPS, with a
cer­tifi­cate from Let’s En­crypt. Some trade­offs
were made as it’s ei­ther full se­cu­ri­ty or sup­port­ing the not-most-re­cent
browsers (but not both), so if you ex­pe­ri­ence any is­sues, please let us know.

Mag­num is now part­ner­ing with a few uni­ver­si­ties with a goal of im­prov­ing
com­put­er graph­ics cour­ses by of­fer­ing stu­dents things that are fun to play
with. You’re in­vit­ed to the par­ty as well — each GitHub re­pos­i­to­ry
now has is­sues marked with a help want­ed la­bel and these
is­sues are specif­i­cal­ly picked to be self-con­tained, ex­cer­cise a well-de­fined
area of knowl­edge and to not re­quire deep un­der­stand­ing of Mag­num in­ter­nals.
The most re­ward­ing among these are var­i­ous ex­am­ples, you can al­so im­ple­ment a
fan­cy al­go­rithm, in­te­grate sup­port for a new file for­mat or share your
ex­per­tise in an area you know the best. If you pick some­thing, let us know
and we’ll help you get on the right path.

There’s al­so a pos­si­bil­i­ty to write a guest post
for this very blog and share in­ter­est­ing de­tails about a Mag­num-re­lat­ed thing
you’re work­ing on.

In con­trast to 2018.04, this re­lease is more of an evo­lu­tion­al one.
Nev­er­the­less, even though we’re al­ways go­ing to ex­treme lengths to pre­serve
back­wards com­pat­i­bil­i­ty, it may hap­pen that some changes will have neg­a­tive
af­fect on your code. Please check the Dep­re­cat­ed APIs and Po­ten­tial
com­pat­i­bil­i­ty is­sues sec­tions in the com­plete changel­og be­low for more
in­for­ma­tion.

Thanks to @mat­jam there’s now a
PPA re­pos­i­to­ry
con­tain­ing pre­built pack­ages for Ubun­tu 14.04, 16.04 and 18.04. If you fol­low
the #mov­ing­tog­it­lab move­ment,
Mag­num now has a mir­ror on Git­Lab, but
note that pri­ma­ry de­vel­op­ment, roadmap and mile­stone plan­ning is still
hap­pen­ing on GitHub and will stay there for the fore­see­able fu­ture.

The 2018.10 re­lease is al­ready avail­able in Home­brew
and Arch­Lin­ux AUR. At the
time of writ­ing, the PPA repos­i­to­ry, Vcp­kg and
Arch­Lin­ux re­pos are not up­dat­ed yet, we’re
work­ing on get­ting the lat­est ver­sion there as well.

Com­ing to an es­tab­lished work­flow for the first time is al­ways an
in­ter­est­ing ex­pe­ri­ence be­cause I don’t have any “it’s been like this since
for­ev­er” in­sights form­ing my opin­ion yet. This time it’s about quater­nion
in­ter­po­la­tion and a sud­den op­ti­miza­tion op­por­tu­ni­ty.

Play­ing with Vulkan but don’t want to in­clude thou­sands lines of
var­i­ous head­ers just to call a few func­tions? FlextGL just learned Vulkan
sup­port and it’s here to speed up your turn­around times.

One of the goals while build­ing the new Mag­num web­site was to low­er
the bar­ri­er for con­tribut­ing con­tent. With Git and GitHub it’s al­ready very
easy to con­trib­ute code to the project it­self, so why not ex­tend that to
the web­site as well?

A new Mag­num ex­am­ple im­ple­ments an an­a­lyt­ic method for area light
shad­ing pre­sent­ed in the pa­per “Re­al-Time Polyg­o­nal-Light Shad­ing with
Lin­ear­ly Trans­formed Cosines”, by Er­ic Heitz, Jonathan Dupuy, Stephen Hill
and David Neubelt.