## Rotating multiple objects? [newbie question]

### Rotating multiple objects? [newbie question]

Hi,

i want to write an application which shows 10 objects, numbered 0 to 9.
The user can select/deselect an object by pressing it's number on the
keyboard, and pressing the arrow keys should rotate all currently
selected objects. Of course if no keys are pressed, the objects
should stay in their current position, and if arrow keys are pressed
they will rotate further.

How do i do that? The red book says that when incrementally rotating
objects i should keep a variable for the total amount that i rotate,
then increment this variable each time a key is pressed and rotate
the object with the accumulated angle when drawing it.

But this only works for rotating about a single axis. As i want to
rotate about at least two axes (perhaps later the objects shall also
be moved), i need to store the actual current position, i.e. the
transformation matrices for all the 10 objects. This is because
rotating around the X-Axis and then around the Y-Axis is different
from rotating around the Y-Axis and then around the X-Axis. Therefore,
i need to know more than the accumulated angle in X- and Y-direction.

With the matrix stack, i can't store and reload 10 matrices in arbitrary
order. So what is the cleanest and most efficient way to do what i want?

Another question: which params should i pass to glutInit() when i write
a win32 application? When writing a console application, i can pass the
argc and argv values that my programs gets, but these are not available
in a pure win32 application.

Regards,

Tobias

### Rotating multiple objects? [newbie question]

hi.

Tobias Thierer schrieb:

...

Quote:> But this only works for rotating about a single axis. As i want to
> rotate about at least two axes (perhaps later the objects shall also
> be moved), i need to store the actual current position, i.e. the
> transformation matrices for all the 10 objects. This is because
> rotating around the X-Axis and then around the Y-Axis is different
> from rotating around the Y-Axis and then around the X-Axis. Therefore,
> i need to know more than the accumulated angle in X- and Y-direction.

...

I assume the following situation:
your scene shows ten objects, aligned along the x-axis,
where positions range from -x_max to +x_max.
-x_max indicates the leftmost, +x_max indicates the rightmost position.

^y
|
----*-*-*-*-*|*-*-*-*-*---->x
|

* object

each object is rotated independently...
I think, you can solve your rot-problem
with that mentioned "angle-array" pretty well -
without any explicit matrixmult-operations.
as long as the order of your rot-calls is the same
for every object, it should work fine.

here comes an idea for coding the solution:
[note: this sample has been intended to be expressive -
not smart]
the clue is to rotate the objects all in the same way.
matrixstack-operations will take care of that,
since they "de-rotate" the coord-sys for each object.

the data:
{
obj_posX[0 .. 9] : x-coord array
obj_rotX[0 .. 9] : "angle around x" -array
obj_rotY[0 .. 9] : "angle around y" -array
obj_rotZ[0 .. 9] : "angle around z" -array

Quote:}

render function [RPY]:
{
for (int i = 0; i < 10; i++)
{
glPushMatrix()
glTranslate(obj_posX[i])
glRotate(obj_rotX[i])
glRotate(obj_rotY[i])
glRotate(obj_rotZ[i])
glPopMatrix()
}

Quote:}

user rotates selected objects:
{
on_key('4'):
for every selected object:
obj_rotX[] -= angleX_inc
limit obj_rotX to [0 .. 360]

on_key('6'):
for every selected object:
obj_rotX[] += angleX_inc
limit obj_rotX to [0 .. 360]

on_key('2'):
for every selected object:
obj_rotY[] -= angleY_inc
limit obj_rotY to [0 .. 360]

on_key('8'):
for every selected object:
obj_rotY[] += angleY_inc
limit obj_rotY to [0 .. 360]

on_key('1'):
for every selected object:
obj_rotZ[] -= angleZ_inc
limit obj_rotZ to [0 .. 360]

on_key('3'):
for every selected object:
obj_rotZ[] += angleZ_inc
limit obj_rotZ to [0 .. 360]

Quote:}

