I ask myself what's the best way to store the transformations in a model class. What I came up with is to store the translation and scaling in a Vector3 and the rotation in a Matrix4.

On each update (frame) I multiply the 3 matrices (first build a Translation and Scaling Matrix) to get the world matrix. In this way I have no accumulated error.

world = translation * scaling * rotation 

Another way would be to store the rotation in a quaternion but then I would have a high cost to convert to a matrix every time step. If I lerp the model I convert the rotation matrix to quaternion and then back to matrix.

For speed optimization I have a global dirty flag and one for each transformation so that I only do a matrix multiplication if necessary.

if (isDirty) {
    world = translation
    if (isScaled) {
        world *= scaling
    if (isRotated) {
        world *= rotation

Is this a common way or is it more common to have only one Matrix4 for all transformations? And is it better to store the rotation only as quaternion? For info: Currently I'm building a CSS3D engine in Javascript but these questions are relevant for every 3D engine.

  • \$\begingroup\$ I usually do the same thing, although I also have to store those 3 values for each bone (although I can usually get away with not storing scale if I don't plan on changing that ever.) \$\endgroup\$ Commented Jun 25, 2013 at 23:07
  • \$\begingroup\$ @BenjaminDangerJohnson yeah this is crazy. but thanks, then I know that I'm on the right track. \$\endgroup\$
    – redreggae
    Commented Jun 27, 2013 at 11:54

1 Answer 1


I would prefer

world = translation * scaling * rotation

you save the translation and scaling and rotation matrix in each object and recalculate the matrices only if the transation/scaling/rotation changed.

In the rendering loop you transform the object after the world matrix.

The reason for this against the cached version is simple, it doesn't branch (except in the multiplication operation, but the compiler or you can inline/optimize it so it works without branches) and its more simple.

About the Quaternions: You use Quaternions only if the rotate operations are used very frequently (Forward kinematic, IK) because of the Quaternion<->Matrix conversation overhead.

  • \$\begingroup\$ I don't understand what you mean with "it doesn't branch". Remember, the engine is written in Javascript, so it's not compiled and every optimization really matters. \$\endgroup\$
    – redreggae
    Commented Jun 25, 2013 at 18:55
  • \$\begingroup\$ ow ic, my fault, i overlooked that part. I dunno if it would make a difference in the performance. Over everything else i think about such things after the kiss principle (the if's make the code more complicated for no reason). \$\endgroup\$
    – Quonux
    Commented Jun 25, 2013 at 19:40
  • \$\begingroup\$ ok thanks, but the main approach of storing translation, scaling and rotation in seperate data structures is common? \$\endgroup\$
    – redreggae
    Commented Jun 25, 2013 at 21:16
  • \$\begingroup\$ yes, this is how I do it. I have another dirty flag and only recalculate the world matrix if one of the three transformations change. thanks for your time..I will accept your answer tomorrow. I'll try to get another answer first. \$\endgroup\$
    – redreggae
    Commented Jun 25, 2013 at 21:42
  • 2
    \$\begingroup\$ @redreggae: "it's not compiled and every optimization really matters" - modern JavaScript runtimes are ridiculously fast, faster than C in some narrow circumstances. Optimizations matter, but probably not the same ones you think. With JS, your big thing is going to be avoiding GC pressure and trying to work around all the JS features and missing features that make it really hard to avoid GC pressure (no anonymous structs for named-parameter passing, no closures, pre-allocate temporaries for all your vector/matrix math, etc.). Don't guess what optimizations you need; profile and find out. \$\endgroup\$ Commented Jun 25, 2013 at 23:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .