world space - view space transformation?

Started by
8 comments, last by smacdo 16 years, 3 months ago
Hey guys, I'm really getting myself confused in opengl's coordinate transformation systems. I understand that the default view is 0,0,0 and all transformations alter it. What I'm really confused about is how the camera factors into the transformation. Normally, with a scene graph or something I could do: camera->setPos( -10, 5, 0 ); and then all my objects would render correctly with respect to the camera. Imagine my surprise when I discovered OpenGL doesn't have a camera system! Mathmatically, it makes sense.... but I'm getting confused as to what I have to do to get objects to work properly. After a lot of googling (either I'm not looking for the right thing, or its assumed everyone knows), it appears what you do is: 1) Apply camera transformation 2) Apply model transformation but that doesn't seem to work! You'd move your coordinate system to the camera's position, and then apply your model's world transforms relative to the camera! I 'm trying to figure out how to transform an object into the camera's viewspace. You'd think that this would be better covered (unless I'm missing the point) Anyhow, after a lot of thinking I got a basic idea of how you could do it in 2d space. I would transform the object into its worldspace coordinates, and then take the difference of the camera's vector from the object's worldspace vector. This new vector, relative from the camera's origin, would correctly position the object. Does any of this make sense? I'm really confused.... here's what I picture in my head: the camera '^' is at: <4,0> the object '0' is at: <2,2> | | 0 | -----+----^-- | | i find the correct position to draw the object, relative to the camera's coordinate system, not the world coordinates that I already know. I need a way to find this offset.
Advertisement
What openGL does is concatenate its Model and View(Camera) matricies into a single GL_MODELVIEW matrix.

Way to go about it is as follows:
from identity (use glLoadIdentity to be sure)
perform view transformation
perform model transformation

The view transform is not the same as the transform of a camera entity though, as what you want is to transform world vertices (model matrix makes them world vertices) into View (or camera) space.

This means you actually need the *inverse* of the camera entities matrix.

For simplicity, in the GLU library there is a function called gluLookAt. This performs the view transformation step for you ;)

Hope this helps.
Thanks, I think I'm just not able to visualize whats going on. In fact, this code works fine...

glTranslatef( 0.0f, 0.0f, -1.0f );
glBegin( GL_TRIANGLES );
glColor3f( 0.0, 1.0, 0.0 );
glVertex3f( 0.0f, 1.0f, 0.0f ); // top

glColor3f( 1.0, 0.0, 0.0 );
glVertex3f( 0.0f, -1.0f, 0.0f ); // bottom left

glColor3f( 0.0, 0.0, 1.0 );
glVertex3f( 1.0f, -1.0f, 0.0f );
glEnd();


but anything translated beyond -1.0f, or 1.0f makes the entire scene disappear! I'm scratching my head over this. Originally I thought it was because opengl's near/far was set incorrectly, but I have this...

screen = SDL_SetVideoMode(
CLIENT_WINDOW_WIDTH,
CLIENT_WINDOW_HEIGHT,
info->vfmt->BitsPerPixel,
SDL_OPENGL | SDL_RESIZABLE
);

glViewport( 0, 0, CLIENT_WINDOW_WIDTH, CLIENT_WINDOW_HEIGHT );
gluPerspective( 60.0f, (GLfloat)CLIENT_WINDOW_WIDTH/(GLfloat)CLIENT_WINDOW_HEIGHT, 1.0f, 1000.0f );

(same for window resizing)


... so it should still show up, even at z = -2.0f, right? But its disappearing as soon as it passes -1.0f (or even 1.0f)

Help please?

This is really getting frustrating
Quote:Thanks, I think I'm just not able to visualize whats going on


To help you get your head around it, consider that from OpenGL's perspective the camera is always located at <0,0,0>. If you want to place the camera somewhere else, you have to translate the whole world in the opposite direction.

Quote:... so it should still show up, even at z = -2.0f, right? But its disappearing as soon as it passes -1.0f (or even 1.0f)

Well, it should show up as long as it is more than 1.0 in front of the "camera", and less than 1000.0. The actual z coordinate means very little....it's relative to the view.

If you translate by more than -1 in the z direction, it doesn't show up? I would think that translating -1 would be questionable (since it puts it right at the clip distance), but -2 or more should show up.
Quote:Original post by smitty1276
Quote:Thanks, I think I'm just not able to visualize whats going on