this would apply a "RollPitchYaw"-kind transformation
to each object. the "RPY"-transformation is a well known
alternative to the "Homogeneous"-transformation for describing
rotations uniquely. although "H"-transformations will be the
better choice for dealing rotations AND translations uniquely.

if you want to switch to homogeneous coords,
you will have to do the "de-rotating"-trick for each rotation.
this re-written render function shows how to do this:

render function [homogeneous]:
{
for (int i = 0; i < 10; i++)
{
glPushMatrix()
glTranslate(obj_posX[i])

glPushMatrix()
glRotate(obj_rotX[i])
glPopMatrix()

glPushMatrix()
glRotate(obj_rotY[i])
glPopMatrix()

glPushMatrix()
glRotate(obj_rotZ[i])
glPopMatrix()

glPopMatrix()
}

Quote:}

every rotation is now handled independently.
and this is the reason for the introduction of the matrix-stack -
each entry on this stack [aka 4x4 H-matrix]
represents a coordsys -
one is able to change the context by calling glPush- /PopMatrix().

the first entry is called world-coordsys.
follow-up entries are called obj-coordsys's.

start at the base of the world-coordsys for this entry.

enough!
I am talking and talking - although
I am sure you have already known that.

the second render function will do the job, I guess.

cheers,
christian

### Rotating multiple objects? [newbie question]

[
PS:
these are some EXTRA thoughts on the issue.
actually, I did not want to post this too -
one could think, I am "posing" or something...
I am not.
I am just having fun.
or skip it.

I also thought of another solution -
namely doing this HT-thing in a weird way.
I thought it would be nice to make use of glMultMatrix()
on the one hand, but carrying not more than three angle-infos
with me on the other hand.
such a solution exists -
taking the effort of transforming the keystrokes
via spherical-cartesian-coordtransformation
or an equivalent.

consider the following H-matrix:
a 0 0 x
0 b 0 y
0 0 c z
0 0 0 1

it represents a vector at position (x, y, z),
x, y, z will indicate the positions of the objects,
a, b, c (normalized) will do the rotation.

by multiplying this matrix with the identity-matrix,
you would move your object to (x, y, z)
and the orientation of the object would be
transformed via (a, b, c) -
(1, 1, 1) then equals "no object rotation".

now, rotating an object is also represented
by moving the direction vector (a, b, c)
on a sphere-surface with radius 1.

manipulating (a, b, c) by keystrokes
in the limits [-1 .. 1] with no further efforts
would result in ... bullshit.
the direct coupling between keystrokes
and rotations is a triangular function and
your rotations would speed up and slow down
following sinus-waves when holding down the rot-keys.

we will have to transform the keystrokes like this:
[the angles are in rad - 1 rad = 180/PI degree -
glRotate() uses degrees]

obj_rotX =    arcos{[(a+b+c) - 0.5*a] /
[sin(arcos(0.5))* sin(arcos(a))]}
obj_rotY = PI/2 + arcos{[(a+b+c) - 0.5*b] /
[sin(arcos(0.5))* sin(arcos(b))]}
obj_rotZ = 2*PI - arcos{[(a+b+c) - 0.5*c] /
[sin(arcos(0.5))* sin(arcos(c))]}

how I have found these equotations?
for each rotation, there are three known vectors,
e.g for rotation around x
(1,1,1) : "no rotation" vector
(1,0,0) : x-axis base vector
(a,b,c) : resulting rotation vector

between each two of them,
we have some angles,
which are calculated via the vector product,
e.g for phi = <[(a,b,c); (1,1,1)]
phi  = arcos[(a+b+c)*(1,1,1)]
= arcos(a+b+c)

these angles are simply the sides of a spherical triangular.
the basic idea now is to calculate one angle of a spherical
triangular where three sides are known.
one has to observe the static angle between the "no rotation"
vector and the base vectors, too -
so the angle counting is based.

et voila!
last step - solving these equotations for a,b,c...
probably impossible.

cheers,
christan
]

