Graphic transforms

P

Peter Oliphant

I'm working with Graphics transforms (i.e., RotateTranform,
TranslateTransform and ScaleTransform ). Are these applied to the WORLD
(graphics container) before drawing into that world (graphics container)?
That is, if I apply a Rotation of 90 degrees clockwise then the old x-axis
is now the new y-axis and the old y-axis is now the new x-axis
(sign-reversed due to the fact that the y-axis of a screen increases the
lower on the display).

I ask because I couldn't figure out what the 'rotation point' for each
object I draw, then it occured to me I'm probably
rotating-translating-scaling the world instead. If I'm correct, doubling the
x-scale will HALVE the x-dimensions of the graphic objects being drawn. This
is in contrast to the scale transform being applied to the object itself,
which would result in it doubling the object in x-size...

Thus, if tranforms are applied to the world (graphics container), I should
apply the reverse operations I want to have as an affect of the object
(e.g., translate in the opposite direction, lower scale to increase object
size, rotate counterclockwise to rotate object clockwise, etc.)...

Have I got this right? : )

[==P==]
 
O

Olaf Baeyens

I'm working with Graphics transforms (i.e., RotateTranform,
TranslateTransform and ScaleTransform ). Are these applied to the WORLD
(graphics container) before drawing into that world (graphics container)?
That is, if I apply a Rotation of 90 degrees clockwise then the old x-axis
is now the new y-axis and the old y-axis is now the new x-axis
(sign-reversed due to the fact that the y-axis of a screen increases the
lower on the display).
I have the impression that it is the first time you work with this type of
functionality.
Did you ever program in DirectX or OpenGL?
If not, then you have a steep learning curve to understand this all.

(This based on my OpenGL adventures)

First of all, check out "affine space" in google, that is a good starting
point.

Second you must understand that every translate and rotate will create a new
coordinate system relative towards the previous one.
Also understand that a rotate and then a translate will have a different
result compared to a translate first and then rotate.

Technically, you could say that your camera is alway in coordinate 0,0,0 and
a rotation of 0,0,0. so your Y will be always right and the Y always up when
you give draw commands. This is because you are working in local
coordinates. And when you finally have drawn you scene then the camera
rotation and translation will shift your scene away from the camera giving
the impression that there is a camera.

Now, it is up to choose what coordinate system you want to use, first rotate
then translate or first translate and then rotate. Whatever you do, stick to
it for all objects you wish to paint. Do not mix it or you will get grey
hair as I got it. ;-)

Another thing that you must separate, you will have multiple matrixes, that
you can set to the identify matrix.
One for the model view and one for the projection view. The projection view
is for warping the scene like perspective but not used for camera movement.
So camera movement must be done on the model matrix, not projection matrix
(I got confused in this one). The same for lights, use the model view
matrix.

If you want to work only in absolute coordinates, then always initialize the
model matrix to the identify before applying EVERY the translate-rotate.
If you want to use relative coordinates, then set the identify matrix BEFORE
you start the sequence of rotate-translate-rotate-translate sequence.
It is you choice what system you want to use.

Note: it is maybe a steep learning curve but it is worth putting the energy
into it. :)
The good news is, if you work in 2D, then it is simple, but once you start
in 3D then the rotation migth give you a lot of headaches.

Good luck.
 
P

Peter Oliphant

Actually, I know this stuuf pretty well (I've been a game
designer/programmer for over 3 decades). But conventions can change, and I
was just interested in 'what' was being transformed and how the transforms
'responded' to parameters. It would be perfectly reasonable to have
transforms applied to the object in contrast to the world, but both paradigm
work. Now I know its the 'transform world' paradigm in this case.

I'm somewhat familiar with how to manipulate a graphic object: you translate
it to (0,0), scale and rotate(the order here doesn't matter IF scale is
consistent in both x and y directions), and then translate, followed by the
final inverse translation from (0,0) (the last two translation order also
doesn't matter). And in fact I already have my code working in this regard.

And, while writing code, I found out the convention is a little 'mixed'.
While rotate and translate do work as inverses from the pov of the object
(e.g., if you want to move the object in a direction move the world in the
opposite direction), I was surprised to find out that 'scale' is odd, in
that to double the object size you double the scale of the world.

It works now, so thanks! : )

[==P==]
 
O

Olaf Baeyens

Actually, I know this stuuf pretty well (I've been a game
designer/programmer for over 3 decades).
Oops my mistake, now I know somone that I can ask question to when I have
this probem. :)
And, while writing code, I found out the convention is a little 'mixed'.
While rotate and translate do work as inverses from the pov of the object
(e.g., if you want to move the object in a direction move the world in the
opposite direction), I was surprised to find out that 'scale' is odd, in
that to double the object size you double the scale of the world.
You mean you double the local scale so your object gets drawn 2 times as
much?
It is hard to imagine that the rest of the world suddenly doubles too.

