Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Transformations

Started by Great_White Oct 27, 2007 at 7:38 PM 4 replies 800+ views
Original Post
Great_White
Great_White
How do I transform my objects around a fixed coordinate system rather than the object's local coordinate system?
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole o
strtok
strtok
Well, if you have an object with it's own local coordinate system, you can put it into another coordinate system by translating it. For instance, to get an object into the world's coordinate system, you translate the object's local coordinate system by the object's position in the world. If I misunderstood the question, please clarify.
Great_White
Great_White
I've checked the OpenGL FAQ. If we premultiply the current matrix by a transformation matrix it will transform the object w.r.t the world axis not local space. But gl transformation calls only postmultiply. How can I make a premultiplication ?
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole o
strtok
strtok
You apply your transformations in reverse order. The last transformation you make actually has the effect of being the first transformation applied. So, like this:

glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(100.0F, 100.0F, 0.0F);   //Move object to (100, 100, 0) in worldglRotatef(45.0F, 0.0F, 1.0F, 0.0F);   //Rotate the object 45 degress around Y axisglScalef(10.0F, 10.0F, 10.0F);        //Scale the object


What happens to the object is this:

1. It gets scaled by 10 in x, y, and z
2. It gets rotated around the Y axis, at its center, by 45 degrees
3. It gets moved to world position (100, 100, 0)

The reason this is the case is that OpenGL uses column vectors. When transforming a column vector by a matrix, the matrix has to be on the left and the vector on the right. This has the effect that when you post-multiply the transformation matrix, you are actually adding a transformation to be applied earlier than the existing transformations. Hope this makes sense.
haegarr
haegarr
A chain of n transformations is mathematically written down as
M := M1 * M2 * ... * Mn

Matrix multiplication isn't commutative (so you can't exchange 2 matrices and expect to get the same result), but the order of performing the multiplications itself plays no role:
( M1 * M2 ) * M3 == M1 * ( M2 * M3 )
Please bear in mind that vectors are just 1 column or 1 row matrices.

If using column vectors (as OpenGL does), such a transformation is applied to a vector like so:
v' := M * v = M1 * M2 * ... * Mn * v

Due to OpenGL uses post-multiplication, you simply provide OpenGL with the data from left to right. I.e. you first provide M1, then with M2, ..., and last but not least v. Due to the feature shown above, it is totally okay to provide all transformations before providing the vertices. As an example, the sequence
glLoadIdentity();
glRotate(...); // M1
glTranslate(...); // M2
glScale(...); // M3
glVertex(...); // the 1st v
glVertex(...); // the 2nd v
glVertex(...); // the 3nd v
...
works like
M := I * M1 * M2 * M3
v1' := M * v1
v2' := M * v2
v3' := M * v3
...

The effect becomes clear when remembering (from the said above) that
M1 * M2 * M3 * v
can be written as
M1 * ( M2 * ( M3 * v ) )

Interpreting this one can say that M3 is applied to v, M2 is applied to the result of the former transformation, and M1 is applied to the respective result. This fact is what strtok means with "applied in reverse order" (although I'm not happy with using this term here, since the math shows that OpenGL doesn't revert anything in a closer sense; but that is a matter of taste).

A local co-ordinate frame L can be understood as a transformation that maps geometry given in the (local) frame to the parent frame (i.e. the co-ordinate frame where the local frame is given in). Without loss of generality we assume that L is given in the "world". So geometry in the local frame is transformed into the world by
vw := L * vl

A transformation M that should be applied to the geometry is given in a co-ordinate frame. You get the desired effect if and only if you apply the transformation to the geometry in the same co-ordinate frame. This can be reached by transforming the geometry into the frame where M is given in (and normally transforming the result back to the local frame).

Assume e.g. that M is given already in the geometry's local frame: Ml. Then you can apply it directly, yielding in a transformed geometry still given in its local frame:
vl' = Ml * vl

The transform M may alternatively be given in "world" frame: Mw. So you have to compute the Ml from Mw first, yielding in
Ml := L-1 * Mw * L

Why this? Setting in you get
vl' = L-1 * Mw * L * vl = L-1 * ( Mw * ( L * vl ) )
Here you can see exactly the steps descibed above: The geometry is transformed into the wanted frame (here from its local frame to "world"), the wanted transformation is applied, and the result is transformed back to the local frame. You can drop the back transformation, of course, if you want the result be given in the world frame.

So, for OpenGL in that case, you would have to provide the inverse of the local frame's transformation, followed by the desired transformation, followed by the local frame's transformation.
Great_White
Great_White
Thats ok, suppose I have a sphere sitting on the world coordinate origin, and one box rotating about the world's y-axis and also x-axis. When I write the above code, after some translation in the z-axis, the box rotation behave stranglely i.e it rotates around z-axis instead of y-axis. I think thats because of the postmultiplication


// Draw a sphere at the world originglPushMatrix();DrawSphere();glPopMatrix();// Draw a boxglPushMatrix();glRotatef(pitch, 1.0f, 0.0f, 0.0f); glRotatef(yaw, 0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 0.0f, transZ);DrawCube();glPopMatrix(); 
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole o

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.