### Rotating multiple objects? [newbie question]

Hi,

Christian Schlette schrieb:

Quote:> Tobias Thierer schrieb:

> > But this only works for rotating about a single axis. As i want to
> > rotate about at least two axes (perhaps later the objects shall also
> > be moved), i need to store the actual current position, i.e. the
> > transformation matrices for all the 10 objects. This is because
> > rotating around the X-Axis and then around the Y-Axis is different
> > from rotating around the Y-Axis and then around the X-Axis. Therefore,
> > i need to know more than the accumulated angle in X- and Y-direction.

> ...

> I assume the following situation:
> your scene shows ten objects, aligned along the x-axis,
> where positions range from -x_max to +x_max.
> -x_max indicates the leftmost, +x_max indicates the rightmost position.

>                       ^y
>                       |
> ----*-*-*-*-*|*-*-*-*-*---->x
>                       |

> * object

Yes.

Quote:> each object is rotated independently...

Yes.

Quote:> here comes an idea for coding the solution:
> [note: this sample has been intended to be expressive -
> not smart]
> the clue is to rotate the objects all in the same way.
> matrixstack-operations will take care of that,
> since they "de-rotate" the coord-sys for each object.

> the data:
> {
> obj_posX[0 .. 9] : x-coord array
> obj_rotX[0 .. 9] : "angle around x" -array
> obj_rotY[0 .. 9] : "angle around y" -array
> obj_rotZ[0 .. 9] : "angle around z" -array
> }

Unfortunately this will not work. As i stated in my first
mail, not only the accumulated angels for the objects but
also the order in which they are applied matters.

The rotation should always be applied with respect to the
global coordinate system.

Imagine you are rotating a cube 180 about the X-Axis.
Then you press the key to rotate it right about the
y-Axis, but it will rotate to the left! Why? Because
the local coordinate system (and therefore the direction
of the Y-Axis) has changed during rotation about the X-Axis.

Therefore i need to save and restore the exact transformation
than three floats angleX, angleY, angleZ can provide.

Quote:> this would apply a "RollPitchYaw"-kind transformation
> to each object. the "RPY"-transformation is a well known
> alternative to the "Homogeneous"-transformation for describing
> rotations uniquely. although "H"-transformations will be the
> better choice for dealing rotations AND translations uniquely.

> if you want to switch to homogeneous coords,

What do you mean with homogenous coords? The homogenous coordinate
is just one part of a four dimensional coordinate. Where in
the following code sample does a homogenous coordinate appear?

- Show quoted text -

Quote:> you will have to do the "de-rotating"-trick for each rotation.
> this re-written render function shows how to do this:

> render function [homogeneous]:
> {
>     for (int i = 0; i < 10; i++)
>     {
>     glPushMatrix()
>         glTranslate(obj_posX[i])

>         glPushMatrix()
>             glRotate(obj_rotX[i])
>         glPopMatrix()

>         glPushMatrix()
>             glRotate(obj_rotY[i])
>         glPopMatrix()

>         glPushMatrix()
>             glRotate(obj_rotZ[i])
>         glPopMatrix()

>     glPopMatrix()
>     }
> }

> every rotation is now handled independently.

Well...this function does a nice number of rotations but actually
doesn't draw any objects. Whereever i place the draw-instruction,
the object will never rotate about more than one axis.

Quote:> and this is the reason for the introduction of the matrix-stack -
> each entry on this stack [aka 4x4 H-matrix]
> represents a coordsys -
> one is able to change the context by calling glPush- /PopMatrix().

Yeah. I need to save and restore the 10 transformation matrices
to save the old rotations of the 10 objects. But with glPushMatrix()
and glPopMatrix(), i can only save and restore the Matrices in
a LIFO way, not with random access as i need it.

Quote:> glLoadIdentity() == tabula rasa -
> start at the base of the world-coordsys for this entry.

> enough!
> I am talking and talking - although
> I am sure you have already known that.

