Ray-Box Intersection during Scene traversal with matrix transforms - raytracing

There are a few ways that I'm testing my ray-box intersections:
Using the ComputeIntersectionBox(...) method, that takes a ray and a box as arguments and computes the closest intersection of the ray and the box. This method works by forming a plane with each of the faces of the box and finding an intersection with each of the planes. Once an intersection is found, a check is made whether or not the point is on the surface of the box by checking that the intersection point is between the corner points.
When I look at rays after running this algorithm on two different boxes, I obtain the correct intersections.
Using ComputeIntersectionScene(...) method without using the matrix transformations on a scene that has two spheres, a dodecahedron (a triangular mesh), and two boxes. ComputeIntersectionScene(...) recursively traverses all of the nodes of the scene graph and computes the closest intersection with the given ray. This test in particular does not apply any transformations that parent nodes may have that also need to be applied to their children. With this test, I also obtain the correct intersections.
Using ComputeIntersectionScene(...) method WITH the matrix transformations. This test works like the one above except that before finding an intersection between the ray and a node in the scene, the ray is transformed into the node's coordinate frame using the inverse of the node's transformation matrix and after the intersection has been computed, this intersection is transformed back into the world coordinates by applying the transformation matrix to the intersection point.
When testing with the third method on the same scene file as described in 2, testing with 4 rays (thus one ray intersects the one sphere, one ray the the other sphere, one ray one box, and one ray the other box), only the two spheres get intersected and the two boxes do not get intersections. When I debug looking into my ComputeIntersectionBox(...) method, it actually tells me that the ray intersects every plane on the box but each intersection point does not lie on the box.
This seems to be strange behavior, since when using test 2 without transformations, I obtain the correct box intersections (thus, I believe my ray-box intersection to be correct) and when using test 3 WITH transformations, I obtain the correct sphere intersections (thus, I believe my transformed ray should be OK).
Any suggestions where I could be going wrong?
Thank you in advance.

So the mistake was actually an implementation bug: when I was transforming the ray, I was transforming the pointer to the ray, which transformed all of the pointers within it as well (since the function is recursive). What I should have done is make a separate copy of my ray and perform the transformation on the copy, not the original.

Related

Intersection test with kd-tree

