Ejemplo n.º 1
0
            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
                           }
                }
                ;
            }
        }
Ejemplo n.º 2
0
 public IEnumerable <HitInfo <T> > Raycast(RayDescription ray)
 {
     return(geometry.Raycast(ray)
            .Select(h => new HitInfo <T> {
         T = h.T, Attribute = transform(h.Attribute)
     }));
 }
Ejemplo n.º 3
0
            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
                           }
                }
                ;
            }
        }
Ejemplo n.º 4
0
            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;
                    }
                }
            }
Ejemplo n.º 5
0
            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);
            }
Ejemplo n.º 6
0
        /// <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);
            }
        }
Ejemplo n.º 7
0
            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;
                }
            }