OpenGL GLM camera matrix problem

Discuss programming topics that involve the OpenGL API.
Post Reply
Feared
Posts: 95
Joined: Fri Jun 11, 2010 11:58 pm
Location: Wylie, TX

OpenGL GLM camera matrix problem

Post by Feared »

Hello everyone,

I am having a tad issue with updating the Quake renderer code to OpenGL 3.x+. The problem is the camera. I cannot use gluPerspective anymore so I'm using the GLM library. It works sort of, here is my code.

Code: Select all

	projectionMatrix	= glm::perspective(r_refdef.fov_y, (float)vid.width / (float)vid.height, 0.01f, 8192.0f);
	viewTransMatrix		= glm::translate(glm::mat4(1.0f), glm::vec3(-r_origin[2], -r_origin[1], -r_origin[0]));
	viewRotMatrix		= glm::rotate(viewTransMatrix, -r_refdef.viewangles[0], glm::vec3(1.0f, 0.0f, 0.0f));
	viewMatrix			= glm::rotate(viewRotMatrix, -r_refdef.viewangles[1], glm::vec3(0.0f, 1.0f, 0.0f));
	modelMatrix			= glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
Also here is an image showing the problem.
http://i.imgur.com/8CskY.jpg
(the sky is to the left, and when I jump the camera moves to the right, at all times no matter the rotation)

The scene feels rotated by 90 degree's and the rotations feel like it's rotating around the player in a big arch.
I'd greatly appreciate any help, I've been stuck on this for a while. I feel like I'm missing something obvious.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: OpenGL GLM camera matrix problem

Post by Baker »

Feared wrote:Hello everyone,

I am having a tad issue with updating the Quake renderer code to OpenGL 3.x+. The problem is the camera. I cannot use gluPerspective anymore so I'm using the GLM library. It works sort of, here is my code.

Code: Select all

	projectionMatrix	= glm::perspective(r_refdef.fov_y, (float)vid.width / (float)vid.height, 0.01f, 8192.0f);
	viewTransMatrix		= glm::translate(glm::mat4(1.0f), glm::vec3(-r_origin[2], -r_origin[1], -r_origin[0]));
	viewRotMatrix		= glm::rotate(viewTransMatrix, -r_refdef.viewangles[0], glm::vec3(1.0f, 0.0f, 0.0f));
	viewMatrix			= glm::rotate(viewRotMatrix, -r_refdef.viewangles[1], glm::vec3(0.0f, 1.0f, 0.0f));
	modelMatrix			= glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
Also here is an image showing the problem.
http://i.imgur.com/8CskY.jpg
(the sky is to the left, and when I jump the camera moves to the right, at all times no matter the rotation)

The scene feels rotated by 90 degree's and the rotations feel like it's rotating around the player in a big arch.
I'd greatly appreciate any help, I've been stuck on this for a while. I feel like I'm missing something obvious.
Infos .... this may or may not be useful.

1) Quake uses Z for up and down, but OpenGL uses Z for depth. As a result, in R_SetupGL does a couple of rotations to effectively make Z go up and down and use Y for depth.

Code: Select all

	glMatrixMode (GL_MODELVIEW);
	glLoadIdentity ();

	glRotatef (-90, 1, 0, 0);	    // put Z going up
	glRotatef (90, 0, 0, 1);	    // put Z going up
2) "I cannot use gluPerspective" ... I'm not exactly sure what you mean there. You don't actually have to use that glu function. A "substitute" was included in the Q1 source ...

I'm not sure what you mean there though, it looks like the glm:Perspective is going to do the same thing.

Code: Select all

void MYgluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
	GLdouble	xmin, xmax, ymin, ymax;

	ymax = zNear * tan(fovy * M_PI / 360.0);
	ymin = -ymax;

	xmin = ymin * aspect;
	xmax = ymax * aspect;

	glFrustum (xmin, xmax, ymin, ymax, zNear, zFar);
}
I don't know if any of the above information is useful to you. It does look from that screenshot you have the camera oriented the wrong way.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Feared
Posts: 95
Joined: Fri Jun 11, 2010 11:58 pm
Location: Wylie, TX

Re: OpenGL GLM camera matrix problem

Post by Feared »

Baker wrote: 1) Quake uses Z for up and down, but OpenGL uses Z for depth. As a result, in R_SetupGL does a couple of rotations to effectively make Z go up and down and use Y for depth.

2) "I cannot use gluPerspective" ... I'm not exactly sure what you mean there. You don't actually have to use that glu function. A "substitute" was included in the Q1 source ...[/code]

I don't know if any of the above information is useful to you. It does look from that screenshot you have the camera oriented the wrong way.
Your first bit of information was helpful.
The reason I am not using MYgluPerspective is because "glFrustum" is depreciated in OGL 3.x as well as "glRotate, glTranslate, etc".
I will try to do a similar rotation with GLM with Z. Thank you.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

