PDA

View Full Version : How to change Axis of Rotation!!!!!!!!!!

just_started
07-30-2003, 07:36 AM
hi

i'm trying out a pgm in which i have a sea and many ships in it. i need to rotate this sea so that i can see it from all angles(360 degrees).

right now i've put the sea and ship into two display lists. i call the sea display list once and the ship display list more than once to have many ships on one sea.

my problem is that when i rotate the sea, it rotates on some axis of its own, each of the ships rotate on some axis of their own. sometimes, some ships move out of the sea, ie. their location within the sea keeps changing.

in the rotating fn, what i do is :
yRot = some changed value
updateGL();
// where yRot is the angle with which every object is drawn, both sea and ships

how does one specify an axis of rotation? is it possible?
will the use of pushMatrix and popMatrix help?
what is the best way to ensure that no ship ever moves out of the sea boundaries?

thanx 4 any help!

nexusone
07-30-2003, 10:43 AM
You need to look at the axis from two view points the objects and the world.

The sea is your world axis and each ship has it's own.

glMatrixMode(GL_MODELVIEW);

gluLookAt(.....) // Our point of view of the sea.

Draw_sea();

// Draw ship(s)
glPushMatrix();
glTranslate(....); location of ship on the sea
draw_ship():
glPopMatrix();
... Repeat above for each ship, store ship location in variables.

Try to think of you sea as a large map with objects on it, now when you rotate a map with your hand all the object on the map are also rotated the same amount.

It is the same with the gluLookAt, we are rotating the sea, but along with it the ship's are also being rotated.

From the ships point of view in relation to the sea, it has not moved. and in regards to keeping track of the ship we only need remember is location on the map and not the location of the sea in regards to what point we are viewing it.

I hope this makes sense!!

Originally posted by just_started:
hi

i'm trying out a pgm in which i have a sea and many ships in it. i need to rotate this sea so that i can see it from all angles(360 degrees).

right now i've put the sea and ship into two display lists. i call the sea display list once and the ship display list more than once to have many ships on one sea.

my problem is that when i rotate the sea, it rotates on some axis of its own, each of the ships rotate on some axis of their own. sometimes, some ships move out of the sea, ie. their location within the sea keeps changing.

in the rotating fn, what i do is :
yRot = some changed value
updateGL();
// where yRot is the angle with which every object is drawn, both sea and ships

how does one specify an axis of rotation? is it possible?
will the use of pushMatrix and popMatrix help?
what is the best way to ensure that no ship ever moves out of the sea boundaries?

thanx 4 any help!

[This message has been edited by nexusone (edited 07-30-2003).]

roffe
07-31-2003, 12:23 AM
Originally posted by just_started:

how does one specify an axis of rotation? is it possible?

The xyz parameters you specify to glRotate is the axis you wish to rotate around.

what is the best way to ensure that no ship ever moves out of the sea boundaries?

Track ship movement and make sure it doesn't cross boundaries.

just_started
07-31-2003, 06:01 AM
hey thanx!

i've been trying to do something like that.
no success so far. anyways i'll look thru again and again and again...

in any case, i thought of posting some of the code. in case anyone finds the pblm, plz let me know.

i think the pblm is somewhere in the Push/Pop matrix area or the order in which i'm giving the translation and rotation. but i just can't figure out a soln. my code is given below, not very detailed though. any help'll b appreciated. thanx!

Sea::Sea( QWidget* parent, const char* name )
: QGLWidget( parent, name )

{
xRot = yRot = zRot = 0.0; // default object rotation
xTrans = 0.0; yTrans = 1.0; zTrans = -10.0; // default object translation
scale = 1.0; // default object scale
}

void Sea :: paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();

GLfloat ship1distx = 1.5 etc...
fnCallList(subList, xRot, yRot, zRot, sub1distx, sub1disty, sub1distz, scale/2.0);
fnCallList(subList, xRot, yRot, zRot, sub2distx, sub2disty, sub2distz, scale/2.0);
fnCallList(seaList, xRot, yRot, zRot, 0.0, 0.0, 0.0, scale);
fnCallList(shipList, xRot, yRot, zRot, ship1distx, ship1disty, ship1distz, scale/2.0);
fnCallList(shipList, xRot, yRot, zRot, ship2distx, ship2disty, ship2distz, scale/2.0);

glPopMatrix();
glFlush();
}

void Sea::initializeGL()
{
qglClearColor(QColor::QColor(204,204,210));
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glEnable(GL_NORMALIZE);

subList = glGenLists(1);
glNewList(subList, GL_COMPILE);
makeSub();
glEndList();
seaList = glGenLists(1);
glNewList(seaList, GL_COMPILE);
makeSea();
glEndList();
shipList = glGenLists(1);
glNewList(shipList, GL_COMPILE);
makeShip();
glEndList();
}

void Sea::resizeGL( int w, int h )
{
glViewport( 0, 0, (GLint)w, (GLint)h );
glMatrixMode( GL_PROJECTION );
if(h==0) h = 1;
float aspect = (float)w/(float)h;
gluPerspective(45.0, aspect, 3.0, 15.0);
glMatrixMode( GL_MODELVIEW );
}

void Sea::fnCallList(GLuint list, GLfloat xRot, GLfloat yRot, GLfloat zRot, GLfloat distx, GLfloat disty, GLfloat distz, GLfloat scale)
{
gluLookAt(0.0,2.0,-3.0,0.0,0.0,-15.0,0.0,1.0,0.0);
glTranslatef(xTrans, yTrans, zTrans);
glPushMatrix();
glScalef(scale, scale,scale);
glRotatef( xRot, 1.0, 0.0, 0.0 );
glRotatef( yRot, 0.0, 1.0, 0.0 );
glRotatef( zRot, 0.0, 0.0, 1.0 );
glCallList(list);
glPopMatrix();

glTranslatef(distx, disty, distz);

glPopMatrix();
}

[This message has been edited by just_started (edited 07-31-2003).]

just_started
07-31-2003, 06:16 AM
there's some more!

this's the fn i use to rotate the sea.

void Sea::setYRotation( int degrees )
// take value from a slider
{
yRot = (GLfloat)(degrees % 360);
updateGL();
}

nexusone
07-31-2003, 08:00 AM
How about going back and looking at my example I posted again.

I am not supper with C++, but here is what I see.

Look's like some of your push/pop's are not needed or wrong order also you usage of glLoadIdentiry.
Also glFlush should only be called after you have drawn all of your objects in the scene.
Maybe you don't really need to call the gluLookAt and use the glTranslates/glRotates together!!

Remember we use push/pop matrix to save and restore our matrix.

voit Draw_ship(float x, float y, float x, float a)
{
glPushMatrix(); // save matrix state
glTranslatef( x, y, z); Place our ship somewhere in the sea.
glRotatef( a, 0, 0, 1); // Heading of our ship
Draw_list( ship );
glPopMatrix();
}

I think you are trying to make it more compicated then needed.

Go back to you paint routine, start with first setting from where you are looking at.
Then draw the sea, note that setting the look at point does the rotate of the sea for you.. only needed if some correct is needed, but should acount for that in the setting up of the look at point.

paint:

set_eye_view
draw_sea
place_ships
fin.

Sea::Sea( QWidget* parent, const char* name )
: QGLWidget( parent, name )

{
xRot = yRot = zRot = 0.0; // default object rotation
xTrans = 0.0; yTrans = 1.0; zTrans = -10.0; // default object translation
scale = 1.0; // default object scale
}

void Sea :: paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Need to set view of scene here.

glPushMatrix();

GLfloat ship1distx = 1.5 etc...
fnCallList(subList, xRot, yRot, zRot, sub1distx, sub1disty, sub1distz, scale/2.0);
fnCallList(subList, xRot, yRot, zRot, sub2distx, sub2disty, sub2distz, scale/2.0);
fnCallList(seaList, xRot, yRot, zRot, 0.0, 0.0, 0.0, scale);
fnCallList(shipList, xRot, yRot, zRot, ship1distx, ship1disty, ship1distz, scale/2.0);
fnCallList(shipList, xRot, yRot, zRot, ship2distx, ship2disty, ship2distz, scale/2.0);

glPopMatrix();
glFlush();
}

void Sea::initializeGL()
{
qglClearColor(QColor::QColor(204,204,210));
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glEnable(GL_NORMALIZE);

subList = glGenLists(1);
glNewList(subList, GL_COMPILE);
makeSub();
glEndList();
seaList = glGenLists(1);
glNewList(seaList, GL_COMPILE);
makeSea();
glEndList();
shipList = glGenLists(1);
glNewList(shipList, GL_COMPILE);
makeShip();
glEndList();
}

void Sea::resizeGL( int w, int h )
{
glViewport( 0, 0, (GLint)w, (GLint)h );
glMatrixMode( GL_PROJECTION );
if(h==0) h = 1;
float aspect = (float)w/(float)h;
gluPerspective(45.0, aspect, 3.0, 15.0);
glMatrixMode( GL_MODELVIEW );
}

void Sea::fnCallList(GLuint list, GLfloat xRot, GLfloat yRot, GLfloat zRot, GLfloat distx, GLfloat disty, GLfloat distz, GLfloat scale)
{
gluLookAt(0.0,2.0,-3.0,0.0,0.0,-15.0,0.0,1.0,0.0); // Remove only call once

glPushMatrix();
glTranslatef(xTrans, yTrans, zTrans); move after push

glRotatef( xRot, 1.0, 0.0, 0.0 );
glRotatef( yRot, 0.0, 1.0, 0.0 );
glRotatef( zRot, 0.0, 0.0, 1.0 );
glScalef(scale, scale,scale); Not sure how if may effect the rotate, so move just before calllist.
glCallList(list);
glPopMatrix();

glTranslatef(distx, disty, distz);// This does nothing, code missing here?

glPopMatrix(); // remove
}

Originally posted by just_started:
there's some more!

this's the fn i use to rotate the sea.

void Sea::setYRotation( int degrees )
// take value from a slider
{
yRot = (GLfloat)(degrees % 360);
updateGL();
}

[This message has been edited by nexusone (edited 07-31-2003).]

[This message has been edited by nexusone (edited 07-31-2003).]

[This message has been edited by nexusone (edited 07-31-2003).]

[This message has been edited by nexusone (edited 07-31-2003).]

just_started
08-01-2003, 05:54 AM
gosh, thanx a lot! it is working now. that was a nice write-up, nexusone. made the concept real clear. at least i knew where to do what, and why i had to do it...

this is the final working code. thought i'd post it for references.

Sea::Sea( QWidget* parent, const char* name )
: QGLWidget( parent, name )
{
// Set the view of the scene
xRot = 10.0; yRot = -20.0; zRot = 0.0; // default object rotation
xTrans = 0.0; yTrans = 1.0; zTrans = -10.0; // default object translation
scale = 1.0; // default object scale
}

void Sea :: paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat ship1distx = 0.5; etc..

// Initialize state variables for drawing the sea : World Coordinates
glMatrixMode( GL_MODELVIEW );
glTranslatef(xTrans, yTrans,zTrans);
glRotatef(xRot, 1.0, 0.0, 0.0);
glRotatef(yRot, 0.0, 1.0, 0.0);
glRotatef(zRot, 0.0, 0.0, 1.0);

// Draw undersea objects here before drawing sea so that it will be visible thru the sea

// Call Sea List
glCallList(seaList);

// Draw ships here

// Make sure all commands above are executed
glFlush();
}

void Sea :: Draw(GLuint list, GLfloat xRot, GLfloat yRot, GLfloat zRot, GLfloat distx, GLfloat disty, GLfloat distz)
{
glPushMatrix();

// location of objects on the sea : Local coordinates
glTranslatef(distx, disty, distz);

// Direction of the objects within sea
glRotatef( xRot, 1.0, 0.0, 0.0 );
glRotatef( yRot, 0.0, 1.0, 0.0 );
glRotatef( zRot, 0.0, 0.0, 1.0 );

// scale just before CallList()
glScalef(1.0, 1.0, 1.0);
glCallList(list);

glPopMatrix();
}

[This message has been edited by just_started (edited 08-01-2003).]

just_started
08-08-2003, 06:39 PM
hi

looks like my troubles r not over yet!

like i said earlier, my sea now turns and all ships turn with it. but i also need to be able to turn each individual ship along its own axis. this is to simulate ships moving towards viewer or to the left... the location of the ship within the sea must be the same, only its direction must change. the thing is i need to do both types of rotation. i use a slider to rotate the entire sea so that i can see the sea from different angles, but the individual ship direction must also change.

right now, if i give any value within the draw fn(i.e. xRot, yRot, zRot), the ships turns by that angle, but its location changes. i suppose this is because it is rotating with respect to the axis of the sea.

the code is the same as mentioned above. should i be using glLoadIdentity somewhere so that i can rotate the ships about its own axis?

thanx!

nexusone
08-09-2003, 05:32 AM
It could be a axis offset problem, remember openGL rotates everything around 0,0,0.

So if you ship's center is not 0,0,0, then you are rotation around some other part of the ship.

Example:

0,0,0 is here ---> +\_______] the your rotation will be from the bow of the ship.

You need to make sure 0,0,0 ----> \___+___] is at the center of the ship, ether by draw the ship based around the center or by translation before rotation to make it the center.
glTranslate // Translate to location on map
glRotate // Rotate ship
glTranslate // Translate after rotate is ship to create axis offset if needed.
ship()

Also remember that openGL works in reverse as to rotation/translate.

Originally posted by just_started:

hi

looks like my troubles r not over yet!

like i said earlier, my sea now turns and all ships turn with it. but i also need to be able to turn each individual ship along its own axis. this is to simulate ships moving towards viewer or to the left... the location of the ship within the sea must be the same, only its direction must change. the thing is i need to do both types of rotation. i use a slider to rotate the entire sea so that i can see the sea from different angles, but the individual ship direction must also change.

right now, if i give any value within the draw fn(i.e. xRot, yRot, zRot), the ships turns by that angle, but its location changes. i suppose this is because it is rotating with respect to the axis of the sea.

the code is the same as mentioned above. should i be using glLoadIdentity somewhere so that i can rotate the ships about its own axis?

thanx!