I use a 45.0 fov degree for my perspective projection so the distance of camera to the near plane equals the height of the near plane but It seems that the near plane height is bigger than I expected and it is a contradiction to the geometry. My objects on the near plane overflow from window. I use shaders to apply matrixes and did not use any glViewport. should I use glViewport?
Related
I am implementing a ray tracer and it currently has an orthographic projection. I want to make it into a perspective projection. I know in orthographic you send out a ray from every pixel and check for intersections. In perspective projection, the starting position of the ray is constant rather than starting from every pixel.
So I assume that in perspective projection the ray's starting position should be the camera's position. The problem is that I don't think I ever explicitly placed a camera, so I do not know what to change my ray's starting position to.
How can I determine where my camera is placed? I tried (0,0,0), but that just leaves me with a blank image so I don't think it is right.
In orthographic projection, the rays through each pixel would have the same direction, as if the rays originated from a camera behind the screen placed at infinite distance.
For perspective projection, the camera has to be placed at a finite distance behind the screen. Each ray should originate from the camera and go through each pixel of the screen. The distance between the screen and camera depends on the viewing angle.
You can triangulate the distance from the camera to your object by first picking an angle for the perspective projection. A simple example: picking an angle of 60° for the vertical Field of View (FOV) and assuming your object's center is at (0,0,0) and you want to place the camera to look down the Z axis towards the center of your object. This forms a triangle, where you can triangulate the distance with trigonometric formula: distance = (objectHeight/2) / tan(60/2). So you place the camera at (0,0,distance). You can use the same concept for your actual object location.
What is the maximum field of view that can be accomplished via a projection matrix with no distortion? There is a hard limit of < 180 degrees before the math completely breaks down, but experimenting with 170-180 degrees leads me to believe that distortion and deviation from reality begins prior to the hard limit. Where does the point at which the projection matrix begins to distort the view lie?
EDIT: Maybe some clarification is in order. As I increased the FOV angle toward 180 with a fixed render size, I observed objects getting smaller much faster than they should in reality. With a fixed render size and the scene/camera being identical, the diameter of objects should be inversely proportionate to the field of view size, if I'm not mistaken. Yet I observed them shrinking exponentially, down to 0 size at 180 degrees. This is undoubtedly due to the fact that X and Y scaling in a projection matrix are proportionate to cot(FOV / 2). What I'm wondering is when exactly this distortion effect begins.
Short answer: There is no deviation from reality and there is always distortion.
Long answer: Common perspective projection matrices project a 3D scene onto a 2D plane with respect to a camera position. If you consider a fixed distance of the plane from the camera, then the field of view defines the plane's size. Larger angles define larger planes. If you fix the size, then the field of view defines the distance. Larger angles define a smaller distance.
Viewed from the camera, the image does not change whether it sees the original scene or the plane with the projected scene (i.e. there is no deviation from reality).
Problems occur when you look at the plane from a different view point. E.g. when the projected plane is displayed on the screen (fixed size), there is only one position of the camera (your eye) from which the image is realistic. For very large field of view angles, you'll need to be very close to the screen to find that position. All other positions will not result in the correct image. For small field of view angles, the resulting distortion is very small and users will mostly consider it a realistic projection. That's because for small angles, the projected image does not change significantly if you change the distance slightly (changing the distance from 1 meter to 1.1 meters (10%) with a small fov is less problematic than changing the distance from 0.1 meters to 0.2 meters (100%) with a large fov). The most extreme case is an orthographic projection with virtually zero fov. Then, the projection does not depend on the distance at all.
And there is always distortion if objects are not at the projection axis (i.e. for any fov greater than zero). This results in spheres not projecting to perfect circles. This effect also happens with small fovs but there it is less obvious.
So let's say I have 2 objects. One with the sprite of a circle, other with the sprite of triangle.
My triangle object is set to the position of mouse in every step of the game, while circle is either standing in place or just moving in its own way, whatever.
What I want to do is to have the TRIANGLE move around the circle, but not on it's own, rather on the way your cursor is positioned.
So basically, calculate degree between circle's center and triangle's center. Whenever they are far from each other I just set triangle position to mouse position, BUT when you hover your mouse too close (past some X distance) you can't get any closer (the TRIANGLE is then positioned at maximum that X distance in the direction from circle center to mouse point)
I'll add a picture and hopefully you can get what I mean.
https://dl.dropboxusercontent.com/u/23334107/help2.png
Steps:
1. Calculate the distance between the cursor and the center of the circle. If it is more than the 'limit' then set the triangle's position to the cursor's position and skip to step 4.
2. Obtain the angle formed between the center of the circle and the cursor.
3. Calculate the new Cartesian coordinates (x, y) of the triangle based of off the polar coordinates we have now (angle and radius). The radius will be set to the limit of the circle before we calculate x and y, because we want the triangle to be prevented from entering this limit.
4. Rotate the image of the triangle to 1.5708-angle where angle was found in step 2. (1.5708, or pi/2, in radians is equivalent to 90°)
Details:
1. The distance between two points (x1, y1) and (x2, y2) is sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
2. The angle (in radians) can be calculated with
double angle = Math.atan2(circleY-cursorY, cursorX-circleX);
The seemingly mistaken difference in order of circleY-cursorY and cursorX-circleX is an artefact of the coordinate system in most programming languages. (The y coordinate increases downwards instead of upwards, as it does in mathematics, while the x coordinate increases in concord with math - to the right.)
3. To convert polar coordinates to Cartesian coordinates use these conversions:
triangle.setX( cos(angle)*limit );
triangle.setY( sin(angle)*limit );
where limit is the distance you want the triangle to remain from the circle.
4. In order to get your triangle to 'face' the circle (as you illustrated), you have to rotate it using the libgdx Sprite function setRotation. It will rotate around the point set with setOrigin.
Now, you have to rotate by 1.5708-angle – this is because of further differences between angles in mathematics and angles in programming! The atan2 function returns the angle as measured mathematically, with 0° at three o'clock and increasing counterclockwise. The setRotation function (as far as I can tell) has 0° at twelve o'clock and increases clockwise. Also, we have to convert from radians to degrees. In short, this should work, but I haven't tested it:
triangle.setRotation(Math.toDegrees(1.4708-angle));
Hope this helps!
I have a perspective projection. I want to have an object follow the mouse. It works fine when I set the object to be almost on a near clipping plane. But as the object goes beyond the near clipping plane, its movement is more and more distorted in a comparison to the mouse position. I know I need to change X and Y coordinates to reflect modified Z, but I don't know exact equation.
The viewport limits map to the near plane, so close to the near plane the scaling factor is ~1. So all you have to do is to scale by the distance of the object in view coordinates in relation to the distance of the near clipping plane:
scale = Z_object / Z_near
I have a flat plane of 2D graphics with a camera pointing at them. I want to get the effect so when a user pinches and zooms, it looks like they anchored their fingers on the plane and can pinch zoom realistically. To do this, I need to calculate the the distance between their fingers into distance in 3D space (which I already can do), but then I need to map that 3D distance to a z value.
For example, if a 100 units wide square and shrunk to 50 units (50%), how much further back would the camera need to move to make that 100 unit square shrink by half?
So to put it simply, If I have the distance in 3D space, how do I calculate the distance of the camera needed to shrink that 3D space by a certain amount?
EDIT:
So, I tried it myself and came up with this formula:
So let's say you are 1 unit away from the object.
When you want to shrink it to 50% (zoomfactor) the new distance equals 2 units => 1 / 0.5 = 2. The camera must be twice as far away.
Moving the camera closer to the plane for zooming only works with a perspective projection. The absolute distance depends on the angle of view. Usually you zoom by reducing the angle of view and not moving the camera at all.
If you are using an orthographic projection you can simply adjust the field of view / scale the projection matrix.