OpenGL: Mix orthographic and perspective projection - opengl

I want to mix a perspective and orthographic view, but I can't get it to work.
I want X and Y coordinates to be orthographic and Z perspective. For clarification I added a sketch of the desired transformation from OpenGL coordinates to screen display:
(I started from a tutorial, but couldn't find how to get values top, bottom, etc.)

What you've drawn is simply perspective, not a mix. You just have to make sure that the viewing direction is parallel to the z axis to make the front and back faces of the box stay rectangular.

You could probably use glFrustum to achieve this.
If you use a standard perspective matrix and the camera faces the box front on, X/Y will be uniform, however movement away from the camera will move the X/Y coordinates towards the centre, shrinking them for a standard parallax effect. What you've drawn is movement towards the top of the window. All you need to do is crop the perspective projection to below its standard centre. That's where glFrustum comes in - move the normally symmetrical top/bottom arguments down, align the camera/view matrix along the axis you want and you should have the desired projection.
Any rotation of the camera/view will destroy the uniform projection in the X/Y plane. For camera movement you're then limited to panning and moving the glFrustum bounds.
EDIT Come to think of it, you could probably just throw in a glTranslatef(shearX, shearY, 0) before the call to gluPerspective and achieve the same thing.

Related

Why does the camera face the negative end of the z-axis by default?

I am learning openGL from this scratchpixel, and here is a quote from the perspective project matrix chapter:
Cameras point along the world coordinate system negative z-axis so that when a point is converted from world space to camera space (and then later from camera space to screen space), if the point is to left of the world coordinate system y-axis, it will also map to the left of the camera coordinate system y-axis. In other words, we need the x-axis of the camera coordinate system to point to the right when the world coordinate system x-axis also points to the right; and the only way you can get that configuration, is by having camera looking down the negative z-axis.
I think it has something to do with the mirror image? but this explanation just confused me...why is the camera's coordinate by default does not coincide with the world coordinate(like every other 3D objects we created in openGL)? I mean, we will need to transform the camera coordinate anyway with a transformation matrix (whatever we want with the negative z set up, we can simulate it)...why bother?
It is totally arbitrary what to pick for z direction.
But your pick has a lot of deep impact.
One reason to stick with the GL -z way is that the culling of faces will match GL constant names like GL_FRONT. I'd advise just to roll with the tutorial.
Flipping the sign on just one axis also flips the "parity". So a front face becomes a back face. A znear depth test becomes zfar. So it is wise to pick one early on and stick with it.
By default, yes, it's "right hand" system (used in physics, for example). Your thumb is X-axis, index finger Y-axis, and when you make those go to right directions, Z-points (middle finger) to you. Why Z-axis has been selected to point inside/outside screen? Because then X- and Y-axes go on screen, like in 2D graphics.
But in reality, OpenGL has no preferred coordinate system. You can tweak it as you like. For example, if you are making maze game, you might want Y to go outside/inside screen (and Z upwards), so that you can move nicely at XY plane. You modify your view/perspective matrices, and you get it.
What is this "camera" you're talking about? In OpenGL there is no such thing as a "camera". All you've got is a two stage transformation chain:
vertex position → viewspace position (by modelview transform)
viewspace position → clipspace position (by projection transform)
To see why be default OpenGL is "looking down" -z, we have to look at what happens if both transformation steps do "nothing", i.e. full identity transform.
In that case all vertex positions passed to OpenGL are unchanged. X maps to window width, Y maps to window height. All calculations in OpenGL by default (you can change that) have been chosen adhere to the rules of a right hand coordinate system, so if +X points right and +Y points up, then Z+ must point "out of the screen" for the right hand rule to be consistent.
And that's all there is about it. No camera. Just linear transformations and the choice of using right handed coordinates.

How to draw a ray/line from the near clipping plane w/ perspective projection?

Simply put - I want to draw a ray/line from the near clipping plane out to the far clipping plane using a perspective projection. I have what I believe are correctly normalized world coordinates generated from a mouse click using methods describe in various OpenGL/graphics programming guides.
The problem I am having is that it seems my ray is being drawn from outside the near clipping plane.
Background: This is for a simple model viewer I am building in Qt that requires a picking capability. I need to draw the ray in order to calculate intersections with objects in the scene. However, my basic problem is that I can seem to draw the ray correctly.
My perspective projection is defined:
gluPerspective(_fov, aspect, 0.1, 100.0);
where _fov is 45.0 degress, and aspect is the ratio of the window width/height.
Using my picking code, I've generated what I believe to be correctly normalized world coordinates based off of mouse clicks. An example of these coordinates:
-0.385753,-0.019608,-0.100000
However, when I try to draw a ray starting at that point, it looks like it is being drawn from outside of the clipping plane:
Maybe I am expecting something different, but in the example above I clicked on the nose of the airplane, generated the world coordinates above, and I am drawing the ray incorrectly (or so I believe). I was hoping to see the line being drawn from the location of the mouse click into the airplane model.
When I draw the ray I first load the identity matrix, and then draw a line from the near clipping plane coordinates to the far plane. Then I draw a sphere at the end of the ray (in this screenshot it is behind the plane).
glPushMatrix();
glLoadIdentity();
glColor3f(0,0,1);
glBegin(GL_LINES);
glVertex3f(_near_ray.x(), _near_ray.y(), _near_ray.z());
glVertex3f(_far_ray.x(), _far_ray.y(), _far_ray.z());
glEnd();
glTranslatef(_far_ray.x(), _far_ray.y(), _far_ray.z());
glColor3f(1,0,0);
glutWireSphere(1, 10, 10);
glPopMatrix();
Any hints as to what I am doing wrong? The _far_ray coordinates are the same as the _near_ray except for the Z field. I want the ray to be drawn straight into the scene.
In The End... I'd just like to know how the draw the ray itself. I understand that there might be errors in my code that generates the coordinates, but what if I just wanted to draw an arbitrary ray from the near clipping plane straight into the scene. That is that I'd like answered.
With perspective projection, a line looks like a point on the screen if and only if it passes through the eye position.
Since you revert modelview matrix to identity, the eye is located at the origin (according to this question). Pass (0, 0, 0) as one of the vertices, and hopefully you'll see that line degenerates into a point.
Generally, the two 3d vectors used as vertices must be collinear.
If you do not revert modelview matrix, then you can draw a line from (eye) to (eye + dir), where eye is the first vector passed to gluLookAt, and dir is the any sufficiently large vector looking into proper direction.

Lessen degree of perspective in 3D grid (reduce convergence)

Please see the following image:
Which mathematical method or POV-Ray/OpenGL command will lessen the convergence of a grid like this? (The grid converges too quickly; theta should be 90 degrees, matching the center line, for this purpose.)
Perspective is still desired, but convergence should happen at a slower rate, as if the distance was shorter or you were using a telephoto lens.
Although this image is from Blender, the methods being used are OpenGL and POV-Ray so a solution in either method would be appreciated.
I have some lines modeled in OpenGL and POV-Ray.
I have tried location, look--at, angle, right and up in POV-Ray, including camera transformations like rotate, scale, translate and matrix.
In OpenGL I have tried gluPerspective, glFrustum and glDepthRange.
Does anyone have a solution to this problem?
(Also, looking down on the grid is not an option in this case)
You're after an orthographic projection...
glOrtho()
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left, right, bottom, top, near, far);
glMatrixMode(GL_MODELVIEW);
It's always nice to be able to swap between orthographic and perspective though since moving around a scene in orthographic can take a while to get used to.
There's an image here... https://blender.stackexchange.com/questions/648/what-are-the-differences-between-orthographic-and-perspective-views
edit
To keep using perspective, but with less perspective effect, you can decrease the field of view parameter. Unfortunately this will make the projection appear to zoom in. To undo the zoom, move the camera back. You can then update the near/far accordingly if need be.

