Why are the returned Z coordinates backwards?

Started by Evan407, August 23, 2015, 19:22:07

Previous topic - Next topic

Evan407

I wrote some code that gets the near and the far points in 3d of where a user clicks. It works by using the inverse of the mvp.
  clickLocationNear = new Matrix(4,1);
		  clickLocationNear.pushElement((float)GL_X_Position); //screen x click location, between -1 and 1
		  clickLocationNear.pushElement((float)GL_Y_Position); //screen y click location
		  clickLocationNear.pushElement(1f); //near z
		  clickLocationNear.pushElement(1f);
		  clickLocationFar = new Matrix(4,1);
		  clickLocationFar.pushElement((float)GL_X_Position);
		  clickLocationFar.pushElement((float)GL_Y_Position);
		  clickLocationFar.pushElement(-1f); //far z
		  clickLocationFar.pushElement(1f);

		  theReverseMatrix = modelMatrix.multiply(viewMatrix); //model times view
		  theReverseMatrix = theReverseMatrix.multiply(projectionMatrix); //that times projection
		  theReverseMatrix = theReverseMatrix.inverse(); //inverse of mvp

		  clickLocationNear = theReverseMatrix.multiply(clickLocationNear);
		  clickLocationFar = theReverseMatrix.multiply(clickLocationFar);

This code works pretty well but for some reason the z coordinate it's returning is the negative of what it should be. I was wondering why and is it an error I made?

I'm still using this basic shader from the tutorial
String vertexShaderSource = "#version 150 core\n"+
	  "in vec3 position;"+
	  "in vec3 color;"+
	  "out vec3 vertexColor;"+
	  "uniform mat4 model;"+
	  "uniform mat4 view;"+
	  "uniform mat4 projection;"+
	  "void main() {"+
	  	"vertexColor = color;"+
		"mat4 mvp = projection * view * model;"+
		"gl_Position = mvp * vec4(position, 1.0);"+
	  "}";

abcdef

I'm sorry but what has this got to do with either opengl or LWJGL?

On the problem in hand there is so little to go on its hard to know where to help. Which z coordinate is wrong? And were all the values used to create it?

Evan407

Quote from: abcdef on August 24, 2015, 08:31:25
I'm sorry but what has this got to do with either opengl or LWJGL?

On the problem in hand there is so little to go on its hard to know where to help. Which z coordinate is wrong? And were all the values used to create it?
The Z for the near point and far point are the negative of what they should be. The near point is the closest point to the screen where the screen was clicked and the far point is the farthest point from the screen where the screen was clicked.
Clicked on screen X: 0.228125 Y: 0.3416666666666667
modelMatrix:
0.453990 0.000000 0.891007 0.000000
0.569744 0.768842 -0.290299 0.000000
-0.685043 0.639439 0.349047 0.000000
0.000000 0.000000 0.000000 1.000000
viewMatrix:
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000
projectionMatrix:
1.000000 0.000000 0.000000 -0.000000
0.000000 1.000000 0.000000 -0.000000
0.000000 0.000000 -1.000000 -0.000000
0.000000 0.000000 0.000000 1.000000
clickLocationNear Matrix:
0.228125
0.341667
1.000000
1.000000
clickLocationFar Matrix:
0.228125
0.341667
-1.000000
1.000000
model matrix times view matrix:
0.453990 0.000000 0.891007 0.000000
0.569744 0.768842 -0.290299 0.000000
-0.685043 0.639439 0.349047 0.000000
0.000000 0.000000 0.000000 1.000000
that times projection matrix:
0.453990 0.000000 -0.891007 0.000000
0.569744 0.768842 0.290299 0.000000
-0.685043 0.639439 -0.349047 0.000000
0.000000 0.000000 0.000000 1.000000
inverse of mvp:
0.453990 0.569744 -0.685043 0.000000
0.000000 0.768842 0.639439 0.000000
-0.891007 0.290299 -0.349047 0.000000
0.000000 0.000000 0.000000 1.000000
inverse mvp times near point:
-0.386814
0.902127
-0.453122     <- should be 0.453122
1.000000
inverse mvp times far point:
0.983272
-0.376751
0.244972     <- should be -0.244972
1.000000

Kai

You are creating a projection matrix that inverts Z. And that is just a convention that most people adhere to, that in the view coordinate system the +Z axis points out of the screen to the viewer, whereas in OpenGL's Normalized Device Coordinate system, the +Z axis always points into the screen, away from the viewer.
Your projection matrix is equivalent to what one would get with
glOrtho(-1, +1, -1, +1, -1, +1).
This results in your projection matrix. And glOrtho assumes that, in the coordinate system which this functions transforms, the +Z axis points to the viewer.
The second-to-last argument, which is -1, says you want -1 to be the near plane and +1 to be the far plane.
When you then transform your clickLocationNear vector with z=+1.0 by that inverse mvp matrix, you say that you have your z-coordinate +1.0 in normalized device coordinates and want the model-space Z-coordinate. And since your projection matrix expresses that Z is inverted/negated (-1.0 becoming NDC +1.0, and +1.0 becoming NDC -1.0), your z-coordinate is negated.

Literature: http://www.songho.ca/opengl/gl_projectionmatrix.html

Evan407

Quote from: Kai on August 24, 2015, 14:25:15
I just wanted to say thanks for answering my question.

I'm still getting used to all the math that makes the magic happen. So OpenGL must do the Z where -1 is the near point and 1 is the far point. And I'm inverting/negating the Z with the projection matrix so my vertices have Z where 1 is the near and -1 is the far.

quew8

As just a little extra information, this is called left and right handed coordinate systems. So (by default) OpenGL is right handed whereas DirectX is left handed. If you take one of your hands, put your thumb, first (index) and second (middle) fingers perpendicular to each other the place it near the bottom left corner of your screen. Now your thumb is the x-axis so point that going across from left to right. Your first (index) finger is the y axis so point that up. Now which way does your second (middle) finger, the z-axis, point? If it's your right hand it points out of the screen like in OpenGL but your left will point into the screen like in DirectX.

And as @Kai adeptly explains, the reason is all down to the matrices.