> the second render function will do the job, I guess.

I don't understand how this should work. Where shall i put the
render() instruction?

Regards,

Tobias

### Rotating multiple objects? [newbie question]

hi.

I read all I have written - and
I must admit, that I was absolutely wrong.
voll daneben.
somehow, I mixed it all up and ended up
with weird ideas about what one could do.
unfortunately, I missed the point
and only produced an incredible mess.

you are right,
when claiming, one will not
get any results with the second render function.

did you read my second post, too?
do so.
there are two mistakes:
- it is not the vector product,
but the scalar product.
- since (1,1,1) is not normalized,
every occurancy of (a+b+c)
has to be (a+b+c)/(sqrt(3.0)).
every occurancy of PI/4
has to be divided by sqrt(3.0), too.

I apologize for these posts.
also my intentions were noble,
they are trash.

christian

### Rotating multiple objects? [newbie question]

On Sun, 17 Sep 2000 00:12:16 +0200, Tobias Thierer

>Hi,

>i want to write an application which shows 10 objects, numbered 0 to 9.
>The user can select/deselect an object by pressing it's number on the
>keyboard, and pressing the arrow keys should rotate all currently
>selected objects. Of course if no keys are pressed, the objects
>should stay in their current position, and if arrow keys are pressed
>they will rotate further.

>How do i do that? The red book says that when incrementally rotating
>objects i should keep a variable for the total amount that i rotate,
>then increment this variable each time a key is pressed and rotate
>the object with the accumulated angle when drawing it.

>But this only works for rotating about a single axis. As i want to
>rotate about at least two axes (perhaps later the objects shall also
>be moved), i need to store the actual current position, i.e. the
>transformation matrices for all the 10 objects. This is because
>rotating around the X-Axis and then around the Y-Axis is different
>from rotating around the Y-Axis and then around the X-Axis. Therefore,
>i need to know more than the accumulated angle in X- and Y-direction.

>With the matrix stack, i can't store and reload 10 matrices in arbitrary
>order. So what is the cleanest and most efficient way to do what i want?

>Another question: which params should i pass to glutInit() when i write
>a win32 application? When writing a console application, i can pass the
>argc and argv values that my programs gets, but these are not available
>in a pure win32 application.

>Regards,

>    Tobias

I am confronting  this problem in an app I am writing for the moment.
My solution is very depending on the number of vertices in the objects
(as allways) when it comes to timeconsuming.

What I do is that I lets the app remember my rotations a while back in
time, in the order that they were made. Then before rendering I just
make the same rotaions, in the same order again.

Of course one can not remember ALL rotations througout the game, so I
set a limit on how many rotations the application are to remember an
then when this limit is reached I multiply all the vertices in the
object with the accumulated rotations around the axes, using
glMultMatrix.

Perhaps not the most optimal solution but it should work I think.

Good luck

/Marcus

### Rotating multiple objects? [newbie question]

>On Sun, 17 Sep 2000 00:12:16 +0200, Tobias Thierer

>>Hi,

>>i want to write an application which shows 10 objects, numbered 0 to 9.
>>The user can select/deselect an object by pressing it's number on the
>>keyboard, and pressing the arrow keys should rotate all currently
>>selected objects.
...
>>But this only works for rotating about a single axis.
...
>>With the matrix stack, i can't store and reload 10 matrices in arbitrary
>>order. So what is the cleanest and most efficient way to do what i want?

Try glLoadMatrix() and glGet(GL_MODELVIEW_MATRIX), for example.
You can get the matrix in question and reload later on.
So for example:
double xa,ya,za;
glMatrixMode(GL_MODELVIEW);
glRotatef(xa,1,0,0);
glRotatef(ya,0,1,0);
glRotatef(za,0,0,1);
glGetDoublev(GL_MODELVIEW_MATRIX,matrix[x]);
// Later on...

