There are two question in one:
- efficiency
- segment-triangle intersection instead of ray-triangle intersection
efficiency
You can use a Bounding Volume Hierarchy (BVH)
The idea is to construct a hierarchy of boxes. Each box contains either other boxes or a bunch of triangles. The boxes are organized as a tree, and the root of the tree corresponds to a box that contains everything.
The function that computes an intersection works like that:
Compute the intersection between the ray and the box. If there is an intersection, open the box and recursively compute the intersections between the ray and what's in the box.
In more formal terms:
Intersect_Ray_Node(Ray, node)
if(Intersect_Ray_Box(Ray, node.box)) {
if(node.is_leaf) {
for each triangle t in node
Intersect_Ray_Triangle(Ray, t)
} else {
for each child in children(node)
Intersect_Ray_Node(Ray,child)
}
}
Now, the "boxes" can be different things. The simplest thing to use is an AABB (Axis Aligned Bounding Box), that is, simply the minimum and maximum values of the coordinates of what's in the box.
There are several ways of implementing the tree. The most efficient implementations use no data structure and simply reorder the facets in the mesh, in such a way that facets that are in the same node have contiguous indices. Then you just need a couple of additional arrays, one that stores for each node the bounds of the boxes, and another one that indicate for each node how many triangles there are in the left child (then the number of triangles in the right child is implicit).
An implementation is available here, in my geogram library. Constructing the AABB is just a matter
of sorting the triangles geometrically here and constructing the bouding box recursively.
I made also a ShaderToy implementation here (and a big comment at the end of BufferA contains the C++ source of my "MeshCompiler" that creates the AABB).
Note that if you want to be even more compact in memory, Pierre Terdiman proposed the Zero Byte AABB-tree (see here and here). The idea is to encode everything in the order of the triangles and the order of the vertices, based on the interesting remark that the bounds of the boxes are always coordinates of existing points in the mesh.
line segment versus ray
If what you want to intersect is a segment (with two vertices) instead of a ray (line that starts from a point and that extends towards infinity in a direction), you can do that with a simple modification of my answer here. Replace the last line
of the intersect_triangle()
function with:
return (det >= 1e-6 && t >= 0.0 && t <= 1.0 && u >= 0.0 && v >= 0.0 && (u+v) <= 1.0);
(test that t
is between 0
and 1
, which means that the point is inside the segment)