예제 #1
0
        public static bool Intersect(BoundingSphere a, Ray b, out object intersection)
        {
            RayIntersection d   = new RayIntersection();
            bool            hit = Ray.Intersects(b, a, out d.Distance);

            intersection = d;
            return(hit);
        }
예제 #2
0
        public static bool Intersect(Bounding.Box a, Bounding.Line b, out object intersection)
        {
            intersection = null;

            Vector3         v    = b.P1 - b.P0;
            RayIntersection rOut = new RayIntersection();

            return(Intersect(a, new Ray(b.P0, Vector3.Normalize(v)), out rOut) && rOut.Distance < v.Length());
        }
예제 #3
0
        // ----------------------------------------------------------------------------------------------
        // -- Plane -------------------------------------------------------------------------------------
        // ----------------------------------------------------------------------------------------------

        public static bool Intersect(Plane a, Ray b, out object intersection)
        {
            float dist;
            bool  i = Ray.Intersects(b, a, out dist);

            intersection = new RayIntersection {
                Distance = dist
            };
            return(i);
        }
예제 #4
0
        public static bool Intersect(BoundingBox a, Ray b, out object intersection)
        {
            float dist;
            bool  i = BoundingBox.Intersects(a, b, out dist);

            intersection = new RayIntersection {
                Distance = dist
            };
            return(i);
        }
예제 #5
0
        public static bool Intersect(RectangleF a, Ray b, out object intersection)
        {
            intersection = null;
            float d;
            bool  hit = BoundingBox.Intersects(new BoundingBox(new Vector3(a.X, a.Y, -float.MaxValue), new Vector3(a.X + a.Width, a.Y + a.Height, float.MaxValue)), b, out d);

            intersection = new RayIntersection {
                Distance = d
            };
            return(hit);
        }
예제 #6
0
        public static bool Intersect(object a, Ray b, float maxDistance, out RayIntersection rOut)
        {
            var bca = a as Bounding.Chain;

            if (bca != null)
            {
                return(ChainRayIntersect(bca, b, maxDistance, out rOut));
            }
            else
            {
                return(Intersect <RayIntersection>(a, b, out rOut));
            }
        }
예제 #7
0
        // ----------------------------------------------------------------------------------------------
        // -- Point -------------------------------------------------------------------------------------
        // ----------------------------------------------------------------------------------------------

        public static bool Intersect(Vector3 a, Ray b, out object intersection)
        {
            intersection = null;

            Vector3 v  = a - b.Position;
            Vector3 vn = Vector3.Normalize(v);

            if (System.Math.Abs(vn.X - b.Direction.X) < 0.0001f &&
                System.Math.Abs(vn.Y - b.Direction.Y) < 0.0001f &&
                System.Math.Abs(vn.Z - b.Direction.Z) < 0.0001f)
            {
                intersection = new RayIntersection {
                    Distance = v.Length()
                };
                return(true);
            }

            return(false);
        }
예제 #8
0
        // ----------------------------------------------------------------------------------------------
        // -- Box ---------------------------------------------------------------------------------------
        // ----------------------------------------------------------------------------------------------

        public static bool Intersect(Bounding.Box a, Ray b, out object intersection)
        {
            var r = new RayIntersection();

            intersection = r;
            Matrix invTransformation = Matrix.Invert(a.Transformation);
            var    newRay            = new Ray(
                Vector3.TransformCoordinate(b.Position, invTransformation),
                Vector3.Normalize(Vector3.TransformNormal(b.Direction, invTransformation)));

            bool hit = BoundingBox.Intersects(a.LocalBoundingBox, newRay, out r.Distance);

            if (hit)
            {
                var newPos = Vector3.TransformCoordinate(newRay.Position + newRay.Direction * r.Distance,
                                                         a.Transformation);
                r.Distance = (newPos - b.Position).Length();
            }
            return(hit);
        }