You get the idea, no doubt.
Problem with iterative matrix rotations may be that you get a small
error when rotating constantly with little angles.
You can also do matrix calculations by yourself; check out the
wonderfully clean coded Phropecy SDK at www.twilight3d.com, where some
classes exist, amongst which a Matrix class, which shows how to do
this yourself (it has a LGPL license which is very flexible). Very
nicely coded, with no MS-variable-naming-pollution. ;-) Great stuff,
Jukka.
Seems Jukka has no problem in the errors that may occur when
continuing to rotate the same matrix.
The problem in rotating is gimbal lock, where axes fall on top of
XYZ axis (local to the object), or you could also check out
quaternions (also available in the Prophecy toolkit). Quats use 4
numbers to describe rotation, and the green book (Mark J. Kilgard,
"OpenGL programming in the X environment"?) contains trackball.c,
which uses this, IIRC. Have used it once, it worked fine. Though
matrices are more flexible and have some nice props which are usable
further on.

Quote:>>Another question: which params should i pass to glutInit() when i write
>>a win32 application? When writing a console application, i can pass the
>>argc and argv values that my programs gets, but these are not available
>>in a pure win32 application.

There is the pCmdLine you get at WinMain(), but you may have to parse
it yourself then. I haven't programmed using GLUT, so I don't know
much about glutInit. Don't think it has anything to do with your
rotation problem though.

Ruud van Gaal, GPL Rank +53.25
MarketGraph   : http://www.marketgraph.nl
Pencil art    : http://www.marketgraph.nl/gallery/
Car simulation: http://www.marketgraph.nl/gallery/racer/

### Rotating multiple objects? [newbie question]

Hiya,

> >On Sun, 17 Sep 2000 00:12:16 +0200, Tobias Thierer

> >>With the matrix stack, i can't store and reload 10 matrices in arbitrary
> >>order. So what is the cleanest and most efficient way to do what i want?

> Try glLoadMatrix() and glGet(GL_MODELVIEW_MATRIX), for example.
> You can get the matrix in question and reload later on.

Thank you very much! This is exactly what i was looking for!
I didn't know that i could query and reload the modelview matrix.

Quote:> So for example:
> double xa,ya,za;
> glMatrixMode(GL_MODELVIEW);
> glRotatef(xa,1,0,0);
> glRotatef(ya,0,1,0);
> glRotatef(za,0,0,1);
> glGetDoublev(GL_MODELVIEW_MATRIX,matrix[x]);
> // Later on...

> You get the idea, no doubt.

Yeah! Thanks!

Quote:> Problem with iterative matrix rotations may be that you get a small
> error when rotating constantly with little angles.

Yeah, of course, like a little translation of the object or so
through rounding errors in the matrix. But this is an acceptable
error.

Quote:> You can also do matrix calculations by yourself;

Of course, but basically i am using OpenGL to avoid such things ;-)
I wrote a raycaster and could just have copy+pasted my matrix
multiplication
code etc., but i want to use OpenGL for everything that it is
efficiently
capable of.

Quote:> check out the
> wonderfully clean coded Phropecy SDK at www.twilight3d.com, where some
> classes exist, amongst which a Matrix class, which shows how to do
> this yourself (it has a LGPL license which is very flexible). Very
> nicely coded, with no MS-variable-naming-pollution. ;-) Great stuff,
> Jukka.

Thank you for the URL, i have just browsed through the page and am
currently
inspection
during the next days.

Quote:> Seems Jukka has no problem in the errors that may occur when
> continuing to rotate the same matrix.
> The problem in rotating is gimbal lock, where axes fall on top of
> XYZ axis (local to the object), or you could also check out
> quaternions (also available in the Prophecy toolkit). Quats use 4
> numbers to describe rotation, and the green book (Mark J. Kilgard,
> "OpenGL programming in the X environment"?) contains trackball.c,
> which uses this, IIRC. Have used it once, it worked fine. Though
> matrices are more flexible and have some nice props which are usable
> further on.

