Advertisement

Mesh matrix transformation question

Started by February 17, 2015 01:36 PM
7 comments, last by Rannion 9 years, 10 months ago

Hi,

I have a mesh which is quika like a cylinder.

When I render it without its local transform, just with an identity matrix, its base is not in 0.0 but in 0.4 and it points toward the -Z.

Then, when I render it with its local transform, it points toward +y and its base is still at 0.4 (just above the origin).

Now, what I need to do is to stretch it in length but without touching those 0.4 from the origin.

I tried so many combinaison now I don't even know if it's possible.

I tried to use its inverse local matrix then scale it then multiply it by its local matrix to put it back etc...

But whatever I'm doing, it's also stretching those 0.4 from the origin so if I scale it 2 times, it puts it at 0.8 from the origin.

I understand I need to cast it in some space where its base would be at the origin, then do the scaling and put it back to where it should be but I can't figure out how to do it with the matrices.

Any help, idea would be much appreciated.

The order of the manipulations depends on the math library and coordinate system you're using - there are "right-hand" and "left-hand" system, normally using "right-to-left" and "left-to-right" multiplication ordered methods, often corresponding to right-hand vs. left-hand rotations.

In words, the sequence you describe is:

1. translate the object to the origin.

2. scale the object along the appropriate axis in it's current orientation.

3. rotate the object to it's desired orientation.

4. translate the object to it's desired location.

N.B., steps 2 and 3 can be reversed BUT the axes for scaling must be as they are in the newly rotated orientation.

In a "left-hand" system, with "left-to-right" ordered multiplication, with "left-hand" rotations:

1. create a translation matrix for ( 0, 0, -0.4 ) or ( 0, -0,4, 0 ) to move the cylinder to the origin = Mt_1 <-- it's not clear from your description whether "in 0.4" means Y or Z

2. create a scaling matrix to stretch the cylinder along the -z axis based on scaling values ( 0, 0, -scaleZ ) = Ms

3. creating a rotation matrix to rotate the cylinder about the X axis by +PI/4 - MatrixFromAxisAngle( ( 1, 0, 0 ), PI/4 ) = Mr

4. Create a matrix to translate it whereever you want ( 0, +0.4, 0 ) ?? = Mt_2

5. create a matrix to be applied to the cylinder M = Mt_1 * Ms * Mr * Mt_2

EDIT: In general, remember the acronym SRT (scale-rotate-translate) for left-hand systems, or TRS for right-hand systems. That order is with the object already at the desired origin.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Advertisement

Yes, that is what I need to do it seems.

What I'm missing then I think is the first step, I was expecting the inverse local matrix to do that for me.

So I need to grab the translation from the local matrix and create a translation matrix Mt to the origin.

I'm going to try that and let you know.

Many thanks anyway.


its local transform, just with an identity matrix,

The inverse of an identity matrix is an identity matrix. So applying the inverse local matrix does nothing.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Yeah I know that but I do have a local matrix from the fbx export. And in that local matrix I have the rotation and that 0.4 translation as well.

In your edit, at point 5, Mt_1 wouldn't be the inverse of Mt_2 ?

Advertisement


In your edit, at point 5, Mt_1 wouldn't be the inverse of Mt_2 ?

Mt_1 is the inverse of Mt_2.

In general, if you think of the structure of a scaling matrix, there is only 1 point that is not affected regardless of the values of the scaling matrix, and that is the point (0,0,0,1):

(0,0,0,1) * Ms = (0,0,0,1) for each scaling matrix Ms

In other words, that is the only point guaranteed to be mapped onto itself.

So if you want an arbitrary point p to be the center of scaling instead, you have to perform the scaling in a space where p is at (0,0,0,1). This is done by a temporary translation like so:

Mt(-p) * Ms * Mt(+p)

With Mt(p) being a translation matrix representing a translation by the vector p-0, the relation

Mt(-p) == Mt(+p)-1

holds.

You can apply the above method to other transformational aspects as well. E.g. any point on the axis (x,0,0,1) will be scaled onto the point (sx*x,0,0,1) of the same axis regardless of the scaling factors sy and sz. If you want an arbitrary axis, you have to perform a temporary rotation.

Considering this principle (and perhaps some simplifications in the end) you'll get the rght solution.

In your edit, at point 5, Mt_1 wouldn't be the inverse of Mt_2 ?

As haegarr mentions, Mt_1 and Mt_2, for the particular case defined, are inverses of one another.

As my post states:


Create a matrix to translate it whereever you want

I separated that step from the others as it may be the case that you wouldn't always want to reposition the object at it's original model origin.

For instance (pun intended), you may want to use that single model to draw several cylinders at various places in your world. In that case, you could create a base matrix:

base_matrix = Mt_1 * Ms * Mr;

// and then create an array of matrices

for each instance of the cylinder:

create Mt_2 for the desired location of this instance

this_instance_render_matrix = base_matrix * Mt_2

EDIT: As an example, I have a vehicle model comprised of a chassis mesh and a wheel mesh. Visually, all four wheels for the vehicle are the same, so I use the same model but draw it at four different locations in the world.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thank you all for your help, and the last post as well.

I managed to do what I wanted, this is to render bones of a skinned mesh but I was really missing the first step of the non uniform scaling of bones. With that small gap built into the bone mesh.

Anyway, thx a lot, I hope it can even help others.

This topic is closed to new replies.

Advertisement