예제 #9
0
        public static bool Intersect(Bounding.Cylinder a, Ray b, out object intersection) // CylHeight implemented
        {
            intersection = null;

            // check if ray is positioned inside cylinder
            if (Intersect(a, b.Position, out intersection))
            {
                if (a.SolidRayIntersection)
                {
                    intersection = new RayIntersection {
                        Distance = 0
                    };
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (b.Direction.X == 0 && b.Direction.Y == 0)
            {
                // check horizontal position
                if (Common.Math.ToVector2(a.Position - b.Position).Length() > a.Radius)
                {
                    return(false);
                }

                // we can't use Ray.Intersects(ray, plane) since it also intersects with backsides of planes which we don't want unless SolidRayIntersection is set
                float zPos    = b.Position.Z;
                float floor   = a.Position.Z;
                float ceiling = floor + a.Height;

                if (b.Direction.Z < 0 && zPos > ceiling)
                {
                    intersection = new RayIntersection {
                        Distance = zPos - ceiling
                    };
                    return(true);
                }
                else if (b.Direction.Z > 0 && zPos < floor)
                {
                    intersection = new RayIntersection {
                        Distance = floor - zPos
                    };
                    return(true);
                }
                else if (!a.SolidRayIntersection)
                {
                    return(false);
                }
            }

            // assume normalized ray direction vector
            // Ray: P + t*D
            // Cylinder: O (center), r (Radius)
            // |P + t*D - O| = radius
            // (P + t*D - O)(P + t*D - O) - r^2 = 0
            // A*t^2 + B*t + C = 0
            // with A: (D . D)
            //      B: 2 * ((P - O) . D),
            //      C: (P - O) . (P - O) - r^2 = = |P - O|^2 - r^2
            // t = -B/(2A) +- sqrt(B^2/(4A^2) - C)

            Vector3 cylinderAxis = Vector3.UnitZ;

            Vector3 P = b.Position - Vector3.Dot(cylinderAxis, b.Position) * cylinderAxis;
            Vector3 D = b.Direction - Vector3.Dot(cylinderAxis, b.Direction) * cylinderAxis;
            Vector3 O = a.Position - Vector3.Dot(cylinderAxis, a.Position) * cylinderAxis;

            float A = Vector3.Dot(D, D);
            float B = 2 * Vector3.Dot(P - O, D);
            float C = Vector3.Dot(P - O, P - O) - a.Radius2;

            float x = -B / (2 * A);
            float y = x * x - C / A;

            if (y < 0)
            {
                return(false);   // imaginary roots
            }
            float z = (float)System.Math.Sqrt(y);

            float t1 = x + z;
            float t2 = x - z;

            float minT = float.MaxValue;

            if (t1 < 0)
            {
                if (t2 < 0)
                {
                    return(false);
                }

                minT = t2;
            }
            else
            {
                if (t2 < 0)
                {
                    minT = t1;
                }
                else
                {
                    minT = (float)System.Math.Min(t1, t2);
                }
            }

            // Check that the point is within cylinder vertical limits
            Vector3 Q   = b.Position + minT * b.Direction;
            Vector3 PO  = Q - a.Position;
            Vector3 POp = Vector3.Dot(PO, cylinderAxis) * Vector3.Normalize(cylinderAxis);

            var debug1 = Vector3.Dot(POp, cylinderAxis);
            var debug2 = POp.Length();

            if (Vector3.Dot(POp, cylinderAxis) >= 0 &&  // not below
                POp.Length() <= a.Height)               // not above
            {
                intersection = new RayIntersection {
                    Distance = minT
                };
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #10
0
 public static bool ChainRayIntersect(Bounding.Chain a, Ray b, float maxDistance, out RayIntersection intersection)
 {
     intersection = null;
     foreach (object o in a.Boundings)
     {
         if (!Intersect(o, b, out intersection))
         {
             return(false);
         }
         else if (intersection.Distance > maxDistance)
         {
             return(false);
         }
     }
     return(true);
 }