Intersect picked Ray with shapes in OpenGL - xcode

I am trying to perform picking in OpenGL, and have 3 questions in 1.
I use twice the Unproject command, once with 0 and once with 1 as near/end planes.
Some article say that 0 and 1 are ok, some others say that I should use a calculated depth. Which one should I take ?
Then, assuming I could substract both results, that gives me a ray (the ray is going from my "camera" to the direction indicated as x,y,z, right ? x,y,z are absolute values or relative to my "camera" ?
Now that I have the ray, how can I intersect it with shapes ? By the way, how can I list existing shapes and calculate their coordinates vs the ray ?

2 - Your ray will be relative to the camera, just multiply it by the inverse camera transform.
3 - For just about all purposes, you need a spatial subdivision algorithm (Binary Space Partition, Bounding Volume Hierarchy, etc.) And you should maintain a list of the shapes you have created...

Related

Method for finding all cubes of size L in a viewing frustum?

I am trying to find or search for a method that quickly finds all cubes of size L that would be contained by a viewing frustum. Maybe even using cuda.
I have made a DDA traversal for raycasting, which is like a 1D case to me and simple, as I only move along the line at a known distance.
My instinct was to create a bounding box of the frustum, and subdivide this space into a spatial grid of size L cubes. Then test each cell's center of the grid for being inside the frustum. Considering the frustum is a pyramid, it seems that about half the cells would be occupied by a bounding box and I feel that this method is just doing too much work. It will surely work though, I am hoping for a less naive or faster geometric approach.
Perhaps ray cast the left wall first, then right wall second and then line cast in between these? So in a nutshell, looking for the R3 version of something like a DDA traversal.
The fastest way to detect if a vertex resides within a frustum is dot product. The frustum consists of 4 planes, that is top, bottom, left, right, and two z values, front and back clipping. For each vertex check two things: First, is it outside front or back panel? And if not, is it inside the four planes?
To check if a vertex is outside front or back panel you check vertex.Z against your frustrum:
isInsideZ = vertex.Z >= frustrum.Zmin && vertex.Z <= frustrum.Zmax;
To check if it's inside the four frustrum 'walls' you need to compute the cross vectors for them, oriented towards the frustrum's center. Then check the dot product of each cross vector and the position vector to your vertex relative to the respective plane. You obtain this position vector by subtracting some arbitrary point on the plane from the vertex you test. Should the dot product be positive, the vertex is above that plane.
isAbove[i] = Vector3D.Dot(cross[i], vertex - planeloc[i]) > 0;
Where planeloc[i] is any point located on the respective plane i.
The vertex is inside the frustrum if all conditions are met:
isInside = isInsideZ && isAbove[0] && isAbove[1] && isAbove[2] && isAbove[3];
This sounds a bit awkward to handle, but a lot of things can be done outside the grinding loop, such as computing the cross products, i.e. frustrum plane normals, or the plane location vectors. For example, if a plane is spanned by (1,0,0), (1,1,0) then (1,0,0) already represents a point located on that plane.

marching cubes efficiency- you can reduce 3/4rs of the edge calculations?

Normal marching cubes finds 12 edges per cube, but you can do 3 edges per cube, save the edges inside an array, and then go through the cubes again, referencing the edges from the cubes adjacent rather than calculating them.
The process to reference adjacent cubes isn't clearly discussed on the Internet so anyone using marching cubes would be welcome to help find the details of the solution. do you know an implementation already?
here is a picture showing the 3 edges in yellow that you need for each cube, instead of 12.
EDIT- I just found this solution, although it's just a part of it:
Imagine 3 edges coming from the corner of the cube with lowerest coordinates. Then all other edges just belong to other cubes. If our cube has coordinates (x,y,z), the neiboring cubes have coordinates (x+1,y,z), (x,y+1,z), (x,y,z+1), (x+1,y+1,z), (x+1,y,z+1), (x,y+1,z+1). You can imagine the edge as a vector. Then the corner of the cube have edges (1,0,0), (0,1,0), (0,0,1). The cube with coordinates (x+1,y,z) have edges (0,1,0) and (0,0,1) that belong to our cube. The cube (x+1,y+1,z) has only one edge (0,0,1) that belongs to our cube. So if you store 4 elements for the cube you can access them like that:
edge1 = cube[x][y][z][0];
edge2 = cube[x][y][z][1];
edge3 = cube[x][y][z][2];
edge4 = cube[x+1][y][z][1];
edge5 = cube[x+1][y][z][2];
edge6 = cube[x][y+1][z][0];
edge7 = cube[x][y+1][z][2];
edge8 = cube[x][y][z+1][0];
edge9 = cube[x][y][z+1][1];
edge10 = cube[x+1][y+1][z][2];
edge11 = cube[x+1][y][z+1][1];
edge12 = cube[x][y+1][z+1][0];
Now which points edge7 connect? The answer is (x,y+1,z) and (x,y+1,z)+(0,0,1)=(x,y+1,z+1).
Now which cubes edge7 connect? It is more harder. We see that coordinate z is changes along the edge this means that neibour cube has the same z coordinate. Now all others coordinates change. Where we have +1, the cube has large coordinate. Where we have +0, the cube has smaller coordinates. So the edge connects cubes (x,y,z) and (x-1,y+1,z). Other 2 cubes that has the same edge are (x,y+1,z) and (x-1,y,z).
-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=--=-=
EDIT2-
So I am doing this, and it isn't so simple. I have a loop which simultaneously calculate 8 points, 12 edges, the interpolation of edges, the bit values and a vertex the values for the edges, all in one loop.
so I am doing a new loop previous to it to calculate as much as possible and place it in arrays to used in the complicated loop.
I can recycle the interpolated values of the intersection points along edges, in an array, although I will have to recalculate all the points again in the complicated loop, because the values of the points I used to decide bit numbers that reference values in the vertex table. That confuses me! I thought that once I have the edge intersection values, I could use those directly to get the triangle tables, without having to calculate the points all over again!
in fact no.
anyway, here is another bit of information with someone that already did it, if only it was readable!
http://www.new-npac.org/projects/sv2all/sv2/vtk/patented/vtkImageMarchingCubes.cxx
scroll to this line: Cubes are responsible for edges on their min faces.
A simple way to reduce edge calculations in the way you are suggesting is to compute cubes one axis aligned plane at a time.
If you kept all of the cubes, with their edges, in memory, it would be easy to compute each edge only once and to find adjacent edges by indexing. However, you usually don't want to keep all the cubes in memory at once because of the space requirements.
A solution to this is to compute one plane of cubes at a time. i.e. an axis aligned cross-section, starting from one side and progressing to the opposite side. You then only need to keep at most two full planes of cubes in memory at a time. As you move through each plane you can reference shared edges in the previous plane and previously computed cubes in the current plane. As you move to the next plane you can deallocate the plane you will no longer need.
Edit: This article discusses doing just what I suggest:
http://alphanew.net/index.php?section=articles&site=marchoptim&lang=eng
Funny, because when I implemented my own MCs I came up with similar solution.
When you start working with MCs you treat them as a distinct cubes but if you want to go for high performance you'll need to create entire mesh as a whole, and creating vertex indices etc. is not so easy here. It gets even more interesting when you want to add smooth per-vertex normals :).
To solve this I created a simple index cache mechanism to store vertex indices for each edge.
Then, for each computed edge I have cube position x,y,z and edge index and I do as follows:
For each axis:
if the edge is on '+' side of axis:
replace edge index with its '-' side sibling
increment cube position along axis
This simple operation gives me the correct cube position, and edge index of 0,1,2. Then I compute a total cache index from x,y,z,edgeIndex values with simple bit rotations.
When I have cache index I check if it's bigger than -1. If it is then there was an already computed vertex at this edge and I can reuse it. If it's -1 I need to create a new vertex and store its index in the cache. This way you'll compute each vertex only once, and you can even add a normal value shared between every triangle containing your vertex.
Yes, I think I do it similar to kolenda. I have a struct with 5 ints: (cube)index and 4 vertexindices (A, B, C, D).
for the most inner loop (x), I have just lastXCache and nextXCache. On the 4 edges pointing in the -x direction, i ask if lastXCache.A != -1 and if so, assign the previously calculated value, etc.
In the +x direction I store calculated vertices in nextXCache. when cube is done: lastXCache = nextXCache;
For y and z direction it needs to be a list (unity term for mutable array), next y is next row (so sizex) and next z is the next plane (so sizex * sizey)
only diadvantage is that this way it has to run cube after cube, so serially. But you can calculate different chunks in parallel.
Another way I thought of that could be more parallel would need 2 passes: 1. calculate 3 edges every cube, when 1 is done -> 2. draw the triangles.
Don't really know what is better, but the way it actually works seems to be fast enough. even better with unity jobs. Create one IJob for 1 chunk/mesh.

Camera homography

I am learning camera matrix stuff. I already known that I can get the homography of the camera (3*3 matrix) by using four points in a plane in object space. I want to know if we can get the homagraphy with four points not in a plane? If yes, how can I get the matrix? What formulas should I look at?
I also confused homography with another concept: I only need to know three points if I want to convert from points from one coordinate to another coordinate system. So why we need four points in computing homography?
Homography maps points
1. On plane to points at another plane
2. Projections of points in 3D (no obligatory lying on the same plane) during a pure camera rotation or zoom.
The latter can be easily verified if you look at the rays that connect points while sensor plane rotates: green are two sensor positions and black is a 3d object
Since Homography is between projections and not between objects in 3D you don’t care what these projections represent. But this can be confusing, I agree. For example you can point your camera at 3D scene (that is not flat!), then rotate your camera and the two resulting pictures of the scene will be related by homography. This is, by the way, a foundation for image panoramas.
Three point correspondences you mentioned may be reladte to a transformation called Affine (happens during large zooms when a perspective effects disappears) or to the finding a rigid rotation and translation in 3D space. Both require 3 point correspondences but the former needs only 2D points while the latter needs 3D points. The latter case has 6DOF ( 3 for rotation and 3 for translation) while each correspondence provides 2DOF, hence 6/2=3 correspondences. Homography has 8 DOF so there should be 8/2=4 correspondences;
Below is a little diagram that explains the difference between affine and homographs transformation when the original square tilts forward. In affine case the perspective effect is negligible that is far side has the same length as a near one. In the case of Homography the far side is shorter.
If you only have 4 points - and they're not on the same plane - then computing a homography will not work.
If you have a loads of points, and 4 of them do lie on a plane but some don't, there are filters you can use to try to remove the ones not lying on a plane. The filters implemented by OpenCV are called RANSAC and LMeDs.
Also as Hammer says in a comment under your question - The 4th point is there to figure out perspective.
Homography is a 3X3 matrix, which consists of 8 independent unknowns which means it requires 4 equations to solve these unknowns. So, in order to calculate homography we need at least 4 points.
In homography we assume that Z=0 in world scene, so the image projected is assumed as 2D. In a very famous journal named ORB-SLAM, the author formulated a scene-selective approach depending on motion parallax in scene.
Homography is the relation between two planes and the degree of freedom in case of homography transform is 7; hence you need minimum 4 corresponding points.
4 points will give you 4 pair of (x,y) hence you can calculate 7 variables. Homography is homogines transfrom hence the (3,3) value in homography matrix is always 1.
So your first question that can you calculate homography with 3 points in the plane and 4th not on the plane : it's not possible. You need projection of that point on the plane and then you can calculate the homography.
Your 2nd question about how to calculate homography matrix, you can see implemetation of findHomography() in opencv.

Nearest-neighbor algorithm with directions (left / right / top / bottom)

Having n random points in 2D geometry, for each point p I need to find 4 (or less if not exists) closest points (qa,qb,qc,qd), where qa is the closest left-top point, qb is the closest right-top point, qc is the closest left-bottom point and qd is the closest right-bottom point to point p. Having same x coordinate is considered as left, having same y coordinate is considered as bottom.
What would be the best data structure to store point coordinates and their nearest-neighbor references? What algorithm would be the fastest or the most performed?
Note: This issue is far more then nearest-neighbor algorithm, as for each point 4 neighbor points are needed.
You can try a space filling curve and a quadtree data structure. A space filling curve reduces the 2 dimension to 1 dimension and it works best with power of 2 grids. A quadtree divides the plane into 4 quads. A space filling curve is mathematical function taking 2 variables and gives 1 number as result. It can have also 3,4,5 variables but the most simple is with 2. Because it gives 1 number and takes 2 variables it can help for questions with 2 dimensions or more.
http://social.technet.microsoft.com/wiki/contents/articles/9694.tuning-spatial-point-data-queries-in-sql-server-2012.aspx
https://www.google.com/search?q=nearest+neigbor+search+space+filling+curve
Use a k-dim tree index (in this case k=2) so a quad tree. This should allow you to efficiently search the space to the left,right,up and down of your point. You can probably formulate a query in a dmbs for this but conceptually I would search the points own "quad" and then depending on the position of the point in the quad we can know if we found the nearest point in one direction or not. Then we know which quads to search for the rest of the points.
Since you are doing this for each point you know there exists symmetry i.e. point P1 has P2 as nearest left neighbor so P2 has P1 as nearest right neighbor. So update the point objects accordingly.

How to generate a subdivided icosahedron?

I've asked some questions here and seen this geometric shape mentioned a few times among other geodesic shapes, but I'm curious how exactly would I generate one about a point xyz?
There's a tutorial here.
The essential idea is to start with an icosahedron (which has 20 triangular faces) and to repeatedly subdivide each triangular face into smaller triangles. At each stage, each new point is shifted radially so it is the correct distance from the centre.
The number of stages will determine how many triangles are generated and hence how close the resulting mesh will be to a sphere.
Here is one reference that I've used for subdivided icosahedrons, based on the OpenGL Red Book. The BSD-licensed source code to my iPhone application Molecules contains code for generating simple icosahedrons and loading them into a vertex buffer object for OpenGL ES. I haven't yet incorporated subdivision to improve the quality of the rendering, but it's in my plans.
To tesselate a sphere, most people sub-divide the points linearly, but that does not produce a rounded shape.
For a rounded tesselation, rotate the two points through a series of rotations.
Rotate the second point around z (by the z angle of point 1) to 0
Rotate the second point around y (by the y angle of point 1) to 0 (this logically puts point 1 at the north pole).
Rotate the second point around z to 0 (this logically puts point 1 on the x/y plane, which now becomes a unit circle).
Find the half-angle, compute x and y for the new 3rd point, point 3.
Perform the counter-rotations in the reverse order for steps 3), 2) and 1) to position the 3rd point to its destination.
There are also some mathematical considerations for values near each of the near-0 locations, such as the north and south pole, and the right-most and left-most, and fore-most and aft-most positions, so check those first and perform an additional rotation by pi/4 (45 degrees) if they're at those locations. This prevents floating point math libraries from freaking out and producing wildly out-of-character values for atan2() and other trig functions.
Hope this helps! :-)

Resources