1: start with a view matrix all 0 except for [2]=-1, [4]=-1, [9]=1, [15]=1 instead of the regular identity matrix. that should correct your view matrix for quake's coord system

2: the problem is unlikely to be your perspective matrix. any weird/missing polys are more likely due to the y rotation of the view not being handled by the frustum code, resulting in culling - the culling is likely as correct as it was for regular glquake, fix the view matrix instead/first.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

The "Z going up" thing is in the modelview matrix so it's not relevant if we're talking projection.

Using a znear of 0.01f is a baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad idea. znear should be as high as you can tolerate going, otherwise you'll get really bad precision falloff in your depth calculations (as the final projected depth is non-linear). Adjusting depth to linear in your vertex shader might look tempting (costs a few instructions but nothing earth-shattering so far as Quake is concerned) but then you lose precision for nearby objects, which looks equally bad, if not worse.

So, I'm not 100% familiar with glm but some other things I can see going wrong here.

You're not actually adjusting for r_refdef.viewangles[2] anywhere here. OK, it's 0 or near 0 most of the time, but you need it for completeness.

Does glm::mat4(1.0f) do what you think it's doing?

Your translation has origin[0] and origin[2] swapped.

Anyway, concepts are the same and what's learned/used in one API can transfer to another so here we go.

Generally rather than load each of translate/rotate as separate matrixes, I would multiply them on top of each other. So you'd have:

Code: Select all

projectionMatrix   = glm::perspective(r_refdef.fov_y, (float)vid.width / (float)vid.height, 4.0f, 8192.0f); // note znear and fixme - does glm require that we make this identity first?

worldMatrix = glm::mat4(1.0f); // let's assume this sets to identity instead of loading 1 onto each component...
viewMatrix = glm::mat4(1.0f); // let's assume this sets to identity instead of loading 1 onto each component...

worldMatrix = glm::rotate(worldMatrix, -90, glm::vec3(1.0f, 0.0f, 0.0f)); // put Z going up
worldMatrix = glm::rotate(worldMatrix, 90, glm::vec3(0.0f, 0.0f, 1.0f)); // put Z going up

viewMatrix = glm::rotate(viewMatrix, -r_refdef.viewangles[2], glm::vec3(1.0f, 0.0f, 0.0f));
viewMatrix = glm::rotate(viewMatrix, -r_refdef.viewangles[0], glm::vec3(0.0f, 1.0f, 0.0f));
viewMatrix = glm::rotate(viewMatrix, -r_refdef.viewangles[1], glm::vec3(0.0f, 0.0f, 0.1f));

viewMatrix = glm::translate(viewMatrix, glm::vec3(-r_origin[0], -r_origin[1], -r_origin[2]));
Then just multiply the 3 for your final MVP which you'll send to your shader. That should work.

Note that I've put the player position into view but the Z going up into world; I just find this approach seems a little clearer as view is then exclusively used for player positioning; all other transforms (including entity transforms) can either go on world or can use their own matrixes. It also enables you to use the view matrix based solely on player position for fog calculations, which is neat.

You don't have to do it that way, in fact it generally doesn't matter which way (load them all onto projection if you wish, even) so long as you get the order correct and are consistent throughout your code.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Feared
Posts: 95
Joined: Fri Jun 11, 2010 11:58 pm
Location: Wylie, TX

Post by Feared »

mh wrote:Using a znear of 0.01f is a baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad idea. znear should be as high as you can tolerate going, otherwise you'll get really bad precision falloff in your depth calculations (as the final projected depth is non-linear). Adjusting depth to linear in your vertex shader might look tempting (costs a few instructions but nothing earth-shattering so far as Quake is concerned) but then you lose precision for nearby objects, which looks equally bad, if not worse.
This is interesting, I'll look into adjusting it in the vertex shader.
mh wrote:Does glm::mat4(1.0f) do what you think it's doing?
No, but you've cleared that up. :)
Many thanks, MH for all the information. Also, thank you everyone else who posted. I learned a good amount from this thread.

Almost forgot: (I still have a few things to work on, as you can tell)
Image
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

I think this is a really neat project you are doing. I wish you luck.

I like this kind of experimentation :D
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

There's an article here: http://www.mvps.org/directx/articles/li ... inearz.htm about linear depth adjustment for D3D - and therefore HLSL - but it should be easy to port. I honestly wouldn't bother though; huge chunks of the view model and world geometry will drop out or invert their depth. If you want to try it as a learning experience by all means go ahead (I did), but don't set your heart on it.

I think this is an awesome project, and mirrors a lot of what I've been doing recently in DirectQ. One tip - get the basics of the Quake renderer done first before even trying to implement any fancy stuff.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Post Reply