Of course if you scale up by 2, then your camera movement will also scaled
with 2.
So somehow you must push the model matrix before the scale of the object on
the stack and pop it back again for the camera translation.
Or am I missing something here?

Now I am very curious. :)
 
P

Peter Oliphant

Of course if you scale up by 2, then your camera movement will also scaled
with 2.
So somehow you must push the model matrix before the scale of the object
on
the stack and pop it back again for the camera translation.
Or am I missing something here?

Now I am very curious. :)

This is the idea. One thinks of rotation as happening 'naturally' about a
certain point of an object. For example, one thinks of rotating a square
about its center point. Lets call this the rotation point of an object, and
measure it as relative to the upper left hand corner of the smallest
rectangel that can contain it (i.e., relative to what the .NET Framework
thinks is its Left and Top points), and call this [rotate_dx, rotate_dy].

Similarly, if one is scaling in an x of y direction separately, one thinks
of this as happening when the object is in a certain 'rotational
orientation'. For example, we think of a square 'naturally' as its sides
being parallel to the x-axis and y-axis.

Thus, the first thing to do is to decide what the natural orientation for an
object is, and build it this way as your model. Then pick a rotation point
for it.

Ok, here we go. Say the object is to be placed at location (x,y) with
rotation r and scale_x and scale_y. First perform a translation of the
object so its rotation point is at (0,0). That is, move the world (-x,-y)
and then (-rotate_dx, -rotate_dy). We'll call this translate transform T =
(-x-rotate_x, -y-rotate_dy).

Now, as far as other transforms are concerned, the object is located at the
world origin. Now we must scale before we rotate, since we can scale
independently on both x and y directions, and our model is the correct
orientation. So we now apply scaling.

We can now apply rotate since scaling does not move the rotation point
(thats why we put it at world (0,0) since multiplying by anything still
results in (0,0)).

We can now move the object back to its original position, so we applt the
INVERSE of what we defined before as T. Thus, we translate by ( x+rotate_x,
y+rotate_y ). Note that since this is done after the scaling the camera
position is NOT scaled along with the object!!! Finally, we can apply any
additional translation in order to move the object from last position.

Thus the full transform function is as follows:

transform = T(-x-rotate_dx,-y-rotate_dy) S(scale_x,scale_y) R(r)
T(x+rotate_dx, y+rotate_dy) T(dx, Tdy)

applied from left to right, with:

T = translate
R = rotate
S = scale

And there you have it! The trick is moving it to the wrod origin before
scaling and rotating to ease the computations, and to scale before rotating
since scaling can be performed on two axes.

Is that what you were asking? : )

[==P==]
 
O

Olaf Baeyens

This is the idea. One thinks of rotation as happening 'naturally' about a
certain point of an object......
...
Thus the full transform function is as follows:

transform = T(-x-rotate_dx,-y-rotate_dy) S(scale_x,scale_y) R(r)
T(x+rotate_dx, y+rotate_dy) T(dx, Tdy)

applied from left to right, with:

T = translate
R = rotate
S = scale

And there you have it! The trick is moving it to the wrod origin before
scaling and rotating to ease the computations, and to scale before rotating
since scaling can be performed on two axes.

Is that what you were asking? : )
I believe you just killed the newsgroup with this quantum mechanics like
explanation. :)
A lot of people here will need counseling here I guess. :)

But you are right in your explanation.

But you forget that every object has another rotation called orientation.
;-)
First is the rotation and translation regarding of your parent starting
coordinate.
Second the orientation rotation on it's own axis (assuming that you do not
have an offset)

I am happy that GDI+ has DirectX and OpenGL like transforming functionality.
I missed that in GDI a lot.

I noticed that in the Windows vista they have created a very simple DirectX
engine usable in .NET, so I guess that 3D visualization will become much
more easy to implement.
But nevertheless, translation/rotation/scaling is confusing for any newbie
trying it.
 
P

Peter Oliphant

I found out (the hard way) that my explanation was too simplified. I now am
aware it's a bit more complex than I previously thought.

For example. Translation. If you translate before you rotate then the
rotation is not about the desired rotation point. Further, one should scale
before rotating since scaling is on two different axis, and if rotation is
applied first then scaling the x-axis will be in the direction of the
ROTATED x-axis.

So. one must apply scale, then rotate, then translation. Before these
operations the object's rotation point must be translated to the origin (so
that rotation is, indeed, about this point), and after all is done
translated back the reverse vector that moved it to the origin.

Now, since translation must happen after both rotation and scaling, to
translate with respect to the original (screen) coordinate system the
translation must be adjusted accordingly. Thus, it must be rotated and
scaled as such:

adjusted_trans_x = ((trans_x * cos) - (trans_y * sin)) / scale_x
adjusted_trans_y = ((trans_y * cos) + (trans_x * sin)) / scale_y

Sooooo, one must 'bite the bullet' with respect to translation, which is
ironic since without rotation and scaling translation is typically the most
computationally simple, but with it the most computationally complex! : )

[==P==]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top