Adding or Concatenating Transforms (Scale, Rotation, Translation)

Started by
21 comments, last by Kwizatz 11 years, 2 months ago

You're right, and I agree, my matrix code works, but to give some more context to this, I'll explain how this idea came to be.

My skeleton file format stores transforms as SRT, as I explained, my animation file format stores a "channel" per vector element, so animations are applied to the SRT vectors as well, this works great, BUT at runtime I need to generate a temp array of matrices (that is, an array of arrays) for the bind pose skeleton pose, a temp array of matrices for the animated joints which gets multiplied by the bind pose array and a final array for the result of the previous multiplication.

I cache the bind pose array since it never changes, but keeping duplicate data on memory kind of bothers me, and having a temp array with the SRT's converted to matrices provokes the same nagging annoyance in me.

So I though that if I could do the operations with the SRT's directly I could do without the auxiliary arrays, so no duplication of data in memory, and at the time avoid a runtime pre-computation (I am trying to do all preprocessing offline so my file formats are ready to use as soon as they're loaded into memory and some pointers are set), and some matrix multiplications here and there.

To me, it is an interesting topic, I have not dumped my matrix code yet, and I won't, but I'd like to know what could I get away with.

Advertisement

You can do everything with SRT (and upload them to the GPU and process the verts with them directly if you wish). Doing so has a number of problems. Firstly, SRT * Vertex is an exceptionally slow operation (well, it's not that bad, but it is much slower than matrix * Vertex). Secondly, SRT * SRT is also fairly slow when compared to matrix * matrix. Really the only time SRT makes any practical sense, is when you are performing lots of interpolations (which is quicker with SRT than with matrices). Most people store the bind pose as matrices because, well, it's efficient as is possible (assuming you have SIMD optimised your matrix operations. If you haven't, then you *may* be able to squeeze a tiny advantage with SRT).

In the end I did manage to get it working, I am doing this for animation interpolation, so it does seem justified. I convert to matrix before feeding the transforms to the gpu.
I do think this way is more efficient at least as long as it stays on the CPU, many multiplications can be avoided for example because one of the multiplicands being zero for the translation part and the scale part (what I did was convert the vectors to matrices and assume constants for the non variable elements in the matrix, then simplify the matrix multiplications),
the most expensive operation then becomes rotating the translation vector using the quaternion, since it implies a quaternion to 3x3 matrix conversion and a matrix vector multiplication but still not as many operations as the regular matrix multiplication.
You only need to apply rotation and scale to the translation, I think, because of the nature of translation, a skew in 4D, rather than being a linear transform in 3D, and in any case it makes sense when you think of the translation vector as being in the space of the rotated and scaled axes.

I am leaving SIMD viability as an exercise for later.

You could have a transformation that rotates by 45 degrees, then scales the x axis by a half, then rotates back. This transformation can not be represented with scaling vector, it happens along an axis that is at 45 degrees.

For the rotation and translation, your transform is like

V'=rotation*V+translation

and for two transforms, it is

V'=rotation2*(rotation1*V+translation1)+translation2

or

V'=rotation2*rotation1*V + rotation2 * translation1 + translation2

so you multiply your rotations and you add translations after multiplying the earlier translation by the later rotation.

The multiplication by rotation here means rotating by a quaternion, i.e. represents Q*a*~Q where ~ is inverse.

Hi Dmytry,

I am not sure I follow, what do you mean? in the end what my SRT operations do is a simplified matrix multiplication, so if you take S,R,and T as matrices with scale, rotation and translation respectively, and I as identity the operation you describe would be something along these lines:

( I * R * I ) * (S * I * I) * ( I * *R * I ),

which is the same as RSR, wouldn't the scale vector (diagonal) on the second matrix be doing the scale on world axes rather than object axes as well?

I think I see where you're going, but I haven't had time to think more about it.

The second part of your post, I am not sure if you're pointing out a (another?) problem or providing me with an optimization smile.png

Thank you for your comments!

He seems to be saying that you should always use matrices because RSR cannot be represented by SRT, which is simply not true. SRT * SRT * SRT can represent RSR just fine, not to mention the fact that your DCC package is going to be authoring data in SRT anyway, so why bother worrying about an edge case that will never happen?

I see, that's what I though, I am still in need of some time to reassess non uniform scaling, but with uniform scaling it seems fine to just multiply the scaling factors, since scale would be the same in all directions.

And yes, this is going to handle mostly DCC'ed meshes and animations, the 'optimization' in fact came about because of how I was doing animation interpolation.

Thanks again!

Just drop non-uniform scaling: The notion of what constitutes a non-uniform scaling is not an intrinsic feature of the transform (in other words, it depends on the coordinate system used), which is the root of a lot of problems. I don't know what people use non-uniform scalings for anyway.
If you want to take account of non-uniform scaling, you can simply do the following:

transform = [S] * [R] * [IS] * [T]

Where IS is the inverse parent scale, which is pretty much all that most dcc packages do....

Certainly maya applies that transformation for all joint nodes, but geometry leaf transforms usually just use a plain SRT.

I don't know what people use non-uniform scalings for anyway.

Speak to an animator, and they usually find a million reasons to support it. A common trick is to apply non-uniform scale on leaf transforms within a skinned mesh to prevent collapsing elbows, or to simulate the effect of muscles bulging. I've even seen rigs that have made use of excessive amounts of animated scaling for classic-cartoon-like squash and stretch. It does have its uses, which is why animators make so much use of it in maya et-al. A seasoned animator in the games industry may not use it at all, but that's usually due to them having been pre-conditioned to not use scaling on pain of death, not because it has no use.
I bet animators could also make use of shearing transformations, which just means that they should be given access to general affine transformations, not just movements (rotation + translation) or a combination of movements and uniform scalings. The only problem with that is what to do about interpolations.

This topic is closed to new replies.

Advertisement