Could you explain to me what is the purpose of -1 in the last row of the gl_projection matrix? And how it affects the perspective division step ?
The essential property of a perspective projection is that you divide the x/y coordinates by the depth (distance from viewer). This makes objects closer to the viewer (which have smaller depth values) larger, and objects farther from the viewer (which have larger depth values) smaller.
The next piece of the puzzle is how homogenous coordinates work. The (x, y, z, w) coordinates in homogenous space produced by the vertex shader are converted to regular 3D coordinates by dividing them by w:
(x, y, z, w) --> (x/w, y/w, z/w, 1)
So we want a division by the depth to achieve a perspective, and we know that the coordinates produced by the vertex shader will be divided by w. To get the desired result, we can simply put the depth value in eye coordinate space into the w coordinate.
This is exactly what the last row of the projection matrix does. The dot product of the last row with the input vector (which are the eye space coordinates of the vertex) produces the w value of the output:
(0 0 -1 0) * (x y z 1) = -z
You might have expected the value of the matrix element to be 1, to simply copy the z value in eye space to the w value of the vertex shader output. The reason we use -1 to invert the sign is based on the common arrangement of eye space coordinates in OpenGL.
Eye coordinates in OpenGL typically have the "camera" at the origin, looking down the negative z-axis. So the visible range of z-coordinates has negative values. Since we want the distance from the viewer in the resulting w-coordinate, we flip the sign of the eye space z-coordinate, which turns the negative z-values into positive distance values from the origin.
Note that much of this is just common policy, partly rooted in the legacy fixed function pipeline. With the programmable pipeline used in current OpenGL versions, you have complete freedom in how you organize your coordinate spaces and transformations. For example, you could easily use an eye space coordinate system where the camera points in the positive z-direction, and then have a 1 in the last row of the projection matrix instead of a -1.
As stated here: http://www.songho.ca/opengl/gl_projectionmatrix.html
"Therefore, we can set the w-component of the clip coordinates as -ze. And, the 4th of GL_PROJECTION matrix becomes (0, 0, -1, 0)."
Related
I have some area X by Y pixels and I need to fill it up pixel by pixel. The problem is that at any given moment the drawn shape should be as round as possible.
I think that this algorithm is subset of Ordered Dithering, when converting grayscale images to one-bit, but I could not find any references nor could I figure it out myself.
I am aware of Bresenham's Circle, but it is used to draw circle of certain radius not area.
I created animation of all filling percents for 10 by 10 pixel grid. As full area is 10x10=100px, then each frame is exactly 1% inc.
A filled disk has the equation
(X - Xc)² + (Y - Yc)² ≤ C.
When you increase C, the number of points that satisfies the equation increases, but because of symmetry it increases in bursts.
To obtain the desired filling effect, you can compute (X - Xc)² + (Y - Yc)² for every pixel, sort on this value, and let the pixels appear one by one (or in a single go if you know the desired number of pixels).
You can break ties in different ways:
keep the original order as when you computed the pixels, by using a stable sort;
shuffle the runs of equal values;
slightly alter the center coordinates so that there are no ties.
Filling with the de-centering trick.
Values:
Order:
Given a 3D object, how do I convert it into an approximated shape in which all the sides of the object are parallel to either of the co-ordinate planes, and all the vertices have integer co-ordinates?
For example, a sphere with center at origin and a radius of 1.5 will be approximated to a cube with center at origin and side length of 2.
For another example, the line given by x = y = 0.5 will have an approximated shape as a rectangular parallelepiped with infinite length, and width and breadth as 1, and positioned such that one of its edge is along z-axis, while all the faces are along or parallel to either of x-z or y-z co-ordinate planes.
I am working with finite objects only, the above example is only meant to explain my needs.
I want an algorithm which can do this for me for any shape.
In general case you need to determine maximum and minimum shape coordinates along every axis and define minimum axis aligned integer bounding box with values rounded to larger (using Ceil) for max and rounded to smaller (using Floor) for min coordinates. For example:
XMin_Box = Floor(XMin_Shape)
XMax_Box = Ceil(XMax_Shape)
Edit:
If you need to approximate a shape with more precision, consider some kind of voxelization (3d analog of 2d rasterization)
What is the unit to measure distence between any 2 points in an image of a spherical object.
For example the distance between the 2 red points on the tennis ball.
NOTE: As a matter of fact, the "Euclidean distance" cannot be used, since ball is non-Euclidean. Ball is almost spherical, the imaging system projects the ball surface on a plane, where the image elements are not equispaced, neither represent equal areas. The true Euclidean distance depends on the actual position of the points with respect to the camera.
General idea
Supposing the picture takes an isometric projection of space, we can measure coordinates on the picture as if they were coordinates on a plane.
From there we can transform them into an arbitrary ball-centric spherical coordinate system, and then we'll easily get the distance between them.
Definitions
Let us suppose you know the radius r of the sphere. We'll use a coordinate system centered at the center of the sphere, with x the direction orthonormal to the plane projection induced by the picture (thus the vector comes right out of the photo). Then the directions y and z are in the picture, let's take y horizontal and z vertical. See drawing for reference.
Then the spherical coordinate system induced by this is such that we have a distance to the centre which is always r on the sphere, and 2 angles theta and phi :
(source: motionscript.com)
.
Now we can convert each point into spherical coordinates and compute the distance between them.
Convert to spherical coordinates
For each point, the z coordinate is the vertical distance on the picture between the point and the horizontal line that cuts the ball in two equal halves. Express it in terms of r, the radius of the ball, thus z = c * r, with c in [-1,1], negative if the point is below the line, positive if above.
We know that z = r * cos(theta), so theta = arccos(c). Since theta is in [0,Π], no special cases here.
Now measure y in the same way, which is the horizontal distance (to the right is positive) between the point and the vertical line cutting the ball in 2. With y = r * b, and b in [-1,1].
We need theta's sine, which is sin(theta) = sqrt(1 - c*c), then it comes that phi = arcsin( b / sqrt(1 - c*c) ). Because we can see the point on the picture, we know that it has x > 0 by definition of our coordinate system. That means that phi is in [-Π/2,Π/2], so again, no tricks or surprises in the trigonometry here.
Distance between points on a sphere
Well everything is explained in this math exchange question, because most great-arc distances are expressed in terms of latitude and longitude, which use different conventions.
Now we replace elements of the formula in term of the c1, c2, b1 and b2 we previously computed :
The formula you eventually get is , where cos-1 is also known as the arccos function.
I won't delve into the detail (especially because it's such a pain to include latex from a mobile app), but the steps are :
expand the difference inside the cosine
in the only non-trivial term transform the phi's cosines with sqrt(1-sin2)
push both sin(theta) of that term inside the square root, some multiplying with the sin(phi) will give you the b squared terms
express remaining squared sines under the square root as 1-cos2
The final unit of measure will be in whatever unit you express r.
As you can see, you only need the radius at the end, after the arccos (for bs and cs, you only need the size of r and respectively ys and zs on the picture, not in the physical world).
Then, if you are only going to compare distances of points on that same sphere, you may simplify by r, and compare the angles between points at the center of the sphere (i.e. use only the arccos's result without multiplying by r), since these angles are proportional to the arc's distances on the sphere. Your unit of measurement would then be in radians.
I have a circle I want to divide up in to a number of segments all defined by X and Y coordinates. How to I test to see if a point (X, Y) is in a particular segment?
A code example would be preferable.
You don't need to use trigonometry for this (and in general, trigonometry should be avoided whenever possible... it leads to too many precision, domain, and around-the-corner problems).
To determine whether a point P is counter-clockwise of another point A (in the sense of being in the half-plane defined by the left side of a directed line going through the origin and then through A), you can examine the sign of the result of Ax*Py - Ay*Px. This is generally known as the "perpendicular dot product", and is the same as the Z coordinate of the 3D cross product.
If there are two points A and B (with B defining the CCW-most extent) defining a sector, and the sector is less than half the circle, any point which is CCW of A and CW of B can be classified as in that sector.
That leaves only a sector which is more than half of the circle. Obviously, a given set of points can only define at most one such sector. There's clever things you can do with angle bisection, but the easiest approach is probably just to classify points as in that sector if you can't classify them as being in any other sector.
Oh, forgot to mention -- determining the order of the points for the purposes of pairing them up for sectors. Not to go against my previous advice, but the most straightforward thing here is just to sort them by their atan2 (not atan... never ever use atan).
Use the polar coordinate system centred at the centre of the circle, and examine the angular coordinate (φ in the Wikipedia article).
What exactly you do with φ depends on how your segments are defined. For example, if you have n equal segments that start at 0 radians, floor(φ * n / (2 * π)) will give you the segment number.
Your segment is defined by two intersections between the circle and a line. You just have to know if:
The angle between the center of your circle and your point is between
the angles formed by the two previous points and the center.
the point is in the circle (the length from this point to the center is smaller than the radius)
from what side is the point compared to the line (it must be beyond the line).
Remark
In geometry, a circular segment (symbol: ⌓) is a region of a circle
which is "cut off" from the rest of the circle by a secant or a chord.
Here is a segment:
If x & y are not already relative to the center of the circle, subtract the coordinates of the center of the circle:
x -= circle.x
y -= circle.y
Use atan2 to get the angle of the point about the origin of the circle:
angle = atan2(y, x)
This angle is negative for points below the x-axis, so adjust to always be positive:
if (angle < 0) angle += 2 * pi
Assuming your segments are equally spaced, use this formula to get the index of the segment:
segment = floor((angle * numSegments) / (2 * pi))
If you find the result is referring to a segment on the opposite side of the circle to what you want, you might have to do y = -y in the beginning or a segment = (numSegments - 1) - segment at the end to flip it round the right way, but it should basically work.
I have a stack of images (about 180 of them) and there are 2 stars (just basic annotations) on every single image. Hence, the position (x,y) of the two stars are provided initially. The dimensions of all these images are fixed and constant.
The 'distance' between the image is about 1o with the origin to be the center (width/2, height/2) of every single 2D image. Note that, if this is plotted out and interpolated nicely, the stars would actually form a ring of an irregular shape.
The dotted red circle and dotted purple circle are there to give a stronger scent of a 3D space and the arrangement of the 2D images (like a fan). It also indicates that each slice is about 1o apart.
With the provided (x,y) that appeared in the 2D image, how do you get the corresponding (x,y,z) in the 3d space knowing that each image is about 1o apart?
I know that MATLAB had 3D plotting capabilities, how should I go about implementing the solution to the above scenario? (Unfortunately, I have very little experience plotting 3D with MATLAB)
SOLUTION
Based on the accepted answer, I looked up a bit further: spherical coordinate system. Based on the computation of phi, rho and theta, I could reconstruct the ring without problems. Hopefully this helps anyone with similar problems.
I have also documented the solution here. I hope it helps someone out there, too:
http://gray-suit.blogspot.com/2011/07/spherical-coordinate-system.html
I believe the y coordinate stays as is for 3D, so we can treat this as converting 2D x and image angle to an x and z when viewed top down.
The 2D x coordinate is the distance from the origin in 3D space (viewed top down). The image angle is the angle the point makes with respect to the x axis in 3D space (viewed top down). So the x coordinate (distance from orign) and the image angle (angle viewed top down) makes up the x and z coordinates in 3D space (or x and y if viewed top down).
That is a polar coordinate.
Read how to convert from polar to cartesian coordinates to get your 3D x and z coordinates.
I'm not great at maths either, here's my go:
3D coords = (2Dx * cos(imageangle), 2Dy, 2Dx * sin(imageangle))
Given the 2D coordinates (x,y) just add the angle A as a third coordinate: (x,y,A). Then you have 3D.
If you want to have the Anotations move on a circle of radius r in 3D you can just calculate:
you can use (r*cos(phi),r*sin(phi),0) which draws a circle in the XY-plane and rotate it with a 3x3 rotation matrix into the orientation you need.
It is not clear from you question around which axis your rotation is taking place. However, my answer holds for a general rotation axis.
First, put your points in a 3D space, lying on the X-Y plane. This means the points have a 0 z-coordinate. Then, apply a 3D rotation of the desired angle around the desired axis - in your example, it is a one degree rotation. You could calculate the transformation matrix yourself (should not be too hard, google "3D rotation matrix" or similar keywords). However, MATLAB makes it easier, using the viewmtx function, which gives you a 4x4 rotational matrix. The extra (fourth) dimension is dependent on the projection you specify (it acts like a scaling coefficient), but in order to make things simple, I will let MATLAB use its default projection - you can read about it in MATLAB documentation.
So, to make the plot clearer, I assume four points which are the vertices of a square lying on the x-y plane (A(1,1), B(1,-1), C(-1,-1), D(1,-1)).
az = 0; % Angle (degrees) of rotation around the z axis, measured from -y axis.
el = 90; % Angle (degrees) of rotation around the y' axis (the ' indicates axes after the first rotation).
x = [1,-1, -1, 1,1]; y = [1, 1, -1, -1,1]; z = [0,0, 0, 0,0]; % A square lying on the X-Y plane.
[m,n] = size(x);
x4d = [x(:),y(:),z(:),ones(m*n,1)]'; % The 4D version of the points.
figure
for el = 90 : -1 :0 % Start from 90 for viewing directly above the X-Y plane.
T = viewmtx(az, el);
x2d = T * x4d; % Rotated version of points.
plot3 (x2d(1,:), x2d(2,:),x2d(3,:),'-*'); % Plot the rotated points in 3D space.
grid
xlim ([-2,2]);
ylim ([-2,2]);
zlim([-2,2]);
pause(0.1)
end
If you can describe your observation of a real physical system (like a binary star system) with a model, you can use particle filters.
Those filters were developed to locate a ship on the sea, when only one observation direction was available. One tracks the ship and estimates where it is and how fast it moves, the longer one follows, the better the estimates become.