rotation & display

I have a world coordinate model, which I read from a file (the positon can be anywhere) with me.
I am trying to do 2 things:

  1. To display the entire model.

  2. To rotate the model on it’s own centric axis (ie, rotate about the axis which passes thru the center of the model in any 3 directions).

  3. I have done first one by calling glOrtho()
    and glTranslatef() (this is tricky as i have to generalize any data).

  4. After displaying the model in window, when I try to rotate the model around it’s own axis, it rotates as if the origin is in the world coord.

one condition: The model rotates around it’s own axis after translating the model to the origin. But I don’t want to do that as it is expensive to transform all points of the data.

Thanks in advance,
R.B

If the model is defined with respect to its own central axis, you should be able to just do this:

const float z_offset(-a_large_enough_float);

// Move the “camera” down the z axis.
glTranslatef(0.0f, 0.0f, z_offset);
// Rotate the model around an axis.
glRotatef(rotate_angle, rotate_axis[0], rotate_axis[1], rotate_axis[2]);
drawModel();

Hope that helps.

Thanks for your answer,
Yes, I am able to display the data in my window, but I need to rotate it around it’s own axis. I cannot use rotatef method as it rotates the model around global origin.

I tried to rotate the camera, but it is not so elgant.

Please help!

The method ffish proposed is essentially correct. You can use glRotatef exactly as described and it will function correctly.

What glRotatef does is multiply the current matrix by a rotation matrix. If the current matrix transforms objects from its local model coordinate system to camera coordinates, then multiplying a rotation matrix will rotate the object in its own local space, then transform to camera space.

Hi, here is the code:-

#include <stdio.h>
#include <iostream.h>

#include <ipm\CsaVector3D.h>
#include “GL/glut.h”

typedef struct
{
CsaVector3D vertex[3];
} triangle;

triangle *tri;
int nTriangles;

CsaVector3D min, max;

enum {FILL, WIRE};
int rendermode = WIRE;

static float transx = 0.0, transy = 0.0 , rotx = 0, roty = 0;
static int ox = -1, oy = -1;
static int mot = 0;
#define PAN 1
#define ROT 2

void menu(int selection)
{
rendermode = selection;
glutPostRedisplay();
}

void initDisplay()
{
GLfloat lightpos[] = {50.f, 50.f, 20.f, 1.f};
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat light_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};

glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);

// PROJECTION
glMatrixMode(GL_PROJECTION);

CsaVector3D dis = max - min;
CsaVector3D cen = min + dis/2.0;
GLdouble left	= cen[0] - dis[0];
GLdouble right	= cen[0] + dis[0];
GLdouble bottom = cen[1] - dis[1];
GLdouble top	= cen[1] + dis[1];
GLdouble zNear	= dis[2];
GLdouble zFar	= zNear + 3*dis[2];

glLoadIdentity();
glOrtho(left, right, bottom, top, zNear, zFar);
//glFrustum(-200., 200., -200., 200., 320., 640.);

// MODEL VIEW
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

/* turn on features */
glEnable(GL_DEPTH_TEST);

/* turn on spot light */
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);

/* place light 0 in the right place */
//glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

glClearColor(.0f, .0f, .0f, .0f);

}

void drawTriangles()
{
glBegin(GL_TRIANGLES);

for(int i=0;i&lt;nTriangles;i++)
{
	CsaVector3D vec = tri[i].vertex[0];
	glVertex3d(vec[0], vec[1], vec[2]);
	vec = tri[i].vertex[1];
	glVertex3d(vec[0], vec[1], vec[2]);
	vec = tri[i].vertex[2];
	glVertex3d(vec[0], vec[1], vec[2]);
}

glEnd();

}

void drawscene()
{
glPushMatrix();

CsaVector3D dis = max - min;
CsaVector3D cen = min + dis/2.0;
glTranslated(0, 0, transx * transy - cen[2] - 2*dis[2]);
cout &lt;&lt; "trans = " &lt;&lt; transx * transy - cen[2] &lt;&lt; endl;

//gluLookAt(cos(roty),sin(rotx),0, 0,0,-1, 0,1,0);

glRotatef(roty, 0.0, 1.0, 0.0);
glRotatef(rotx, 1.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 0.f);
drawTriangles();

glPopMatrix();

}

/* Called when window needs to be redrawn */
void redraw()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

