• Advertisement
Sign in to follow this  

Design: Matrix or Scale,Rotate,Translate

This topic is 2343 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

in order to position and orientate the objects in my scene my scene objects currently have a scale, rotate and translate Vector3. From these vectors I build a matrix M that performs a Scale, XYZ rotation and translate: M = Scale * XYZRotate * Translate.

While this approach is very easy to use (for example I can just rotate an object around the y axis by: object->setRotation( Vec3(0, 45, 0)) it also not very flexible, since I have a fixed order (always scale, then rotate, then translate) AND I have a fixed rotation order (always X rotation, then Y, then Z).

Do you think this is a good design or should I change it? Should I just use a general Matrix so the user could apply any matrix? Or should I just make the rotation order variable? Or...?

Thanks for any ideas!

Share this post


Link to post
Share on other sites
Advertisement
The approach i use (wich i think is good but im not an expert) is to store those 3 things seperately for each entity but to also have a matrix that gets build up from those 3 componants each time one of them changes. So the 3 componants are for "internal" use only. When im rendering/doing other stuff i always use the matrix. The entity just needs to be sure to rebuild te matrix when changes occur.

I take it a step futher and i use a clean/dirty boolean flag for this matrix meaing that whenever this matrix is required it checks the flag to see if its up to date and if its not rebuild it using the 3 base componants.

I take this another step futher and i also store the "absolute matrix" in each entity. wich represents te entity's transformation from the origin. I also use a clean/dirty boolean flag for this. So the "absolute matrix" only gets updated when its needed. Having the absolute matrix of the entity in the entity is usefull if not neccesary for game logic and rendering. The absolute matrix is easily calculated by multiplying the entities parents absolute matrix with the entities relative matrix.

Another thing. when you build up your matrix from the base componants you should probely convert the rotation into 3 separate rotations (1 for x, 1 for y and 1 for z) and convert each of them into quaternions and then multiply the 3 resulting queternions together to get 1 rotation again that does all 3 rotations in one instead of first x then y then z. This should prevent the anoying gimbal lock effect.

Hope this helps.

Share this post


Link to post
Share on other sites
It really depends on what you are doing.

If you are creating generic 3D editor, your approach may be the best.

If you are doing level or scene editor, I'd go with matrices. You are probably not interested in the actual values of transformation components anyways. Also notice, that (relative) rotation can still be as easy as: M' = M * Matrix::rotation(Vector::Y, 45)

If writing actual game, I would go with constrained matrices - i.e. always strictly orthogonal and without scaling. Then the expensive matrix inversion would simply become transposition + plus translation adjustment. Also you can transform normals (planes) with the same matrix as positions.

But this is only about the physical/rendering part of your code. For game logic you should save whatever transform components, that make sense - for example pitch, yaw, roll for flight simulator, movement direction for biped character and so on.




Share this post


Link to post
Share on other sites

Another thing. when you build up your matrix from the base componants you should probely convert the rotation into 3 separate rotations (1 for x, 1 for y and 1 for z) and convert each of them into quaternions and then multiply the 3 resulting queternions together to get 1 rotation again that does all 3 rotations in one instead of first x then y then z. This should prevent the anoying gimbal lock effect.

But it doesn't: Gimbal lock is an issue of concatenating rotations so that a rotation axis gets coincident with an already used rotation axis. It is not an issue of whether one uses matrices or quaternions for rotation representation. Hence the above suggestion doesn't help against gimbal lock but makes things needlessly more complex.

Furthermore, there is no difference (besides perhaps efficiency and rounding errors) whether one applies particular rotations one by one or else computes the composition matrix first and applies that:
( R[sub]1[/sub] * R[sub]2[/sub] ) * v == R[sub]1[/sub] * ( R[sub]2[/sub] * v )
a.k.a. associativity

Share this post


Link to post
Share on other sites
The method I use, which is common in the industry, is to store a forward, up, and right vector, along with scale and position vectors.
Although it is a bit more complicated to maintain, it is generally only conceptually more difficult, not computationally more difficult.
When rotating, you have to keep your vectors orthogonal. While this may sound like more work, this is only a few cross-products, and is much less expensive than building rotational matrices around individual axes. Plus they can be converted directly to a matrix without performing any matrix math. For example, you do not need to build a rotation, scaling, and translation matrix and then combine them. Just write directly to the components of the matrix the values in your rotational vectors (multiplied by scale of course).


The matrix only needs to be built once per frame, usually just for render, but a simply dirty flag can be used to cause any-time updating whenever it is needed.


L. Spiro

Share this post


Link to post
Share on other sites

in order to position and orientate the objects in my scene my scene objects currently have a scale, rotate and translate Vector3. From these vectors I build a matrix M that performs a Scale, XYZ rotation and translate: M = Scale * XYZRotate * Translate.[/quote]
Replacing the XYZRotate with QuatRotate would make the system perfect. It doesn't matter how you try to work them, using Euler triplets will always feel wrong....
The matrices only need to be computed at the point of rendering.


While this approach is very easy to use (for example I can just rotate an object around the y axis by: object->setRotation( Vec3(0, 45, 0))[/quote]

And with quats you can do the same thing.....

object->setRotation( Quat(0, sin(45.0f/2), 0, cos(45.0f/2.0f)) );


it also not very flexible, since I have a fixed order (always scale, then rotate, then translate) AND I have a fixed rotation order (always X rotation, then Y, then Z).[/quote]
The scale->rotate->translate ordering is perfectly fine. What is NOT fine is using euler angle triplets (if you *really* must use them, change the ordering so that the axis the is rotated around least is the middle one. i.e. If a rotation around Y is rare, then you should use XYZ or ZYX ordering. If a rotation around Y occurs all the time, then use YXZ, XZY, YZX or ZXY).

Do you think this is a good design or should I change it? Should I just use a general Matrix so the user could apply any matrix? Or should I just make the rotation order variable? Or...?[/quote]


This is why you should use a Quat instead of the euler triplets. Converting from Matrix to a Quat is generally much more reliable than Matrix->euler XYZ. The upshot is that you can provide a simple method to decompose a user specified matrix into scale translate and rotation (as a quat) components.

Share this post


Link to post
Share on other sites

The method I use, which is common in the industry, is to store a forward, up, and right vector, along with scale and position vectors.



Citation needed!

You can everything you need to do with nothing more complex than a single pos quat. Very few people use anything more complex than that because it keeps all of the maths simple, and therefore efficient. No one uses scale (unless they absolutely have too). It causes so many annoying problems that it's usually just ignored...

Share this post


Link to post
Share on other sites
If the design is not suitable for your intended use cases then definitely change it; design should always follow the requirements of usage, not the other way around.

You've already identified some areas where you're lacking flexibility so tackle them first. Have a look at some existing matrix libraries, see how they work, and get inspiration from them. Who knows, you may even find one that does the job you want the way you want it and end up not needing to build your own.

Share this post


Link to post
Share on other sites

[quote name='YogurtEmperor' timestamp='1316172888' post='4862406']
The method I use, which is common in the industry, is to store a forward, up, and right vector, along with scale and position vectors.



Citation needed!

You can everything you need to do with nothing more complex than a single pos quat. Very few people use anything more complex than that because it keeps all of the maths simple, and therefore efficient. No one uses scale (unless they absolutely have too). It causes so many annoying problems that it's usually just ignored...
[/quote]
It was used in Halo 1 and Halo 2, and in at least one commercial game engine. It is also used in at least one game programming book.
If your only goal is to make an orientation, your suggestion is fine.
But if the orientation has any meaning outside of rendering, you will need something more.
CryTech interviews sometimes ask how to detect if an object is to the left or right of a player. A right vector sure makes this trivial.

The poster should decide based of what he or she plans to do in his or her project.


Also, I disagree about ignoring scaling. I know of no game engines that ignore scaling. The original poster is free to ignore them if he or she does not need them, but with certainty I can say that it is not usually ignored.


L. Spiro

Share this post


Link to post
Share on other sites
Personally I just don't see much point in separately storing right, up, forward, position vectors. They are exactly the four columns of the objects transformation matrix you're going to build every frame anyway. Keeping them together as a unit (ie. matrix) seems a lot more convenient than rotating each vector separately (even of mathematically it's the same of course). If anything it will save you a few operations that would have likely be done in parallel anyway.

In terms of memory you just save yourself 4 floats by dropping w (but if that is your concern, you can just store the orientation as a "compressed" quaternion reducing it to 3 floats instead of 9 or 12 floats for a matrix).

Factoring out scaling is a different issue, because it muddles the neatness of the matrix and makes the three axes "useless" for many applications.

Point is: what is your application? Do you expect to concatenate a lot of rotations each frame (skeletal animations)? Quaternions might be worth a look then. Do you want to minimize memory usage? Only calculate "right" when you need it or use a quat. Do you want it to be simple, robust and easy to use? Stick with a 4x4 matrix and only store scaling separately.

But storing the three axes separately without good reason when even the memory layout in a matrix would be exactly the same and you can still always access them separately anyway seems to just make it more troublesome to directly apply transformations.You can still transform each vector separately and ignore w.

Share this post


Link to post
Share on other sites

[color="#1C2837"]It was used in Halo 1 and Halo 2, and in at least one commercial game engine. It is also used in at least one game programming book.


So you've found one engine that uses scaling, and have found a book detailing the same system that uses scaling, and then use that to assert that there are no commercial games that ignore scaling?

Also, I disagree about ignoring scaling. I know of no game engines that ignore scaling.


GTA4. Red dead redemption. Star wars force unleashed. Backbreaker. None of those games use scaling in their engines. I know of at least another 20 to 30 games in development at the moment that also don't use scaling in their engines. I know this, because I worked on their animation system ;)


I've added scale into exactly one animation system (for sudeki ~2002), however it was scaling in a very limited form to keep computation time down to a minimum. (i.e. no scale pivots, no segment scale compensation). So you could use the system to scale an entire character, or use scale at the end chains for roll bones, and other skin fixes. But it was no where near robust enough to handle animated scaling in the same way you'd be able to handle it in say Maya/Max etc.

[color="#1C2837"]
[/quote]

[color="#1c2837"]It doesn't make them useless at all. It just makes it much much harder to make use of them - i.e. you will find yourself dividing through by the dot product of the axis, with itself, whenever you need the direction vectors. Whilst the computation isn't terribly slow in a global sense, the use of dot products (not so great with SIMD) and divisions everywhere makes the whole system many orders of magnitude slower than a simple pos quat system.

[color="#1C2837"]In terms of memory you just save yourself 4 floats by dropping w (but if that is your concern, you can just store the orientation as a "compressed" quaternion reducing it to 3 floats instead of 9 or 12 floats for a matrix).


[color="#1c2837"]In terms of memory, you can't beat 4 floats for a quat, 3 for a position. You don't need the direction vectors at all, since you can do

[color="#1c2837"]
Vector3 forward = rotation.rotateVector( Vector3::kOneX );
Vector3 up = rotation.rotateVector( Vector3::kOneY );
Vector3 side = rotation.rotateVector( Vector3::kOneZ );

[color="#1c2837"]
[color="#1C2837"]It should be fairly obvious that there are a lot of 0's and 1's within that computation, which largely cancel each other out (i.e. expand the code out, and you will notice it's not very slow!). Personally speaking, the idea of storing a matrix at any point with in an animation pipeline seems a little daft to me (i.e. convert to matrices if needed at the point of rendering, but not before).

Share this post


Link to post
Share on other sites

[quote name='YogurtEmperor' timestamp='1316229349' post='4862678']
[color="#1C2837"]It was used in Halo 1 and Halo 2, and in at least one commercial game engine. It is also used in at least one game programming book.


So you've found one engine that uses scaling, and have found a book detailing the same system that uses scaling, and then use that to assert that there are no commercial games that ignore scaling?

Also, I disagree about ignoring scaling. I know of no game engines that ignore scaling.


GTA4. Red dead redemption. Star wars force unleashed. Backbreaker. None of those games use scaling in their engines. I know of at least another 20 to 30 games in development at the moment that also don't use scaling in their engines. I know this, because I worked on their animation system ;)


I've added scale into exactly one animation system (for sudeki ~2002), however it was scaling in a very limited form to keep computation time down to a minimum. (i.e. no scale pivots, no segment scale compensation). So you could use the system to scale an entire character, or use scale at the end chains for roll bones, and other skin fixes. But it was no where near robust enough to handle animated scaling in the same way you'd be able to handle it in say Maya/Max etc.[color="#1C2837"][/quote]

[color="#1C2837"]You should not pursue this, as there is no way to prove an erroneous claim.
[color="#1c2837"]Joint systems and skeleton hierarchies sometimes ignore scale (they can cause problems when mixed with model scales sometimes, or leave body parts disconnected), but at most this is only sometimes, and specific to one part of game engines.
[color="#1c2837"]I’ve not just found one engine and one book that use scaling.
[color="#1c2837"]Every non-specialized engine supports scaling. Unity 3D, CryEngine, CryEngine 2, CryEngine 3, Leadwerks Engine, Claustrophobia Engine, Frostbite, Frostbite 2, Crystal Tools, RenderWare, Gamebryo, Unreal Engine 3, id Tech 4, and on and on.
[color="#1c2837"]I make game engines for a living, and I never worked on or seen an engine that ignored scaling.
[color="#1c2837"]

[color="#1c2837"]Grand Theft Auto 3’s engine (RenderWare) is capable of scaling. The animated objects ignore scaling. I have even done such a thing in a recent tech demo.
[color="#1c2837"]

[color="#1c2837"]

[color="#1c2837"]I am aware of your background. This person is not asking just about animations and joint hierarchies. He or she is asking how to orient objects in his or her scene, and there are no game engines that would force you to make a new tree model just because you want a tree to be a little smaller than the others.
[color="#1c2837"]

[color="#1c2837"]

[color="#1c2837"]L. Spiro

Share this post


Link to post
Share on other sites

[color="#1c2837"]In terms of memory, you can't beat 4 floats for a quat, 3 for a position.


Correct me if I got it wrong, but we only deal with unit quaternions. Knowing x,y and w means you can calculate z. The only issue of z being negative is solved by simply inverting the axis and angle of the rotation to make sure z is always positive. The tradeoff in calculations to save 4 bytes is another issue, but since I was purely speaking about being desperate to save memory...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement