public IEnumerable <HitInfo <V> > Raycast(RayDescription ray) { if (mesh.Topology != Topology.Triangles) { yield break; } Ray3D r = new Ray3D(ray.Origin, ray.Direction + 0.000000001f); // epsilon deviation of the direction to avoid indefinitions float minT, maxT; if (!box.Intersect(r, out minT, out maxT)) { yield break; } maxT = min(maxT, ray.MaxT); float t = max(ray.MinT, minT); float3 P = r.X + r.D * t; int3 cell = (int3)min(((P - box.Minimum) * resolution / (box.Maximum - box.Minimum)), resolution - 1); float3 side = r.D > 0; int3 cellInc = (r.D > 0) * 2 - 1; float3 corner = box.Minimum + (cell + side) * (box.Maximum - box.Minimum) / resolution; float3 alphas = (corner - r.X) / r.D; float3 alphaInc = (box.Maximum - box.Minimum) / abs(resolution * r.D); while (t < maxT) { float nextT = min(alphas.x, min(alphas.y, alphas.z)); if (any(cell < 0) || any(cell >= resolution)) { yield break; // just for numerical problems, traversal could go outside grid. } // check current cell if (triangleHash[cell.z, cell.y, cell.x] != null) { List <HitInfo <V> > hits = new List <HitInfo <V> >(); foreach (var i in triangleHash[cell.z, cell.y, cell.x]) { V v1 = mesh.Vertices[mesh.Indices[i * 3 + 0]]; V v2 = mesh.Vertices[mesh.Indices[i * 3 + 1]]; V v3 = mesh.Vertices[mesh.Indices[i * 3 + 2]]; Triangle3D tri = new Triangle3D(v1.Position, v2.Position, v3.Position); float triT; float3 baricenter; if (tri.Intersect(r, out triT, out baricenter)) { if (triT >= t && triT <= nextT) { hits.Add(new HitInfo <V> { T = triT, Attribute = v1.Mul(baricenter.x).Add(v2.Mul(baricenter.y)).Add(v3.Mul(baricenter.z)) }); } } } hits.Sort((h1, h2) => h1.T.CompareTo(h2.T)); // only need to sort hits inside a cell, because cells are iterated in ray-order foreach (var hi in hits) { yield return(hi); } } // advance ray to next cell int3 movement = new int3(alphas.x <= alphas.y && alphas.x <= alphas.z, alphas.y < alphas.x && alphas.y <= alphas.z, alphas.z < alphas.x && alphas.z < alphas.y); cell += movement * cellInc; alphas += movement * alphaInc; t = nextT; } }