public IEnumerable <HitInfo <float3> > Raycast(RayDescription ray) { float minT, maxT; if (!quadric.Intersect(new Ray3D(ray.Origin, ray.Direction), out minT, out maxT)) { yield break; } if (minT >= ray.MinT && minT < ray.MaxT) { yield return new HitInfo <float3> { T = minT, Attribute = ray.Origin + ray.Direction * minT } } ; if (maxT >= ray.MinT && maxT < ray.MaxT) { yield return new HitInfo <float3> { T = maxT, Attribute = ray.Origin + ray.Direction * maxT } } ; } }
public IEnumerable <HitInfo <T> > Raycast(RayDescription ray) { return(geometry.Raycast(ray) .Select(h => new HitInfo <T> { T = h.T, Attribute = transform(h.Attribute) })); }
public IEnumerable <HitInfo <float3> > Raycast(RayDescription ray) { float t; if (!plane.Intersect(new Ray3D(ray.Origin, ray.Direction), out t)) { yield break; } if (t >= ray.MinT && t < ray.MaxT) { yield return new HitInfo <float3> { T = t, Attribute = ray.Origin + t * ray.Direction } } ; } }
public IEnumerable <HitInfo <float3> > Raycast(RayDescription ray) { float epsilon = 0.0001f; foreach (var item in XYlow.Raycast(ray) .Concat(XYup.Raycast(ray) .Concat(XZlow.Raycast(ray) .Concat(XZup.Raycast(ray) .Concat(YZlow.Raycast(ray) .Concat(YZup.Raycast(ray)))))) .OrderBy(x => x.T)) { if (lowerBound.x <= item.Attribute.x + epsilon && item.Attribute.x <= upperBound.x + epsilon && lowerBound.y <= item.Attribute.y + epsilon && item.Attribute.y <= upperBound.y + epsilon && lowerBound.z <= item.Attribute.z + epsilon && item.Attribute.z <= upperBound.z + epsilon) { yield return(item); break; } } }
public IEnumerable <HitInfo <V> > Raycast(RayDescription ray) { List <HitInfo <V> > hits = new List <HitInfo <V> >(); if (mesh.Topology != Topology.Triangles) { return(hits); } Ray3D r = new Ray3D(ray.Origin, ray.Direction); for (int i = 0; i < mesh.Indices.Length / 3; i++) { 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 t; float3 baricenter; if (tri.Intersect(r, out t, out baricenter)) { if (t >= ray.MinT && t < ray.MaxT) { hits.Add(new HitInfo <V> { T = t, Attribute = v1.Mul(baricenter.x).Add(v2.Mul(baricenter.y)).Add(v3.Mul(baricenter.z)) }); } } } hits.Sort((h1, h2) => h1.T.CompareTo(h2.T)); return(hits); }
/// <summary> /// Performs a trace of a ray through the scene. The payload object will be updated in events OnAnyHit and OnClosestHit. /// </summary> public void Trace(Scene <A> scene, RayDescription ray, ref P payload) { Scene <A> .Visual?closestVisual = null; A? closestAttribute = null; float closestDistance = ray.MaxT; bool stopped = false; InternalRaycastingContext context = new InternalRaycastingContext { GlobalRay = ray, GeometryIndex = 0 }; foreach (var v in scene.instances) { context.FromGeometryToWorld = v.Transform; context.FromWorldToGeometry = inverse(v.Transform); context.LocalRay = ray.Transform(context.FromWorldToGeometry); foreach (var hitInfo in v.Geometry.Raycast(context.LocalRay)) { context.CurrentT = hitInfo.T; var result = OnAnyHit == null ? HitResult.CheckClosest : OnAnyHit(context, hitInfo.Attribute, ref payload); if ((result & HitResult.CheckClosest) == HitResult.CheckClosest) { // Check current attribute with closest one. if (closestDistance > hitInfo.T) { closestDistance = hitInfo.T; closestVisual = v; closestAttribute = hitInfo.Attribute; } } stopped |= (result & HitResult.Stop) == HitResult.Stop; if (stopped) { break; } } if (stopped) { break; } context.GeometryIndex++; } if (closestVisual.HasValue && OnClosestHit != null) { context.CurrentT = closestDistance; context.FromGeometryToWorld = closestVisual.Value.Transform; context.FromWorldToGeometry = inverse(closestVisual.Value.Transform); context.LocalRay = ray.Transform(context.FromWorldToGeometry); OnClosestHit(context, closestAttribute.Value, ref payload); } if (!closestVisual.HasValue && OnMiss != null) { OnMiss(context, ref payload); } }
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; } }