OpenGL orthographic projection

In the description of gluOrtho2d they say it's like glOrtho with near=-1 and far=1.
Why is near behind the viewer.
Why does the matrix described
here: http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml have the
Z-axis inverted?
1) As the name would imply, gluOrtho2d is meant for drawing things where the depth coordinate doesn't really matter. It's set up so you can send 2-component verts to the gpu and the depth just defaults to 0. In this case it makes sense to have a projection where 0 is right in between the near/far planes so you don't have to worry about it. It's worth mentioning that in an orthographic projection the idea of being "behind" the viewer loses some of its meaning anyway because the distance from the viewer to the object has no affect on the projection other than choosing whether or not to draw it at all.
2) Probably because in OpenGL space, the NEGATIVE Z-axis is into the screen, so if glOrtho didn't negate you'd always have to pass in negative values for near and far. Which would be a little weird I guess.

How to get the projection plane in OpenGL

I use the gluPerspective and glLookAt to set my projection matrix and view matrix. If I want to get the coordinate of the eye, it's the first three arguments in the gluLookAt, right?
However, now I need to get the projection plane, that is, the position of the screen in the world coordinate system. You know, if I can calculate the left-bottom corner point and the right-top corner point, the plane is right there!
Could anyone give me a hint about how to do this calculation?
You could use gluUnProject with screen space coordinates (mapping viewport width and height to 0…1) A=(0,0,0), B=(1,0,0) and C=(1,0,0) giving the coplanar points of the projection plane. Adding a fourth point (1,1,0) you get the rectangular limits.