how to get the center of a model and rotate from there?

I’m trying to center an object in the middle of the screen. I read in some points from a cad like file to render an object on screen and when I rotate it, the center of rotation is around the center of one of the far ends of the box so it rotates funny and not from the direct center of the box (this model is like a long rectangle).

Doesn’t by setting the gluLookAt(…) center the camera on the model (which I think is default w/ what I have below)? Should I somehow have to measure the length and width of the model and replace it somehow?
The code I use to display it follows …

Any pointers or advice on doing this much appreciated?


public void display(GLDrawable drawable) {

gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

// reset the modelview matrix
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();

// viewing transformation
glu.gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);

// modeling transformation
gl.glTranslatef(xTrans, yTrans, zTrans);

gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
gl.glRotatef(zRot, 0.0f, 0.0f, 1.0f);
			
gl.glScalef(xScale, yScale, zScale);

// draw the model
model.draw(active_id);
model.drawInfo();
...

I probably should have posted my reshape(…) method since it has the glOrtho method in it (and if I understand correctly that it gets called at least one when the window appears). I was thinking by fixing the center of rotation, that this might fix another problem I have which is that my model is clipped on the near and far panes. But no matter what I set the near and far clipping panes to (near and far are never same value and near is always more than the far), it doesn’t affect my near and far panes, they still clip my model.

public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
GL gl = drawable.getGL();
GLU glu = drawable.getGLU();

gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
	
float aspectRatio = width / height;
	
// still need to fix near and far clipping panes
gl.glOrtho(0.0, 400.0, 0.0, 400.0, 1, -1);
	
/* doing this throws the shape out of proportion
if (width <= height) {
	gl.glOrtho(0.0, 400.0, 0.0 / aspectRatio, 400.0 / aspectRatio, 2, -1);
}
else {
	gl.glOrtho(0.0, 400.0, 0.0 * aspectRatio, 400.0 * aspectRatio, 2, -1);
}*/

}

Any help much appreciated.

You need to compute the centroid of your model by averaging the positions of the points. Then translate that point to the origin, rotate the model, and translate back.

Any advice on how to avg points?

You mean like, of all the points I read in from my CAD file, I take the largest and smallest X, largest and smallest Y, and largest and smallest of Z, avg those and … this is where I get lost, it sounds like I’d have to change all of the thousands of coordinates of the nodes which I use to draw all my meshing and move them to push the model in the center.

Or is there any good reading anywhere’s about getting the centroid?

I think once I get it in the center, I can just use the translate and rotate the way I have it now as it seems to sort of work. Or maybe I didn’t understand why I’d have to translate, rotate, then translate it back. I can already rotate my model now, it’s just of center.

Errrr … nevermind, I found out how now.

[quote]Using the x-dimension as an example, sum all of the x components of all points then divide by the number of points. Repeat for the y and z dimensions, then the resulting xyz triplet is the centroid. Note that this assumes that each point is equally “weighted”.
[/quote]
Thnx

I now have the centroid computed for my model and I tried to center it using gluLookAt with my new centroid coordinates as follows …

glu.gluLookAt(0.0, 0.0, 0.0, centroid.getX(), centroid.getY(), centroid.getZ(), 0.0, 1.0, 0.0);

But this didn’t change anything. Is this the correct function to use to center the model? This is located in my display() methods where I do my model tranformations.

Why do you like that gluLookAt so much? Just do this:
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glPushMatrix();//I use these assuming you may later on have other transformationf before /after; if you just use LoadIdentity after you are done with rotations.
gl.glTranslatef(-cent.x, -cent.y, -cent.z); //I am pretty sure you need to use reverse transformation; if it makes matters worse use direct ones :wink:
gl.glRotate3d(angle.a, angle.b, angle.g);//or whatever format you have
//render your model here
gl.glPopMatrix();

Should work… IMO :slight_smile:

I was confused between adjusting the view and model tranformations … but now I understand it’s the model transformation that needs to be adjusted.

Anyways, I did that but still can’t get it to rotate around the center. I now have the following …


public void display(GLDrawable drawable) {

// reset the modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();

// viewing transformation
glu.gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);
			
// modeling transformation
gl.glScalef(xScale, yScale, zScale);

// these translations are keyboard inputs to move (translate) the model
gl.glTranslatef(xTrans, yTrans, zTrans);

// PROBLEM, doing this negative translation doesn't move the model to the centroid 
gl.glTranslated(-centroid.getX(), -centroid.getY(), -centroid.getZ());
							
    // and rotations don't occur around the center of model, but on one of the ends
gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
gl.glRotatef(zRot, 0.0f, 0.0f, 1.0f);

gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
			
model.draw(active_id);

gl.glDisable(GL.GL_BLEND);
gl.glFlush();

The problem lies in the ordering of the transformations. The modelview transformation is represented as a 4x4 matrix. Each time you do a transformation operation (translate, scale, rotate) a 4x4 matrix representing this transformation is multiplied to the current modelview matrix. Matrix multiplication is not commutative, so the order in which you call these operations is important. In your code, when you call

gl.glTranslated(-centroid.getX(), -centroid.getY(), -centroid.getZ());

The point at ‘centroid’ will not actually be translated to (0, 0, 0) since you have done a bunch of other translations before namely the implicit one in gluLookAt and the keyboard one. Additionaly there’s a scale in between there, which also modifies the result of the translation, so in fact after the

gl.glTranslated(-centroid.getX(), -centroid.getY(), -centroid.getZ());

you are translating to

(xScale * (xTrans - centroidX), yScale * (yTrans - centroidY), -100 + zScale * (zTrans - centroidZ))

The simplest solution is to do the rotation first, then perform all the other transformations. If I’m not mistaken the following code should do the trick:

// reset the modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();

// Translate the center of the model the origin, rotate and translate back
gl.glTranslated(-centroid.getX(), -centroid.getY(), -centroid.getZ());
gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
gl.glRotatef(zRot, 0.0f, 0.0f, 1.0f);
gl.glTranslated(centroid.getX(), centroid.getY(), centroid.getZ());

// viewing transformation
glu.gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);
            
// modeling transformation
gl.glScalef(xScale, yScale, zScale);

// these translations are keyboard inputs to move (translate) the model
gl.glTranslatef(xTrans, yTrans, zTrans);

An alternative solution would be to take all the previous transformations into account. To do this you could take the point ‘centroid’, transform it using the model-view matrix and then translate using the transformed point.

// reset the modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();

// viewing transformation
glu.gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);
            
// modeling transformation
gl.glScalef(xScale, yScale, zScale);

// these translations are keyboard inputs to move (translate) the model
gl.glTranslatef(xTrans, yTrans, zTrans);

// Translate the center of the model the origin, rotate and translate back
float[] modelViewMatrix = new float[16];
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modelViewMatrix);
float[] centroid = new float[] {centroid.getX(), centroid.getY(), centroid.getZ(), 1};
... do matrix multiplication here (centroid * modelViewMatrix);

gl.glTranslated(-centroid.getX(), -centroid.getY(), -centroid.getZ());
gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
gl.glRotatef(zRot, 0.0f, 0.0f, 1.0f);
gl.glTranslated(centroid.getX(), centroid.getY(), centroid.getZ());

This is all off the top of my head, so I hope I didn’t make any obvious mistakes :slight_smile: