PDA

View Full Version : automatically center 3d object ???



holyburak
11-17-2003, 12:50 AM
hi all,

i'm trying to develop a pre-GUI for a statical analysis prog. of civil engineering.

i couldnt find out how to make the automatically read model(by the way i calculate the min and max's of it) be guaranteed to be seen at the center when first loaded.

shall i use glFrustum??

Thanks to all. http://www.opengl.org/discussion_boards/ubb/smile.gif
Burak

Rog
11-17-2003, 02:22 AM
You say you keep the min/max coordinates when you read your model. You should be able to use these to find the centre point of the model - it's just the average of these two 3D coordinates. Then you can glTranslate() to reposition your model wherever you want in your view.

E.g. if you want your model centered on the origin, do something like -

glTranslatef(-(max.x + min.x)/2.0f,-(max.y + min.y)/2.0f,-(max.z + min.z)/2.0f);

before you draw your model.

holyburak
11-17-2003, 02:35 AM
let me explain more briefly..
the way you tell it seems sth like below for a cube with max-min = 2 and glTranslatef(1.0f,1.0f,1.0f); => nothing seen.
it is ok when using glulookat but how can i make sure the model not to be clipped by the borders of my window?

thanks anyway Rog http://www.opengl.org/discussion_boards/ubb/wink.gif


Here's the code
--------------------------------------------

void COpenGLWindow: http://www.opengl.org/discussion_boards/ubb/biggrin.gifrawGLCube(void) // Draw cube
{

glLoadIdentity(); // Reset The Current Modelview Matrix

//glTranslatef(1.5f,0.0f,-7.0f); // Move Right 1.5 Units And Into The Screen 7.0
glTranslatef(1.0f,1.0f,1.0f);

//gluLookAt(0.0f,0.0f,10.0f,
// 0.0f,0.0f,0.0f,
// 0.0f,1.0f,0.0f);

glRotatef(rquad,1.0f,1.0f,1.0f); // Rotate The Quad On The X axis ( NEW )
glBegin(GL_QUADS); // Draw A Cube
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Blue
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)
glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)
glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
glVertex3f( 1.0f,-1.0f,-1.0f); // Top Right Of The Quad (Back)
glVertex3f(-1.0f,-1.0f,-1.0f); // Top Left Of The Quad (Back)
glVertex3f(-1.0f, 1.0f,-1.0f); // Bottom Left Of The Quad (Back)
glVertex3f( 1.0f, 1.0f,-1.0f); // Bottom Right Of The Quad (Back)
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)
glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)
glEnd(); // Done Drawing The Quad

rquad -= 0.15f; // Decrease The Rotation Variable For The Quad ( NEW )

}

[This message has been edited by holyburak (edited 11-17-2003).]

Rog
11-17-2003, 02:52 AM
Originally posted by holyburak:
let me explain more briefly..
the way you tell it seems sth like below for a cube with max-min = 2 and glTranslatef(1.0f,1.0f,1.0f); => nothing seen.


I think that should be glTranslatef(-1.0f, -1.0f, -1.0f) from my example, but no matter.

I see you also need to get the whole object in view, so you either need to scale to an appropriate size for your viewing volume, or set your viewing volume to encompass your object.

The latter is the way I'd do it and you also have all the info you should need from the min/max vertices. The extremes of x and y should determine your left/right and top/bottom clipping planes - you may need to adjust for one or other depending on the aspect ratio of your window to get the best fit.

The rest is just trigonometry. You already know how deep your model is (in z) so can use this together with the field-of-view angle you require to set the distance to the near/far clipping planes and the position of the "camera". Then, like you said originally, use all of these parameters in glFrustum() to define the view you want. Personally, I would still translate the model to centre on the origin and just use it's dimensions to set the limits for glFrustum() - it will make it easier to handle more than one object this way.

Did I get any closer this time? http://www.opengl.org/discussion_boards/ubb/smile.gif


[This message has been edited by Rog (edited 11-17-2003).]