My current understanding of a kd-tree is; that on every node we split our points into two equally big groups for one axis.
We iterate through the individual axis until the tree is saturated.
This kind of data-structure is, of course, is interesting for raytracing applications because we don't have to search through every triangle face to test our intersection with the ray, we simply know where it would be likely that a triangle would intersect with our ray.
I have some question on how this is done.
How do we handle weird triangles where we cannot make easy splits(triangles intersecting other triangles or triangles which span the entire?
Do we even split on the triangles or do we split on the vertices?
How exactly do we test for an intersection of a ray that we send out from the camera ?
I see a couple of methods. First, we could build bounding boxes from our scene and the splitting planes and test for intersection with those boxes or we could test for intersection with the splitting planes and see where the intersection is relative to the camera
The short answer is: This all depends on your application. There are several variations of kd-trees.
How do we handle weird triangles where we cannot make easy splits?
I believe you are referring to the choice of the splitting plane for a given set of triangles. This is a pretty hard optimization problem, which is usually solved with a heuristic. E.g., you could sort the centroids of triangles along one axis and choose the median as the splitting plane. Nothing is stopping you from implementing some more intelligent criterion.
If you find that your splitting plane passes through a primitive, you have two options. Either split the primitive or add it to both subtrees. What you should do depends on your application.
Do we even split on the triangles or do we split on the vertices?
That depends on the primitives you want to add to your tree. If you want to use the tree for raycasting, then it makes sense to have the triangles in the tree. kd-trees are a very general concept that works with any kind of primitives, though. E.g., they are also widely used for point clouds.
How exactly do we test for an intersection of a ray that we send out from the camera?
You do this by traversing the tree. So, you start at the root node and check if the ray intersects with the associated bounding box (which is the entire space). Then you check which of the two subtrees are first intersected by the ray and continue to this one. And then you repeat: You test for intersection with the node's AABB (which you build incrementally from the splitting planes). If the ray does not intersect the AABB, then immediately return back to the parent node. If it does, continue to the first child. When you come back from the first child, go to the second child (unless you already found an intersection).
For some more details, I would advice to take a look at application-specific instances of kd-trees.

Point of intersection between Oriented Boxes (or OBB)

I am trying to write a Rigid body simulator, and during simulation, I am not only interested in finding whether two objects collide or not, but also the point as well as normal of collision. I have found lots of resources which actually says whether two OBB are colliding or not using separating axis theorem. Also I am interested in 3D representation of OBB. Now, if I know the axis with minimum overlap region for two colliding OBB, is there any way to find the point of collision and normal of collision? Also, there are two major cases of collision, first, point-face and second edge-edge.
I tried to google this problem, but almost every solution is only detecting collision with true or false.
Kindly somebody help!
Look at the scene in the direction of the motion (in other terms, apply a change of coordinates such that this direction becomes vertical, and drop the altitude). You get a 2D figure.
Considering the faces of the two boxes that face each other, you will see two hexagons each split in three parallelograms.
Then
Detect the intersections between the edges in 2D. From the section ratios along the edges, you can determine the actual z distances.
For all vertices, determine the face they fall on in the other box; and from the 3D equations, the piercing point of the viewing line into the face plane, hence the distance. (Repeat this for the vertices of A and B.)
Comparing the distances will tell you which collision happens first and give you the coordinates of the first meeting point (in the transformed system, the back to absolute coordinates).
The point-in-face problem is easy to implement as the facesare convex polygons.

Point in polygon on Earth globe

I have a list of coordinates (latitude, longitude) that define a polygon. Its edges are created by connecting two points with the arc that is the shortest path between those points.
My problem is to determine whether another point (let's call it U) lays in or out of the polygon. I've been searching web for hours looking for an algorithm that will be complete and won't have any flaws. Here's what I want my algorithm to support and what to accept (in terms of possible weaknesses):
The Earth may be treated as a perfect sphere (from what I've read it results in 0.3% precision loss that I'm fine with).
It must correctly handle polygons that cross International Date Line.
It must correctly handle polygons that span over the North Pole and South Pole.
I've decided to implement the following approach (as a modification of ray casting algorithm that works for 2D scenario).
I want to pick the point S (latitude, longitude) that is outside of the polygon.
For each pair of vertices that define a single edge, I want to calculate the great circle (let's call it G).
I want to calculate the great circle for pair of points S and U.
For each great circle defined in point 2, I want to calculate whether this great circle intersects with G. If so, I'll check if the intersection point lays on the edge of the polygon.
I will count how many intersections there are, and based on that (even/odd) I'll decide if point U is inside/outside of the polygon.
I know how to implement the calculations from points 2 to 5, but I don't have a clue how to pick a starting point S. It's not that obvious as on 2D plane, since I can't just pick a point that is to the left of the leftmost point.
Any ideas on how can I pick this point (S) and if my approach makes sense and is optimal?
Thanks for any input!
If your polygons are local, you can just take the plane tangent to the earth sphere at the point B, and then calculate the projection of the polygon vertices on that plane, so that the problem becomes reduced to a 2D one.
This method introduces a small error as you are approximating the spherical arcs with straight lines in the projection. If your polygons are small it would probably be insignificant, otherwise, you can add intermediate points along the arcs when doing the projection.
You should also take into account the polygons on the antipodes of B, but those could be discarded taking into account the polygons orientation, or checking the distance between B and some polygon vertex.
Finally, if you have to query too many points for that, you may like to pick some fixed projection planes (for instance, those forming an octahedron wrapping the sphere) and precalculate the projection of the polygons on then. You could even create some 2d indexing structure as a quadtree for every one in order to speed up the lookup.
The biggest issue is to define what we mean by 'inside the polygon'.
On a sphere, every polygon (as long as the lines are not intersecting) defines two regions of the sphere. Both regions are equally qualified to be called the inside of the polygon.
Consider a simple, 1-meter on a side, yellow square around the south pole.
You can think of the yellow area to be the inside of the square OR you can think of the square enclosing everything north of each line (the rest of the earth).
So, technically, any point on the sphere 'validly' inside the polygon.
The only way to disambiguate is to select which side of the polygon you want. For example, define the interior to always be the area to the right of each edge.

Algorithm for determining whether a point is inside a 3D mesh

What is a fast algorithm for determining whether or not a point is inside a 3D mesh? For simplicity you can assume the mesh is all triangles and has no holes.
What I know so far is that one popular way of determining whether or not a ray has crossed a mesh is to count the number of ray/triangle intersections. It has to be fast because I am using it for a haptic medical simulation. So I cannot test all of the triangles for ray intersection. I need some kind of hashing or tree data structure to store the triangles in to help determine which triangle are relevant.
Also, I know that if I have any arbitrary 2D projection of the vertices, a simple point/triangle intersection test is all necessary. However, I'd still need to know which triangles are relevant and, in addition, which triangles lie in front of a the point and only test those triangles.
I solved my own problem. Basically, I take an arbitrary 2D projection (throw out one of the coordinates), and hash the AABBs (Axis Aligned Bounding Boxes) of the triangles to a 2D array. (A set of 3D cubes as mentioned by titus is overkill, as it only gives you a constant factor speedup.) Use the 2D array and the 2D projection of the point you are testing to get a small set of triangles, which you do a 3D ray/triangle intersection test on (see Intersections of Rays, Segments, Planes and Triangles in 3D) and count the number of triangles the ray intersection where the z-coordinate (the coordinate thrown out) is greater than the z-coordinate of the point. An even number of intersections means it is outside the mesh. An odd number of intersections means it is inside the mesh. This method is not only fast, but very easy to implement (which is exactly what I was looking for).
This is algorithm is efficient only if you have many queries to justify the time for constructing the data structure.
Divide the space into cubes of equal size (we'll figure out the size later). For each cube know which triangles has at least a point in it. Discard the cubes that don't contain anything. Do a ray casting algorithm as presented on wikipedia, but instead o testing if the line intersects each triangle, get all the cubes that intersect with the line, and then do ray casting only with the triangles in these cubes. Watch out not to test the same triangle more than one time because it is present in two cubes.
Finding the proper cube size is tricky, it shouldn't be neither to big or too small. It can only be found by trial and error.
Let's say number of cubes is c and number of triangles is t.
The mean number of triangles in a cube is t/c
k is mean number of cubes that intersect the ray
line-cube intersections + line-triangle intersection in those cubes has to be minimal
c+k*t/c=minimal => c=sqrt(t*k)
You'll have to test out values for the size of the cubes until c=sqrt(t*k) is true
A good starting guess for the size of the cube would be sqrt(mesh width)
To have some perspective, for 1M triangles you'll test on the order of 1k intersections
Ray Triangle Intersection appears to be a good algorithm when it comes to accuracy. The Wiki has some more algorithms. I am linking it here, but you might have seen this already.
Can you, perhaps improvise by, maintaining a matrix of relationship between the points and the plane to which they make the vertices? This subject appears to be a topic of investigation in the academia. Not sure how to access more discussions related to this.

Finding the polygon in a 2D mesh which contains a point

I have a 3D polygon mesh and a corresponding 2D polygon mesh (actually from a UV map) which I'm using to map the geometry onto a 2D plane. Given a point on the plane, how can I efficiently find the polygon on which it's resting in order to map that 2D point back into 3D?
The best approach I can think of is to store the polygons in a 2D interval tree, and use that to get candidate polygons. Is there a simpler approach?
To clarify, this is not for a shader. I'm actually taking a 2D physical simulation and rendering it wrapped around a 3D mesh. For drawing each object, I need to figure out what point in 3D corresponds to its real 2D position.*
One approach I've seen for triangle meshes goes as follows: choose a triangle, and imagine that each of the sides defines a half space. For a given edge, the half space boundary is the line containing the edge, and the half space does not contain the triangle. Choose an edge whose corresponding half space contains your target point. Then select the triangle on the other side of edge, and repeat the process.
Using this method, you will eventually end up at the triangle that contains your target point.
This method is arguable simpler than implementing a 2D interval tree, although the search is less efficient (if n is the number of triangles, it is O(√n) rather than O(log n). Also, it should work for a polygon mesh, as long as the polygons are convex.
So, if I were trying to just get the thing implemented, I'd probably start with a global search of all triangles - compute the barycentric coordinates of that 2d point for each triangle, find the triangle where the barycentric coordinates are all positive, and then use those to map to 3d (multiply the stu position by the 3d points). I'd do this first, and only if it's not fast enough would I try something more complex.
If it's possible to iterate by triangle rather than by 2d points, then the barycentric method would probably be fast enough. But it seems like you've got a bunch of 2d points at arbitrary positions that need to be mapped, and the points change position from frame to frame?
If you've got this kind of situation, you could probably get a big speedup by implementing a local update per frame. Each 2d point would remember which triangle it was within. Set that as the current triangle. Test if the new position is within the current triangle. If not, then you want to walk the mesh to the adjacent triangle which is closest to the target 2d point. Each edge-adjacent triangle is composed of the two common points on the edge, plus another point. Find which edge-adjacent triangle's other point is closest to the target, and set that as current. Then iterate - seems like it should find it pretty quickly? You could also cache a max size for each triangle, so if the point has moved a lot you can just iterate to the next neighbor without doing the barycentric computation (the max size would need to be the distance such that if you are farther than that distance from any triangle point there is no chance you're inside the triangle. This is the length of the largest edge).
But as you mention in your comments, you can run into problems with meshes that have concavities, holes, or separate connected components, where you may fall into a local minimum. There are a couple of ways to deal with this. I think the simplest is to keep a list of all visited triangles (maybe as a flag on the triangle, vector< bool > or set< triangle index >) and refuse to revisit a triangle. If you find that you've visited all the neighbors of your current triangle, then fall back to a global search. Such failures are likely to be uncommon, so it shouldn't hurt your performance too much.
This kind of per-frame updating can be very fast, and might even be a decent approach for computing the initial containing triangles - just choose a random triangle and walk from there (changes from checking all n triangles to only those that are in roughly a straight line to the target). If it's not fast enough, what you could do is keep a k-d tree (or something similar) of the 2d mesh points as well as a single touching triangle index for each mesh point. To seed the iteration, find the closest point to the target 2d point in the k-d tree, set the adjacent triangle to be current, and then iterate.

Resources