I understand from this presentation: http://www.terathon.com/gdc07_lengyel.pdf
The focal length (fx) is the first value (e) in all OpenGL projection 4x4 matrices.
How would we get the values of principal point (cx, cy) from this projection matrix? Is it possible? I also know the view matrices.
The matrix in question describes a central perspective projection. It would seem the principal point of that would have to be (0, 0)…
Related
If I have a 3x4 camera projection matrix, can I compute all or just some of the individual intrinsic and extrinsic camera parameters, i.e., focal length, principal point coordinates, rotation angles (roll, yaw and tilt), and translation vector? If yes, what are the formula?
Is there any tool in OpenCV/OpenGL/MATLAB that could help me do so?
Yes. You proceed by decomposing your projection matrix into the product of an upper triangular one and an orthogonal one. You can google search for RQ-decomposition for details. A nice summary is here.
I have a rotation matrix I use to show a 3D-vector with openGL. Now I would like to have a projection of this vector on the XY-plane. So I´m looking for the rotation matrix that I can use to do this. Any ideas on how to do this?
This will not be rotation matrix, but general 4x4 transformation matrix for doing a projection on a plane. It is often used to do a "shadow" matrix for flattening objects onto a floor.
See more here: http://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
https://math.stackexchange.com/questions/320527/projecting-a-point-on-a-plane-through-a-matrix
Projected Shadow with shadow matrix, simple test fails
According to MSDN, we are multiplying the current matrix with the perspective matrix. What matrix are we talking about here? Also from MSDN:
"The glFrustum function multiplies the current matrix by this matrix, with the result replacing the current matrix. That is, if M is the current matrix and F is the frustum perspective matrix, then glFrustum replaces M with M • F."
Now, from my current knowledge of grade 12 calculus (in which I am currently), M is a vector and M dot product F returns a scalar, so how can one replace a vector with a scalar?
I'm also not sure what "clipping" planes are and how they can be referenced via one float value.
Please phrase your answer in terms of the parameters, and also conceptually. I'd really appreciate that.
I'm trying to learn openGL via this tutorial: http://www.youtube.com/watch?v=WdGF7Bw6SUg. It is actually not really good because it explains nothing or else it assumes one knows openGL. I'd really appreciate a link to a tutorial otherwise, I really appreciate your time and responses! I'm sure I can struggle through and figure things out.
You misunderstand what it's saying. M is a matrix. M•F therefore is also a matrix. It constructs a perspective matrix. See this article for an explanation of how it is constructed and when you want to use glFrustum() vs. gluPerspective():
glFrustum() and gluPerspective() both produce perspective projection matrices that you can use to transform from eye coordinate space to clip coordinate space. The primary difference between the two is that glFrustum() is more general and allows off-axis projections, while gluPerspective() only produces symmetrical (on-axis) projections. Indeed, you can use glFrustum() to implement gluPerspective().
Clipping planes are planes that cut out sections of the world so they don't have to be rendered. The frustum describes where the planes are in space. Its sides define the view volume.
glFrustum generates a perspective projection matrix.
This matrix maps a portion of the space (the "frustum") to your screen. Many caveats apply (normalized device coordinates, perspective divide, etc), but that's the idea.
The part that puzzles you is a relic of the deprecated OpenGL API. You can safely ignore it, because usually you apply gluFrustum() on an identity projection matrix, so the multiplication mentioned in the doc has no effect.
A perhaps more comprehensible way to do things is the following :
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Or, for an ortho camera :
//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
Here, I used glm::perspective (the equivalent of old-style gluPerspective() ), but you can use gluFrustum too.
As for the arguments of the function, they are best explained by this part of the doc :
left bottom - nearVal and right top - nearVal specify the points on
the near clipping plane that are mapped to the lower left and upper
right corners of the window, assuming that the eye is located at (0,
0, 0)
If you're unfamiliar with transformation matrices, I wrote a tutorial here; the "Projection Matrix" section especially should help you.
I am working with NV Path extension which forces using of fixed pipeline transformations. Now, while for view and model matrices I just roll my own and load those via:
glMatrixPushEXT(GL_MODELVIEW);
glMatrixLoadfEXT(GL_MODELVIEW, value_ptr(viewmodel) );
I have issues with perspective matrix FOV. The fixed method for creation persp matrix is this:
glMatrixLoadIdentityEXT(GL_PROJECTION);
glMatrixFrustumEXT(GL_PROJECTION, -aspect_ratio, aspect_ratio, -1, 1, nearF, farF);
but it doesn't allow passing a custom FOV. So it probably creates some default FOV based on l ,r ,b ,t params of the method above. Can I use:
glMatrixLoadfEXT(GL_PROJECTION, myProjectionMatrix);
to load a custom projection matrix without using glMatrixFrustumEXT?
UPDATE:
As some peopled pointed out, I can load projection matrix the same way I do with model view.But I found that my custom projection never looks the same as when using glMatrixFrustumEXT(). Probably FOV calculation is different. Anybody knows how glMatrixFrustumEXT calculates the FOV?
Using glFrustum or glMatrixFrustumEXT does allow to specify the FOV, and you actually do so. As you define the points on the near plane, and the distance of the near plane, you implicitely define the fov, both vertical and horizontal.
Look at the old gluPerspective function:
gluPersepctive(fov_y, aspect, zNear, zFar)
This would generate a symmetrical frustum with the given vertical FOV of fov_y as follows:
top=tan(fov_y/2.0) * zNear; // assuming fov_y in radians here
bottom=-top;
left=bottom*aspect;
right=-left;
glFrustum(left, right, bottom, top, zNear, zFar);
In your code, you are simply specifying a vertical FOV of 2*atan(1/nearF)
I started to read lesson 1 in learningwebgl blog, and I noticed this part:
var pMatrix = mat4.create();
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
I roughly understand how matrices (translation/rotation/multiple) works, but I have no idea what mat4.perspective(...) means. What is it used for? What is the result, if I multiply a vector with this matrix?
The perspective matrix is used to scale, and possibly translate or flip the coordinate system in preparation for the perspective divide. Since the the perspective projection operation involves a divide, it cannot be represented by a linear matrix transformation alone.
In a programmable graphics pipeline (see pixel shaders) you cannot see the divide operation - it is still one of the fixed-function parts. The programmer controls it by tweaking the variables involved in the operation. In the case of the perspective divide it is the projection matrix that gives you this control.
The projection matrix is used to convert world-coordinates to screen coordinates.
The positions in your three-dimensional virtual world are triplets of x, y and z coordinates. When you want to draw something (or rather tell OpenGL to draw something) it needs to calculation where these coordinates are on the users screen.
This calculation is implemented with matrix multiplication.
A vector consisting of x, y and z (and a fourth value of 1 which is necessary to allow the matrix to do some operations like scaling) is multiplied with a matrix to receive a new set of x, y and z coordinates (4th value is discarded) which represent where this point is on the users screen (the z-coordinate is required to determine which objects are in front of others).
The function mat4.perspective generates a projection matrix which generates a matrix which does exactly that. The arguments are:
The field-of-view in degree (45)
the aspect ratio of the field of view (the aspect ratio of the viewport)
the minimal distance from the viewer which is still drawn (0.1 world units)
the maximum distance from the viewer which is still drawn (100.0 world units)
the array in which the generated matrix is stored (pMatrix)
When a point is multiplied with this matrix, the result are the screen coordinates where this point has to be drawn.