holyburak
11-17-2003, 04:18 AM
can you give a more practical solution?
a code snippet? the idea is correct but i'm confused with all the concepts.

Rog
11-17-2003, 05:24 AM
Originally posted by holyburak:
can you give a more practical solution?

I'll try http://www.opengl.org/discussion_boards/ubb/smile.gif

Suppose you have the following information:

float minx = [smallest x in all model vertices]
float miny = [smallest y in all model vertices]
float minz = [smallest z in all model vertices]

float maxx = [largest x in all model vertices]
float maxy = [largest y in all model vertices]
float maxz = [largest z in all model vertices]

Then your model can be bounded by a sphere of radius r, centered on a point p, where -

p.x = (minx + maxx) / 2.0f;
p.y = (miny + maxy) / 2.0f;
p.z = (minz + maxz) / 2.0f;

r = sqrt((maxx - p.x)*(maxx - p.x) + (maxy - p.y)*(maxy - p.y) + (maxz - p.z)*(maxz - p.z));

If you're model is long and thin rather than vaguely spherical this may not give the best result but you'll get the general idea. At least if we assume the above, you can orient your model as you like without part of it poking outside the viewing volume.

The viewing volume will be that which encompasses the sphere. So the left and right bounds we can set as -r and +r respectively. Similarly, the top and bottom bounds are +r and -r respectively. In glFrustum(), these represent the points on the near clipping plane that get mapped to the bounds of the window.

To find out where we need the near and far clipping planes, we just need to choose a field of view angle (in the y direction by convention) - so say we choose 30 degrees. If we imagine a line drawn from the camera position, along the z axis to the centre of the sphere, this is the base of a triangle. The height of the triangle is the distance from the centre of the sphere to the top of the model (i.e. the radius r). With an angle of 30 degress, this means that the distance from the camera to the model centre should be -

float fDistance = r / 0.57735f; // where 0.57735f is tan(30 degrees)

The near and far clipping planes then lay either side of this point, allwoing for the radius of the sphere. So -

double dNear = fDistance - r;
double dFar = fDistance + r;

That (hopefully!) gives us a frustum -

glFrustum(-r, +r, +r, -r, dNear, dFar); // ignoring aspect ratio of the window for now!

All we need to do is to position the camera back along the z axis to where we want it -

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, fDistance, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

and then move the model to align its centre with the origin -

glTranslatef(-p.x, -p.y, -p.z);

Then we can draw the model using the original vertices.

NB - I haven't actually tested any of this but it paraphrases some of my own code I use in a similar situation. I can't reproduce that here as it is bound up in a load of OO stuff. Please excuse any glaring mistakes, which I'm sure will be pointed out in very short order! http://www.opengl.org/discussion_boards/ubb/redface.gif




[This message has been edited by Rog (edited 11-17-2003).]

nexusone
11-17-2003, 05:25 AM
I think Rog has given you a practical solution to your problem.

Maybe you need to study more about how openGL works so that you can understand more the concepts of 3D programming.

nehe.gamedev.net has some good tutors on openGL.

You need to look at how viewport works vs. the world view, how scale function works.

A good book on openGL would not be a bad idea also.

holyburak
11-17-2003, 11:05 PM
Last night i read the sphere in the online version of redbook and applied it. Tadaa!
That was really what i needed. It works! http://www.opengl.org/discussion_boards/ubb/biggrin.gif
Your last code made the concept well understood Rog. Believe me i'm not that much silly all the time! :P Just one has to do is sweeping all the confusing thoughts and concentrate on the concept.
i dont think a simple "Thank you" is enough. i guess the best will be sharing the program and replying others' posts (in my spare time :P )
nexusan you're right but i dont have much time to apply a 600 page book on the comp.
But i'll try to.. and maybe try to write tutorials.. who knows http://www.opengl.org/discussion_boards/ubb/smile.gif
Thanks all.

Rog
11-18-2003, 01:10 AM
That's cool http://www.opengl.org/discussion_boards/ubb/cool.gif - glad you got it sorted....