Centre the scene on the screen

Hi all,

I have a scene that has a bound: maxX, maxY, minx, minY, maxZ (may be = 0), minZ (may be = 0), the size of screen is: screenWidth, screenHeight. The point (0,0) is in the centre of the screen

  • I would like to centre this scene on the screen.
  • Zoom in and zoom out this scene but the scene is always in the centre of the screen. If the size of the scene is too large, it will be clipped.

How can I do this?
Thanks all,

look at this:
FAQ 8.070 How can I automatically calculate a view that displays my entire model? (I know the bounding sphere and up vector.)

This approach should center your objects in the middle of the window and stretch them to fit

I don’t want to stretch my scene. And this code does not work for me. See this thread: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=241885#Post241885

Do you have the complate code that work?

Thanks so much,

Ah yes, I read it too fast.

If you want to see the scene at the center of the screen, just draw a the world center and set the view (with glLookAt) to look at the center.
What is the problem with glLookAt? It is really simple to use in your case:
You need 3 camera parameters:

  • camera position
  • camera view axis
  • camera vertical axis which is in most cases (0, 1, 0)

view axis in the vector between scene center (i.e (0,0,0)) and the camera position.

Then for zooming, you just need to recompute cmera position moving it along the view vector (this one should be normalized for a constant speed).

I don’t think so. IMHO it should be scaled by the camera distance so that you move slower near the model and move faster if the camera is farther away. Moving the camera at a constant speed is a very unsatisfying solution for zooming.

Now, my code that run well is :


void Viewer::initGLES(){
	glViewport( 0, 0, iScreenWidth, iScreenHeight );
	glClearColor(0.f,0.f,0.1f,1.f);
	glDisable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);

	//glFrustumf (-100.f,1000.f,-1000.f,500.f,3.f,300.f);
	glFrustumf(-1500.f, 1500.f, -1500.f, 1500.f, 3.f, 1500.f);
    //glFrustumf(Loader->minX, Loader->maxX, Loader->minY, Loader->maxY, 3.f, 2500.f);
    //glFrustumf(657, 1155, -781, -442, 1.2f, 1500.f);
    glMatrixMode(GL_MODELVIEW);
    glShadeModel(GL_SMOOTH);
}

//--------------------------------------------
void Viewer::draw(){
	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();
	float centerX = (Loader->minX + Loader->maxX)/2;
	float centerY = (Loader->minY + Loader->maxY)/2;
	float centerZ = 0;
	//glScalef(m_scale, m_scale, m_scale);
	//glTranslatef(centerX, centerY, centerZ);
glTranslatef(-1400.f, 1000.f, -3.f);
	//glTranslatef(906.0f, -611.5f, -7.f);
	//glScalef(2.0, 2.0, 2.0);
	
	//glScalef(5.0, 5.0, 5.0);
	glColor4f(0, 1, 0, 1);
		
	drawScene();
}

But as you can see, the parameters of the function glFrustumf(-1500.f, 1500.f, -1500.f, 1500.f, 3.f, 1500.f); are fixed. It is not good, because I don’t know the real data, it must be read from the data file.

And in the function glTranslatef(-1400.f, 1000.f, -3.f);, the parameters are also fixed. I would like to center my scene.

//glFrustumf(657, 1155, -781, -442, 1.2f, 1500.f); --> The real value in the data file.

How should I change thes parameters?

Thanks,

satan> Yes this a good idea in this case. But one thing I don’t like in this mode is when you look at little objects, you have to make a huge mouse scroll to move from 1 millimeter…

anime.igala.net> You have to compute this values according to the scene file.


glFrustumf(657, 1155, -781, -442, 1.2f, 1500.f);

if these values are the limits of the scene bounding box, you can find the scene center very easily:

xcenter = (right+left)/2
ycenter = (top+bottom)/2
zcenter = (far+near)/2

then you translate all scene vertices from the vector (-xcenter, -ycenter, -zcenter) and your scene is centered.

yeah, I think that the problem now is in two functions: glFrustumf and glTranslatef.

If I use this, it works (these values are groped/fumbled):

void Viewer::initGLES(){
	glViewport( 0, 0, iScreenWidth, iScreenHeight );
	glClearColor(0.f,0.f,0.1f,1.f);
	glDisable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);

glFrustumf(-1500.f, 1500.f, -1500.f, 1500.f, 3.f, 1500.f);

    glMatrixMode(GL_MODELVIEW);
    glShadeModel(GL_SMOOTH);
}

//-----------------------------------
void Viewer::draw(){
	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();
glTranslatef(-1400.f, 1000.f, -3.f);
	glColor4f(0, 1, 0, 1);
		
	drawScene();
}

But it does not work with this one, I don’t know why:

void Viewer::initGLES(){
	glViewport( 0, 0, iScreenWidth, iScreenHeight );
	glClearColor(0.f,0.f,0.1f,1.f);
	glDisable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);

    glFrustumf(Loader->minX, Loader->maxX, Loader->minY, Loader->maxY, 3.f, 1500.f);
    //glFrustumf(657, 1155, -781, -442, 1.2f, 1500.f);
    glMatrixMode(GL_MODELVIEW);
    glShadeModel(GL_SMOOTH);
}
//------------------------
void Viewer::draw(){
	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();
	float far = 1500;
	float near = 1;
	float centerX = (Loader->minX + Loader->maxX)/2;
	float centerY = (Loader->minY + Loader->maxY)/2;
	float centerZ = (far-near)/2;
	glTranslatef(centerX, centerY, centerZ);
	
	glColor4f(0, 1, 0, 1);
		
	drawScene();
}

float centerX = (Loader->minX + Loader->maxX)/2;
float centerY = (Loader->minY + Loader->maxY)/2;
float centerZ = (far-near)/2;
glTranslatef(centerX, centerY, centerZ);

What the hell is that? :smiley:

I did not write this but:

xcenter = (right+left)/2
ycenter = (top+bottom)/2
zcenter = (far+near)/2

and then

translate all scene vertices from the vector (-xcenter, -ycenter, -zcenter)

AND

Since you have moved your scene center, this won’t work:


glFrustumf(Loader->minX, Loader->maxX, Loader->minY, Loader->maxY, 3.f, 1500.f);

because as you translate all the scene from the vector (-xcenter, -ycenter, -zcenter), your scene boundaries move too. :slight_smile:

you also have to translate each min/max value.

So what’s the code should be now? :stuck_out_tongue:

Please help me! :slight_smile:

Are you kidding? Je t’ai maché le travail la! :slight_smile:

It is very simple, you should draw your scene and the view frustrum on a paper and you will easily see the solution…

Because I am nice, this time I will help you, but please understand that people on a forum are not here to write your entire code.

So, for glFrustrum you should do this:


glFrustumf(Loader->minX-centerX, Loader->maxX-centerX, Loader->minY-centerY, Loader->maxY-centerY, 3.f-centerZ, 1500.f-centerZ);