I have just read somewhere that quaternions are some "further
development"
of complex numbers and can be used to describe rotations, but i do not
really know what they are and what they are exactly capable of. Perhaps
in the red book.

Quote:> >>Another question: which params should i pass to glutInit() when i write
> >>a win32 application? When writing a console application, i can pass the
> >>argc and argv values that my programs gets, but these are not available
> >>in a pure win32 application.

> There is the pCmdLine you get at WinMain(), but you may have to parse
> it yourself then. I haven't programmed using GLUT, so I don't know
> much about glutInit. Don't think it has anything to do with your
> rotation problem though.

Yeah, it doesn't have anything to do with it. The glutInit() functions
wants the commandline args because it extracts those that are intended
for the glut library (therefore, it also writes to these args).
Unfortunately,
the lib is too dumb to do just nothing if it gets 0 as argc, 'cause it
always expects to get at least one arg (the name of the executable).

Currently, i am just passing a single commandline arg ("foo.exe") to
glutInit(), and although this is a dirty hack and not correct, it works
fine.

Regards,

Tobias

### Rotating multiple objects? [newbie question]

On Tue, 19 Sep 2000 16:29:35 +0200, Tobias Thierer

>Hiya,

>> Try glLoadMatrix() and glGet(GL_MODELVIEW_MATRIX), for example.
>> You can get the matrix in question and reload later on.

>Thank you very much! This is exactly what i was looking for!
>I didn't know that i could query and reload the modelview matrix.

Almost everything (if not EVERYthing) from the OpenGL state is
queryable. Nice to remember for future things. :)

...

Quote:>> Problem with iterative matrix rotations may be that you get a small
>> error when rotating constantly with little angles.

>Yeah, of course, like a little translation of the object or so
>through rounding errors in the matrix. But this is an acceptable
>error.

I'm still wondering about that if I for example run a 3D race game for
an hour or so. Esp. since in my car sim I'm doing simulation at
somewhere between 100 and 1000Hz, so that's 1000 rounding errors per
second, at least. But well, I'll see.

Quote:>> You can also do matrix calculations by yourself;

>Of course, but basically i am using OpenGL to avoid such things ;-)

I know, I would do the same. However, OpenGL doesn't really provide
generic matrix functions on matrices other than the usual (projection,
modelview, texture).
So in your code, you might want to use matrix code nevertheless, for
example to store your object's orientations, as you do now. Sure, you
can abuse the modelview matrix for this, and it may be hw-accelerated
even, but it is not really very clean. And there may be a lot of
matrices around.

...

Quote:>I have just read somewhere that quaternions are some "further
>development"
>of complex numbers and can be used to describe rotations, but i do not
>really know what they are and what they are exactly capable of.

Hm, I don't understand them really, but what it amounts to is that
there are 4 parameters, instead of 3 (XYZ rotation). Then there is 1
constraint on the parameters, so you end up with 3 degrees of freedom.
The green book contains a complete .c example, but I have a C++ class
example which I can mail you. This emulates a trackball, where you
just construct it with the 'window' position, put in mouse movements
and it returns a rotation matrix ready for OpenGL use.

...

Quote:>Currently, i am just passing a single commandline arg ("foo.exe") to
>glutInit(), and although this is a dirty hack and not correct, it works
>fine.

Well, it really is so close to what is done in normal _main() code

Ruud van Gaal, GPL Rank +53.25
MarketGraph   : http://www.marketgraph.nl
Pencil art    : http://www.marketgraph.nl/gallery/
Car simulation: http://www.marketgraph.nl/gallery/racer/

How to rotate a group of objects when animating (auto key is on)?!

Usually I can just select the lot and rotate around a common axis
(pivot), but when auto-key is set then every object rotates around its
own axis. I don't think this happened in Max 4 (this is Max 5).

Oh yeah, and turning off Local Center During Animate check box in the
Preferences dialog doesn't help, doesn't seem to have any effect.

Piece of shit junk...