To help you get your head around it, consider that from OpenGL's perspective the camera is always located at <0,0,0>. If you want to place the camera somewhere else, you have to translate the whole world in the opposite direction.

Quote:... so it should still show up, even at z = -2.0f, right? But its disappearing as soon as it passes -1.0f (or even 1.0f)

Well, it should show up as long as it is more than 1.0 in front of the "camera", and less than 1000.0. The actual z coordinate means very little....it's relative to the view.

If you translate by more than -1 in the z direction, it doesn't show up? I would think that translating -1 would be questionable (since it puts it right at the clip distance), but -2 or more should show up.


So here's some preliminary testing....

glTranslatef( x, y, z )
0,0,1.1 -> nothing on the screen
0,0,1 -> triangle takes up half the screen (expected)
0,0,0.5 -> visible
0,0,0.0 -> visible
0,0,-0.5 -> visible
0,0,-1.0 -> visible
0,0,-1.1 -> nothing on the screen


Did I set something up wrong somehow? Because common sense would say that from [-1,1] there should be nothing on the screen and from [-1000,1] should be visible. (The camera is at (0,0,0) and looks down the negative z axis IIRC)



Here's the rendering code:

ErrorCode FirstScene::doGameFrame( 				unsigned int deltatime,				ForgeClient* client, 				ForgeEngine* engine ){	// Clear the depth buffers	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );		// Reset the view	glMatrixMode( GL_MODELVIEW );	glLoadIdentity();	//	// Apply the camera transformation	//	glTranslatef( 0.0f, 0.0f, -1.1f );	//	// Draw a vector axis thingy	//	glBegin( GL_LINES );		glColor3f( 1.0f, 0.0f, 0.0f );		// Red X axis		glVertex3f( 0.0f, 0.0f, 0.0f );			glVertex3f( 1.0f, 0.0f, 0.0f );		glColor3f( 0.0f, 1.0f, 0.0f );		// Green Y axis		glVertex3f( 0.0f, 0.0f, 0.0f );		glVertex3f( 0.0f, 1.0f, 0.0f );		glColor3f( 0.0f, 0.0f, 1.0f );		// Blue Z axis		glVertex3f( 0.0f, 0.0f, 0.0f );					glVertex3f( 0.0f, 0.0f, 1.0f );	glEnd();	// draw a triangle (yay!)	glBegin( GL_TRIANGLES );		glColor3f( 0.0, 1.0, 0.0 );		glVertex3f( 0.0f, 1.0f, 0.0f );			// top		glColor3f( 1.0, 0.0, 0.0 );		glVertex3f( 0.0f, -1.0f, 0.0f );		// bottom left		glColor3f( 0.0, 0.0, 1.0 );		glVertex3f( 1.0f, -1.0f, 0.0f );	glEnd();	return RESULT_OK;}



[EDIT]
Just to make things even weirder, changing gluPerspective doesn't seem to change the results at all. Setting the near view to 0.1 and the far view to 0.5, setting it 5.0 and 10.0, or even deleting it doesn't do ANYTHING to the results. Which leads me to believe it isn't being called.... except it is (I set a breakpoint on that line, and it definately is being called)


I'm about to scream. What is going on? I've never had this many problems before.... >.<

[Edited by - smacdo on January 21, 2008 12:33:34 PM]
Quote:Did I set something up wrong somehow? Because common sense would say that from [-1,1] there should be nothing on the screen and from [-1000,1] should be visible.
Well, from [-1000, -1] should be visible (not +1).

Can you post more code? Where is the viewport and projection setup? Also, use source tags (put it inside of [ source ] and [ /source ], but with no spaces).
Okay, snippets....

ErrorCode ForgeClient::init() {	//	// Register SDL_Quit to be called at exit, just in case we don't exit	// properly (like crash)	//	atexit( SDL_Quit );	//	// Init SDL's subsystems	//	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )	{		printf("Unable to init SDL: %s\n", SDL_GetError());		return ERROR_SDL_INIT_VIDEO;	}		if (SDLNet_Init() < 0)	{		printf("Could not initialize SDL_net:%s\n", SDLNet_GetError());		return ERROR_SDL_INIT_NET;	}	//	// Query the video subsystem's capabilities	//	const SDL_VideoInfo *info = SDL_GetVideoInfo();	if( info == 0 )	{		FATAL_ERROR("Could not query for video information");	}	//	// Create the main rendering window	//	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );	screen = SDL_SetVideoMode(					CLIENT_WINDOW_WIDTH, 					CLIENT_WINDOW_HEIGHT, 					info->vfmt->BitsPerPixel,					SDL_OPENGL | SDL_RESIZABLE	);	glViewport( 0, 0, CLIENT_WINDOW_WIDTH, CLIENT_WINDOW_HEIGHT );	gluPerspective( 60.0f, (GLfloat)CLIENT_WINDOW_WIDTH/(GLfloat)CLIENT_WINDOW_HEIGHT, 0.1f, 1000.0f );}



ErrorCode FirstScene::init( ForgeClient* client, ForgeEngine* engine ){	glShadeModel(GL_SMOOTH);	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	glClearDepth(1.0f);	glEnable(GL_DEPTH_TEST);	glDepthFunc(GL_LEQUAL);		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	glCullFace( GL_BACK );        glFrontFace( GL_CCW );        glEnable( GL_CULL_FACE );	//	// Make sure we're rendering in projection mode	//    glMatrixMode( GL_PROJECTION );    glLoadIdentity( );	return RESULT_OK;}ErrorCode FirstScene::doGameFrame( 				unsigned int deltatime,				ForgeClient* client, 				ForgeEngine* engine ){	// Clear the depth buffers	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );		// Reset the view	glMatrixMode( GL_MODELVIEW );	glLoadIdentity();	//	// Apply the camera transformation	//	glTranslatef( 0.0f, 0.0f, 1.0f );//	camera.apply();//	gluLookAt( 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, -100.0f, 0.0f, 1.0f, 0.0f );	//	// Draw a vector axis thingy	//	glBegin( GL_LINES );		glColor3f( 10.0f, 0.0f, 0.0f );		// Red X axis		glVertex3f( 0.0f, 0.0f, 0.0f );			glVertex3f( 1.0f, 0.0f, 0.0f );		glColor3f( 0.0f, 1.0f, 0.0f );		// Green Y axis		glVertex3f( 0.0f, 0.0f, 0.0f );		glVertex3f( 0.0f, 10.0f, 0.0f );		glColor3f( 0.0f, 0.0f, 1.0f );		// Blue Z axis		glVertex3f( 0.0f, 0.0f, 0.0f );					glVertex3f( 0.0f, 0.0f, 10.0f );	glEnd();//	RenderableRobot thing;//	thing.render();	// draw a triangle (yay!)	glBegin( GL_TRIANGLES );		glColor3f( 0.0, 1.0, 0.0 );		glVertex3f( 0.0f, 1.0f, 0.0f );			// top		glColor3f( 1.0, 0.0, 0.0 );		glVertex3f( 0.0f, -1.0f, 0.0f );		// bottom left		glColor3f( 0.0, 0.0, 1.0 );		glVertex3f( 1.0f, -1.0f, 0.0f );	glEnd();	return RESULT_OK;}



Thanks again guys. I know its hard trying to figure out other people's code... but this is just a nightmare.


For the record, I'm using Visual Studio 2008 Pro and SDL's OpenGL API.
First of all, I would move the projection stuff into init. You also need to set the matrix mode to projection before calling gluPerspective...
glViewport( 0, 0, CLIENT_WINDOW_WIDTH, CLIENT_WINDOW_HEIGHT );glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0f, (GLfloat)CLIENT_WINDOW_WIDTH/(GLfloat)CLIENT_WINDOW_HEIGHT, 0.1f, 1000.0f);


The way you have it now (if I'm not mistaken) gluPerspective is applying the projection matrix it generates to whatever matrix is active (internally using glMultMatrix, I think). I have no idea whether or not projection is the default or even if there is a default... it's probably undefined behavior. You need to set the active matrix to projection and load identity first. The above code does that.

There is no reason to set the matrix mode to projection at the end of init. In fact, you probably should set it to modelview at the end of init just for good measure.

ALSO: You are translating +1 unit on the Z axis. That will put it behind the camera. You need to be translating at LEAST .1 unit toward -Z.

glTranslatef(0.0f, 0.0f, -5.0f);
Did that help?
Quote:Original post by smitty1276
Did that help?


Not only does that make a LOT of sense, but it worked.

Thank you a ton!

This topic is closed to new replies.

Advertisement