switch(rendermode) {
case FILL:
drawscene();
break;
case WIRE: /* basic wireframe mode /
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
drawscene();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
}
if(glGetError()) /
to catch programming errors; should never happen */
printf("Oops! I screwed up my OpenGL calls somewhere
");

glutSwapBuffers();
}

void key(unsigned char key, int x, int y)
{
if(key == ‘\033’)
exit(0);
}

void pan(const int x, const int y)
{

transx +=  (x-ox)/10.;
transy -= (y-oy)/10.;
ox = x; oy = y;
glutPostRedisplay();

}

void rotate(const int x, const int y)
{
rotx += (y-oy) / 60.0;
if (rotx > 360.) rotx -= 360.;
else if (rotx < -360.) rotx += 360.;
roty += (x-ox) / 60.0;
if (roty > 360.) roty -= 360.;
else if (roty < -360.) roty += 360.;
ox = x; oy = y;
glutPostRedisplay();
}

void motion(int x, int y)
{
if (mot == PAN) pan(x, y);
else if (mot == ROT) rotate(x,y);
}

void mouse(int button, int state, int x, int y)
{

/* hack for 2 button mouse */
//if (button == GLUT_LEFT_BUTTON && glutGetModifiers() & GLUT_ACTIVE_SHIFT)
//button = GLUT_MIDDLE_BUTTON;

if(state == GLUT_DOWN) {
switch(button) {
case GLUT_LEFT_BUTTON:
    mot = ROT;
    motion(ox = x, oy = y);
    break;
case GLUT_MIDDLE_BUTTON:
    mot = ROT;
    motion(ox = x, oy = y);
    break;
case GLUT_RIGHT_BUTTON:
    mot = PAN;
    motion(ox = x, oy = y);
    break;
}
} else if (state == GLUT_UP) {
mot = 0;
}

}

void getBounds(CsaVector3D &min, CsaVector3D &max)
{
CsaVector3D vec = tri[0].vertex[0];
min = max = vec;

cout &lt;&lt; "init=" &lt;&lt; min &lt;&lt; "," &lt;&lt; max &lt;&lt; endl;
for(int i=0; i &lt; nTriangles; i++)
{
	for(int k=0;k&lt;3;k++)
	{
		vec = tri[i].vertex[k];
		for(int j=0; j&lt;3 ; j++)
		{
			if(min[j] &gt; vec[j]) min[j] = vec[j];
			if(max[j] &lt; vec[j]) max[j] = vec[j];
		}
	}
}
cout &lt;&lt; "final=" &lt;&lt; min &lt;&lt; "," &lt;&lt; max &lt;&lt; endl;

}

/* Parse arguments, and set up interface between OpenGL and window system */
void glDisplay(triangle *triangles, int nTri)
{
if(triangles == NULL) return;

tri = triangles;
nTriangles = nTri;

getBounds(min, max);

//glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("triangle display");
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutMouseFunc(mouse);
glutMotionFunc(motion);

glutCreateMenu(menu);
glutAddMenuEntry("Solid Fill", FILL);
glutAddMenuEntry("Wireframe", WIRE);
//glutAttachMenu(GLUT_RIGHT_BUTTON);

initDisplay();

glutMainLoop();

}

void main(int argc, char *argv[])
{
CsaVector3D offsetVec = CsaVector3D(100,200,300);
triangle *t = (triangle *)malloc(sizeof(triangle) * 4);

t[0].vertex[0] = CsaVector3D(0,0,0) - offsetVec;
t[0].vertex[1] = CsaVector3D(100,0,0) - offsetVec;
t[0].vertex[2] = CsaVector3D(50,50,50) - offsetVec;

t[1].vertex[0] = CsaVector3D(50,50,50) - offsetVec;
t[1].vertex[1] = CsaVector3D(0,0,100) - offsetVec;
t[1].vertex[2] = CsaVector3D(0,0,0) - offsetVec;

t[2].vertex[0] = CsaVector3D(50,50,50) - offsetVec;
t[2].vertex[1] = CsaVector3D(0,0,100) - offsetVec;
t[2].vertex[2] = CsaVector3D(100,0,100) - offsetVec;

t[3].vertex[0] = CsaVector3D(50,50,50) - offsetVec;
t[3].vertex[1] = CsaVector3D(100,0,100) - offsetVec;
t[3].vertex[2] = CsaVector3D(100,0,0) - offsetVec;

glDisplay(t, 4);

}

I didn’t look at all the code, but I think I understand what your problem is. Are you saying that the data for your model is not centered around the origin? That is, the “center” of the model about which you want to rotate is not at the origin. If that is the case you can do something like so…

DoAnyCameraLikeTransformations();

glTranslate(center.x, center.y, center.z);
glRotate(whatever…);
glTranslate(-center.x, -center.y, -center.z);

Esentially what this does is to translate your model to the origin, where you can then correctly do your rotations, and then translate it back to it’s proper location.

Now for your actual rotations, I notice you are rotating separately about the x and y axes. You are probably going to run into something called “gimbal lock.” Do a search on it for ways to avoid that. In short, it will matter which order you do the rotations, and there are times when you do things in a certain order, the rotation will not appear correct.