示例#1
0
文件: TestRay3F.cs 项目: Joxx0r/ATF
        private void TestToStringWithCulture(CultureInfo culture)
        {
            CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = culture;
            try
            {
                string listSeparator = culture.TextInfo.ListSeparator;
                string decimalSeparator = culture.NumberFormat.NumberDecimalSeparator;
                var o = new Ray3F(new Vec3F(1.1f, 2.2f, 3.3f), new Vec3F(4.4f, 5.5f, 6.6f));

                string s = o.ToString(null, null);
                TestToStringResults(o, s, listSeparator, decimalSeparator);

                string s2 = o.ToString();
                Assert.AreEqual(s, s2);

                s = o.ToString("G", culture);
                TestToStringResults(o, s, listSeparator, decimalSeparator);

                s = o.ToString("R", culture);
                TestToStringResults(o, s, listSeparator, decimalSeparator);
            }
            finally
            {
                Thread.CurrentThread.CurrentCulture = originalCulture;
            }
        }
示例#2
0
文件: TestRay3F.cs 项目: Joxx0r/ATF
 private void TestToStringResults(Ray3F o, string s, string listSeparator, string decimalSeparator)
 {
     string[] results = s.Split(new[] { listSeparator }, StringSplitOptions.RemoveEmptyEntries);
     Assert.AreEqual(results.Length, 6);
     foreach (string oneFloatString in results)
         Assert.True(oneFloatString.Contains(decimalSeparator));
     Assert.AreEqual(float.Parse(results[0]), o.Origin.X);
     Assert.AreEqual(float.Parse(results[1]), o.Origin.Y);
     Assert.AreEqual(float.Parse(results[2]), o.Origin.Z);
     Assert.AreEqual(float.Parse(results[3]), o.Direction.X);
     Assert.AreEqual(float.Parse(results[4]), o.Direction.Y);
     Assert.AreEqual(float.Parse(results[5]), o.Direction.Z);
 }
示例#3
0
        /// <summary>
        /// Tests if a specified ray intersects this sphere</summary>
        /// <param name="ray">The ray, with an origin and unit-length direction. Only intersections in
        /// front of the ray count.</param>
        /// <param name="x">The intersection point, if there was an intersection</param>
        /// <returns>True iff ray intersects this sphere</returns>
        /// <remarks>Algorithm is from _Real-Time Rendering_, p. 299</remarks>
        public bool Intersects(Ray3F ray, out Vec3F x)
        {
            // vector from ray's origin to sphere's center
            Vec3F oToC = Center - ray.Origin;

            // 'd' is the distance from the ray's origin to the nearest point on the ray to Center.
            // Assumes that Direction has unit length.
            float d = Vec3F.Dot(oToC, ray.Direction);

            // distToCenterSquared is the distance from ray's origin to Center, squared.
            float distToCenterSquared = oToC.LengthSquared;
            float radiusSquared       = Radius * Radius;

            // if the sphere is behind the ray and the ray's origin is outside the sphere...
            if (d < 0 && distToCenterSquared > radiusSquared)
            {
                x = new Vec3F();
                return(false);
            }

            // 'm' is the distance from the ray to the center. Pythagorean's theorem.
            float mSquared = distToCenterSquared - d * d;

            if (mSquared > radiusSquared)
            {
                x = new Vec3F();
                return(false);
            }

            // 'q' is the distance from the first intersection point to the nearest point
            //  on the ray to Center. Pythagorean's theorem.
            float q = (float)Math.Sqrt(radiusSquared - mSquared);

            // 't' is the distance along 'ray' to the point of first intersection.
            float t;

            if (distToCenterSquared > radiusSquared)
            {
                // ray's origin is outside the sphere.
                t = d - q;
            }
            else
            {
                // ray's origin is inside the sphere.
                t = d + q;
            }

            // the point of intersection is ray's origin plus distance along ray's direction
            x = ray.Origin + t * ray.Direction;
            return(true);
        }
示例#4
0
        public HitRegion Pick(Matrix4F world, Matrix4F view, Ray3F rayL, Ray3F rayV, float s)
        {
            m_hitRegion = HitRegion.None;
            m_hitRayV = rayV;

            m_hitMatrix.Set(world);
            m_hitWorldView = world * view;
            
            float sl = s * SquareLength;
           

            // test xy square.            
            Vec3F p1 = new Vec3F(0, 0, 0);
            Vec3F p2 = new Vec3F(sl, 0, 0);
            Vec3F p3 = new Vec3F(sl, sl, 0);
            Vec3F p4 = new Vec3F(0, sl, 0);
            Plane3F plane = new Plane3F(p1, p2, p3);
            Vec3F p;
            if (rayL.IntersectPlane(plane, out p))
            {
                // test point in 2d rectangle.
                if (p.X > p1.X && p.X < p2.X
                    && p.Y > p1.Y && p.Y < p4.Y)
                {
                    m_hitRegion = HitRegion.XYSquare;
                    return m_hitRegion;
                }

            }

            // test xz square
            p1 = new Vec3F(0, 0, 0);
            p2 = new Vec3F(sl, 0, 0);
            p3 = new Vec3F(sl, 0, sl);
            p4 = new Vec3F(0, 0, sl);
            plane = new Plane3F(p1, p2, p3);
            if (rayL.IntersectPlane(plane, out p))
            {
                // test point in 2d rectangle.
                if (p.X > p1.X && p.X < p2.X
                    && p.Z > p1.Z && p.Z < p4.Z)
                {
                    m_hitRegion = HitRegion.XZSquare;
                    return m_hitRegion;
                }

            }


            // test yz square
            p1 = new Vec3F(0, 0, 0);
            p2 = new Vec3F(0, 0, sl);
            p3 = new Vec3F(0, sl, sl);
            p4 = new Vec3F(0, sl, 0);
            plane = new Plane3F(p1, p2, p3);
            if (rayL.IntersectPlane(plane, out p))
            {
                // test point in 2d rectangle.
                if (p.Z > p1.Z && p.Z < p2.Z
                    && p.Y > p1.Z && p.Y < p4.Y)
                {
                    m_hitRegion = HitRegion.YZSquare;
                    return m_hitRegion;
                }

            }

            Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f);
            Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f);
            AABB box = new AABB(min, max);
            Matrix4F boxScale = new Matrix4F();
            Matrix4F boxTrans = new Matrix4F();
            Matrix4F BoxMtrx = new Matrix4F();

            // X axis
            boxScale.Scale(new Vec3F(s, s * br, s * br));
            boxTrans.Translation = new Vec3F(s / 2, 0, 0);
            BoxMtrx = boxScale * boxTrans;

            Ray3F ray = rayL;
            BoxMtrx.Invert(BoxMtrx);
            ray.Transform(BoxMtrx);            
            if (box.Intersect(ray))
            {
                m_hitRegion = HitRegion.XAxis;
                return m_hitRegion;
            }

            // y axis
            boxScale.Scale(new Vec3F(s * br, s, s * br));
            boxTrans.Translation = new Vec3F(0, s / 2, 0);
            BoxMtrx = boxScale * boxTrans;
            ray = rayL;
            BoxMtrx.Invert(BoxMtrx);
            ray.Transform(BoxMtrx);
            if (box.Intersect(ray))
            {
                m_hitRegion = HitRegion.YAxis;
                return m_hitRegion;
            }

            // z axis
            boxScale.Scale(new Vec3F(s * br, s * br, s));
            boxTrans.Translation = new Vec3F(0, 0, s / 2);
            BoxMtrx = boxScale * boxTrans;

            ray = rayL;
            BoxMtrx.Invert(BoxMtrx);
            ray.Transform(BoxMtrx);
            if (box.Intersect(ray))
            {
                m_hitRegion = HitRegion.ZAxis;
            }

            return m_hitRegion;
        }
示例#5
0
        public Vec3F OnDragging(Ray3F rayV)
        {
            if (m_hitRegion == HitRegion.None)
                return Vec3F.ZeroVector;


            Vec3F xLocal = m_hitMatrix.XAxis;
            Vec3F yLocal = m_hitMatrix.YAxis;
            Vec3F zLocal = m_hitMatrix.ZAxis;

            Vec3F xAxis = m_hitWorldView.XAxis;
            Vec3F yAxis = m_hitWorldView.YAxis;
            Vec3F zAxis = m_hitWorldView.ZAxis;
            Vec3F origin = m_hitWorldView.Translation;

            Vec3F translate;
            float a1, a2;
            switch (m_hitRegion)
            {
                case HitRegion.XAxis:
                    {
                        a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, yAxis));
                        a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, zAxis));
                        Vec3F axis = (a1 > a2 ? yAxis : zAxis);
                        Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        float dragAmount = Vec3F.Dot((p1 - p0), xAxis);
                        translate = dragAmount * xLocal;
                    }

                    break;
                case HitRegion.YAxis:
                    {
                        a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, zAxis));
                        a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, xAxis));
                        Vec3F axis = (a1 > a2 ? zAxis : xAxis);
                        Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        float dragAmount = Vec3F.Dot((p1 - p0), yAxis);
                        translate = dragAmount * yLocal;
                    }
                    break;
                case HitRegion.ZAxis:
                    {
                        a1 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, xAxis));
                        a2 = Math.Abs(Vec3F.Dot(m_hitRayV.Direction, yAxis));
                        Vec3F axis = (a1 > a2 ? xAxis : yAxis);
                        Vec3F p0 = m_hitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin));
                        float dragAmount = Vec3F.Dot((p1 - p0), zAxis);
                        translate = dragAmount * zLocal;
                    }
                    break;
                case HitRegion.XYSquare:
                    {
                        Vec3F p0 = m_hitRayV.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin));
                        Vec3F p1 = rayV.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin));
                        Vec3F deltaLocal = p1 - p0;
                        float dragX = Vec3F.Dot(xAxis, deltaLocal);
                        float dragY = Vec3F.Dot(yAxis, deltaLocal);
                        translate = dragX * xLocal + dragY * yLocal;
                    }
                    break;
                case HitRegion.YZSquare:
                    {
                        Vec3F p0 = m_hitRayV.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin));
                        Vec3F p1 = rayV.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin));
                        Vec3F deltaLocal = p1 - p0;
                        float dragY = Vec3F.Dot(yAxis, deltaLocal);
                        float dragZ = Vec3F.Dot(zAxis, deltaLocal);
                        translate = dragY * yLocal + dragZ * zLocal;
                    }
                    break;
                case HitRegion.XZSquare:
                    {
                        Vec3F p0 = m_hitRayV.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin));
                        Vec3F p1 = rayV.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin));
                        Vec3F deltaLocal = p1 - p0;
                        float dragX = Vec3F.Dot(xAxis, deltaLocal);
                        float dragZ = Vec3F.Dot(zAxis, deltaLocal);
                        translate = dragX * xLocal + dragZ * zLocal;

                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return translate;
        }
示例#6
0
        public static HitRecord[] RayPick(Matrix4F viewxform, Matrix4F projxfrom, Ray3F rayW, bool skipSelected)
        {
            HitRecord* nativeHits = null;
            int count;

            fixed (float* ptr1 = &viewxform.M11, ptr2 = &projxfrom.M11)
            {
                NativeRayPick(
                ptr1,
                ptr2,
                &rayW,
                skipSelected,
                &nativeHits,
                out count);                
            }
            
            var objects = new List<HitRecord>();

            for (int k = 0; k < count; k++)
            {                
                objects.Add(*nativeHits);                
                nativeHits++;
            }
            return objects.ToArray();

        }
示例#7
0
        public static bool RayPick(Matrix4F viewxform, Matrix4F projxfrom, Ray3F rayW, bool skipSelected, out HitRecord hit)
        {
            HitRecord* nativeHits = null;
            int count;

            //bool skipSelected,
            fixed (float* ptr1 = &viewxform.M11, ptr2 = &projxfrom.M11)
            {
                NativeRayPick(
                ptr1,
                ptr2,
                &rayW,
                skipSelected,
                &nativeHits,
                out count);
            }

            if(count > 0)
            {
                hit = *nativeHits;
            }
            else
            {
                hit = new HitRecord();
            }
           
            return count > 0;

        }
示例#8
0
文件: Box.cs 项目: zparr/ATF
        /// <summary>
        /// Tests if specified ray intersects the box</summary>
        /// <param name="ray">The ray</param>
        /// <returns>True iff ray intersects box</returns>
        public bool Intersects(Ray3F ray)
        {
            // http://www.gametutorials.com/gtstore/pc-429-9-ray-and-aabb-collision.aspx
            // Compute the ray delta
            Vec3F rayDelta = ray.Direction * 100000f;

            // First we check to see if the origin of the ray is
            // inside the AABB.  If it is, the ray intersects the AABB so
            // we'll return true.  We start by assuming the ray origin is
            // inside the AABB
            bool inside = true;

            // This stores the distance from either the min or max (x,y,z) to the ray's
            // origin (x,y,z) respectively, divided by the length of the ray.  The largest
            // value has the delta time of a possible intersection.
            float xt, yt, zt;

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.X < Min.X)
            {
                xt = Min.X - ray.Origin.X;

                if (xt > rayDelta.X) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                xt    /= rayDelta.X;
                inside = false;
            }
            else if (ray.Origin.X > Max.X)
            {
                xt = Max.X - ray.Origin.X;

                if (xt < rayDelta.X) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                xt    /= rayDelta.X;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the x component of the ray
                // origin is in between, the AABB's left and right side (which reside in the yz plane),
                // we know we don't have to test those sides so we set this to a negative value.
                xt = -1.0f;
            }

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.Y < Min.Y)
            {
                yt = Min.Y - ray.Origin.Y;

                if (yt > rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                yt    /= rayDelta.Y;
                inside = false;
            }
            else if (ray.Origin.Y > Max.Y)
            {
                yt = Max.Y - ray.Origin.Y;

                if (yt < rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                yt    /= rayDelta.Y;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the y component of the ray
                // origin is in between, the AABB's top and bottom side (which reside in the xz plane),
                // we know we don't have to test those sides so we set this to a negative value.
                yt = -1.0f;
            }

            if (ray.Origin.Z < Min.Z)
            {
                zt = Min.Z - ray.Origin.Z;

                if (zt > rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                zt    /= rayDelta.Z;
                inside = false;
            }
            else if (ray.Origin.Z > Max.Z)
            {
                zt = Max.Z - ray.Origin.Z;

                if (zt < rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection
                {
                    return(false);
                }

                zt    /= rayDelta.Z;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the z component of the ray
                // origin is in between, the AABB's front and back side (which reside in the xy plane),
                // we know we don't have to test those sides so we set this to a negative value.
                zt = -1.0f;
            }

            // If the origin inside the AABB
            if (inside)
            {
                return(true); // The ray intersects the AABB
            }
            // Otherwise we have some checking to do...

            // We want to test the AABB planes with largest value out of xt, yt, and zt.  So
            // first we determine which value is the largest.

            float t = xt;

            if (yt > t)
            {
                t = yt;
            }

            if (zt > t)
            {
                t = zt;
            }

            // **NOTE** Normally comparing two floating point numbers won't necessarily work, however,
            //            since we set to explicitly to equal either xt, yt, or zt above, the equality test
            //            will pass

            if (t == xt) // If the ray intersects with the AABB's YZ plane
            {
                // Compute intersection values
                float y = ray.Origin.Y + rayDelta.Y * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (y < Min.Y || y > Max.Y)
                {
                    return(false);
                }
                else if (z < Min.Z || z > Max.Z)
                {
                    return(false);
                }
            }
            else if (t == yt) // Intersects with the XZ plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                {
                    return(false);
                }
                else if (z < Min.Z || z > Max.Z)
                {
                    return(false);
                }
            }
            else // Intersects with the XY plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float y = ray.Origin.Y + rayDelta.Y * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                {
                    return(false);
                }
                else if (y < Min.Y || y > Max.Y)
                {
                    return(false);
                }
            }

            // The ray intersects the AABB
            return(true);
        }
示例#9
0
文件: AABB.cs 项目: ldh9451/XLE
 public bool Intersect(Ray3F r)
 {
     float tmin;
     float tmax;
     Vec3F pos;
     Vec3F norm;
     bool result = Intersect(r, out tmin,out tmax, out pos, out norm);
     return result;
 }
示例#10
0
 /// <summary>
 /// compute ray in  given space starting from 
 /// screen space x,y.        
 /// The space of the computed ray depends on the value of mtrx:
 ///               world * view * projection // ray in local space (object space).
 ///               view * projection  // ray in world space.
 ///               projection   // ray in view space.        
 /// </summary>        
 public Ray3F GetRay(Point scrPt, Matrix4F mtrx)
 {
     Vec3F min = Unproject(new Vec3F(scrPt.X, scrPt.Y, 0), mtrx);
     Vec3F max = Unproject(new Vec3F(scrPt.X, scrPt.Y, 1), mtrx);
     Vec3F dir = Vec3F.Normalize(max - min);
     Ray3F ray = new Ray3F(min, dir);
     return ray;
 }
示例#11
0
 /// <summary>
 /// compute ray in world space starting from 
 /// screen space x,y.
 /// </summary>        
 public Ray3F GetWorldRay(Point scrPt)
 {
     Matrix4F vp = Camera.ViewMatrix * Camera.ProjectionMatrix;
     Vec3F min = Unproject(new Vec3F(scrPt.X, scrPt.Y, 0), vp);
     Vec3F max = Unproject(new Vec3F(scrPt.X, scrPt.Y, 1), vp);
     Vec3F dir = Vec3F.Normalize(max - min);
     Ray3F ray = new Ray3F(min, dir);
     return ray;
 }
示例#12
0
 public virtual bool Pick(ViewControl vc, Point scrPt)
 {
     Matrix4F normWorld = GetManipulatorMatrix();
     if (normWorld == null) return false;
     HitRayV = vc.GetRay(scrPt, vc.Camera.ProjectionMatrix);
     HitMatrix.Set(normWorld);
     return true;
 }
        private bool CalculateTerrainIntersection(ViewControl vc, Ray3F ray, GUILayer.IntersectionTestSceneWrapper testScene, out Vec3F result)
        {
            var nativeVC = vc as NativeDesignControl;
            if (nativeVC == null) { result = Vec3F.ZeroVector; return false; }

            var pick = XLEBridgeUtils.Picking.RayPick(nativeVC.Adapter, ray, XLEBridgeUtils.Picking.Flags.Terrain);
            if (pick != null && pick.Length > 0)
            {
                result = pick[0].hitPt;
                return true;
            }

            result = Vec3F.ZeroVector;
            return false;
        }
示例#14
0
        /// <summary>
        /// Creates a ray originating at the given normalized window coordinates and pointing into
        /// the screen, along -Z axis. Normalized window coordinates are in the range [-0.5,0.5]
        /// with +x pointing to the right and +y pointing up.</summary>
        /// <param name="x">The x normalized window coordinate</param>
        /// <param name="y">The y normalized window coordinate</param>
        /// <returns>The ray</returns>
        public Ray3F CreateRay(float x, float y)
        {
            float height, width;

            // Setup ray
            Ray3F ray = new Ray3F();

            // World height on origin's z value
            if (Frustum.IsOrtho)
            {
                width = Frustum.Right - Frustum.Left;
                height = Frustum.Top - Frustum.Bottom;
                ray.Origin = new Vec3F(x * width, y * height, -NearZ);
                ray.Direction = new Vec3F(0, 0, -1);
            }
            else
            {
                height = Frustum.Far * (float)Math.Tan(Frustum.FovY / 2.0f) * 2.0f;
                width = Frustum.Far * (float)Math.Tan(Frustum.FovX / 2.0f) * 2.0f;

                ray.Origin = new Vec3F(0, 0, 0);
                ray.Direction = new Vec3F(x * width, y * height, -Frustum.Far);
                float l = ray.Direction.Length;
                ray.Direction = ray.Direction / l;
            }

            return ray;
        }
示例#15
0
        private bool CalculateTerrainIntersection(ViewControl vc, Ray3F ray, GUILayer.IntersectionTestSceneWrapper testScene, out Vec3F result)
        {
            var pick = XLEBridgeUtils.Picking.RayPick(vc, ray, XLEBridgeUtils.Picking.Flags.Terrain);
            if (pick != null && pick.Length > 0)
            {
                result = pick[0].hitPt;
                return true;
            }

            result = new Vec3F(0.0f, 0.0f, 0.0f);
            return false;
        }
        /// <summary>
        /// Projects the ghost</summary>
        private void ProjectGhost(DomNode ghost, 
            Ray3F rayw,
            HitRecord? hit)
        {

            ITransformable xformnode = ghost.Cast<ITransformable>();
            IBoundable bnode  = ghost.As<IBoundable>();
            AABB box = bnode.BoundingBox;
            
            Vec3F pt;
            if (hit.HasValue && hit.Value.hasNormal)
            {
                Vec3F rad = box.Radius;
                Vec3F norm = hit.Value.normal;
                Vec3F absNorm = Vec3F.Abs(norm);
                Vec3F offset = Vec3F.ZeroVector;
                
                if (absNorm.X > absNorm.Y)
                {
                    if (absNorm.X > absNorm.Z)
                        offset.X = norm.X > 0 ? rad.X : -rad.X;
                    else
                        offset.Z = norm.Z > 0 ? rad.Z : -rad.Z;                        
                }
                else
                {
                    if (absNorm.Y > absNorm.Z)
                        offset.Y = norm.Y > 0 ? rad.Y : -rad.Y;
                    else
                        offset.Z = norm.Z > 0 ? rad.Z : -rad.Z;                        
                        
                }                
                Vec3F localCenter = box.Center - xformnode.Translation;
                pt = hit.Value.hitPt + (offset - localCenter);
            }
            else
            {
                float offset = 6.0f * box.Radius.Length;
                pt = rayw.Origin + offset * rayw.Direction;
            }
                                          
            if (ViewType == ViewTypes.Front)
                pt.Z = 0.0f;
            else if (ViewType == ViewTypes.Top)
                pt.Y = 0.0f;
            else if (ViewType == ViewTypes.Left)
                pt.X = 0.0f;           
            xformnode.Translation = pt;

        }
示例#17
0
        public bool RayPick(Ray3F rayw, out RayPickRetVal retval)
        {
            INativeObject nobj = this.As<INativeObject>();
            IntPtr retvalPtr = IntPtr.Zero;
            IntPtr rayptr = new IntPtr(&rayw);
            nobj.InvokeFunction("RayPick", rayptr, out retvalPtr);
            if (retvalPtr != IntPtr.Zero)
                retval = *(RayPickRetVal*)retvalPtr;
            else
                retval = new RayPickRetVal();

            return retval.picked;
        }
示例#18
0
文件: AABB.cs 项目: ldh9451/XLE
        public bool Intersect(Ray3F r, 
            out float out_tmin,
            out float out_tmax,
            out Vec3F out_pos, 
            out Vec3F out_nor)
        {
            out_pos = Vec3F.ZeroVector;
            out_nor = Vec3F.ZeroVector;
            out_tmin = 0.0f;
            out_tmax = 0.0f;

            Vec3F p = r.Origin;
            Vec3F d = r.Direction;
            float tmin = float.MinValue;
            float tmax = float.MaxValue;

            // check vs. all three 'slabs' of the aabb
            for (int i = 0; i < 3; ++i)
            {
                if (Math.Abs(d[i]) < float.Epsilon)
                {   // ray is parallel to slab, no hit if origin not within slab
                    if (p[i] < Min[i] || p[i] > Max[i])
                    {
                        return false;
                    }
                }
                else
                {
                    // compute intersection t values of ray with near and far plane of slab
                    float ood = 1.0f / d[i];
                    float t1 = (Min[i] - p[i]) * ood;
                    float t2 = (Max[i] - p[i]) * ood;
                    tmin = Math.Max(tmin, Math.Min(t1, t2));
                    tmax = Math.Min(tmax, Math.Max(t1, t2));

                    // exit with no collision as soon as slab intersection becomes empty
                    if (tmin > tmax)
                    {
                        return false;
                    }
                }
            }

            if (tmax < 0.0f)
            {
                // entire bounding box is behind us
                return false;
            }
            else if (tmin < 0.0f)
            {
                // we are inside the bounding box
                out_tmin = 0.0f;
                out_tmax = tmax;
                out_pos = p + d * tmax;
                out_nor = Vec3F.Normalize(Center - out_pos); // use 'sphere' type normal calculation to approximate.
                return true;
            }
            else
            {
                // ray intersects all 3 slabs. return point and normal of intersection
                out_tmin = tmin;
                out_pos = p + d * tmin;
                out_nor = Vec3F.Normalize(Center - out_pos); // use 'sphere' type normal calculation to approximate.
                return true;
            }
        }
示例#19
0
文件: Box.cs 项目: vincenthamm/ATF
        /// <summary>
        /// Tests if specified ray intersects the box</summary>
        /// <param name="ray">The ray</param>
        /// <returns>True iff ray intersects box</returns>
        public bool Intersects(Ray3F ray)
        {
            // http://www.gametutorials.com/gtstore/pc-429-9-ray-and-aabb-collision.aspx
            // Compute the ray delta
            Vec3F rayDelta = ray.Direction * 100000f;

            // First we check to see if the origin of the ray is 
            // inside the AABB.  If it is, the ray intersects the AABB so 
            // we'll return true.  We start by assuming the ray origin is 
            // inside the AABB
            bool inside = true;

            // This stores the distance from either the min or max (x,y,z) to the ray's
            // origin (x,y,z) respectively, divided by the length of the ray.  The largest
            // value has the delta time of a possible intersection.
            float xt, yt, zt;

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.X < Min.X)
            {
                xt = Min.X - ray.Origin.X;

                if (xt > rayDelta.X) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                xt /= rayDelta.X;
                inside = false;
            }
            else if (ray.Origin.X > Max.X)
            {
                xt = Max.X - ray.Origin.X;

                if (xt < rayDelta.X) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                xt /= rayDelta.X;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the x component of the ray
                // origin is in between, the AABB's left and right side (which reside in the yz plane), 
                // we know we don't have to test those sides so we set this to a negative value.
                xt = -1.0f;
            }

            // Test the X component of the ray's origin to see if we are inside or not
            if (ray.Origin.Y < Min.Y)
            {
                yt = Min.Y - ray.Origin.Y;

                if (yt > rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                yt /= rayDelta.Y;
                inside = false;
            }
            else if (ray.Origin.Y > Max.Y)
            {
                yt = Max.Y - ray.Origin.Y;

                if (yt < rayDelta.Y) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                yt /= rayDelta.Y;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the y component of the ray
                // origin is in between, the AABB's top and bottom side (which reside in the xz plane), 
                // we know we don't have to test those sides so we set this to a negative value.
                yt = -1.0f;
            }

            if (ray.Origin.Z < Min.Z)
            {
                zt = Min.Z - ray.Origin.Z;

                if (zt > rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                zt /= rayDelta.Z;
                inside = false;
            }
            else if (ray.Origin.Z > Max.Z)
            {
                zt = Max.Z - ray.Origin.Z;

                if (zt < rayDelta.Z) // If the ray is moving away from the AABB, there is no intersection 
                    return false;

                zt /= rayDelta.Z;
                inside = false;
            }
            else
            {
                // Later on we use the "xt", "yt", and "zt" variables to determine which plane (either
                // xy, xz, or yz) we may collide with.  Since the z component of the ray
                // origin is in between, the AABB's front and back side (which reside in the xy plane), 
                // we know we don't have to test those sides so we set this to a negative value.
                zt = -1.0f;
            }

            // If the origin inside the AABB
            if (inside)
                return true; // The ray intersects the AABB

            // Otherwise we have some checking to do...

            // We want to test the AABB planes with largest value out of xt, yt, and zt.  So
            // first we determine which value is the largest.

            float t = xt;

            if (yt > t)
                t = yt;

            if (zt > t)
                t = zt;

            // **NOTE** Normally comparing two floating point numbers won't necessarily work, however,
            //            since we set to explicitly to equal either xt, yt, or zt above, the equality test
            //            will pass

            if (t == xt) // If the ray intersects with the AABB's YZ plane
            {
                // Compute intersection values
                float y = ray.Origin.Y + rayDelta.Y * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (y < Min.Y || y > Max.Y)
                    return false;
                else if (z < Min.Z || z > Max.Z)
                    return false;
            }
            else if (t == yt) // Intersects with the XZ plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float z = ray.Origin.Z + rayDelta.Z * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                    return false;
                else if (z < Min.Z || z > Max.Z)
                    return false;
            }
            else // Intersects with the XY plane
            {
                // Compute intersection values
                float x = ray.Origin.X + rayDelta.X * t;
                float y = ray.Origin.Y + rayDelta.Y * t;

                // Test to see if collision takes place within the bounds of the AABB
                if (x < Min.X || x > Max.X)
                    return false;
                else if (y < Min.Y || y > Max.Y)
                    return false;
            }

            // The ray intersects the AABB
            return true;
        }
示例#20
0
        private static float CalcAngle(Vec3F origin, Plane3F plane, Ray3F ray0, Ray3F ray1, float snapAngle)
        {
            float theta = 0;            
            Vec3F p0;
            Vec3F p1;

            if( ray0.IntersectPlane(plane, out p0)
                && ray1.IntersectPlane(plane, out p1))
            {
                Vec3F v0 = Vec3F.Normalize(p0 - origin);
                Vec3F v1 = Vec3F.Normalize(p1 - origin);
                theta = CalcAngle(v0, v1, plane.Normal, snapAngle);
            }
            return theta;
        }
示例#21
0
        /// <summary>
        /// Tests if a specified ray intersects this sphere</summary>
        /// <param name="ray">The ray, with an origin and unit-length direction. Only intersections in
        /// front of the ray count.</param>
        /// <param name="x">The intersection point, if there was an intersection</param>
        /// <returns>True iff ray intersects this sphere</returns>
        /// <remarks>Algorithm is from _Real-Time Rendering_, p. 299</remarks>
        public bool Intersects(Ray3F ray, out Vec3F x)
        {
            // vector from ray's origin to sphere's center
            Vec3F oToC = Center - ray.Origin;

            // 'd' is the distance from the ray's origin to the nearest point on the ray to Center.
            // Assumes that Direction has unit length.
            float d = Vec3F.Dot(oToC, ray.Direction);

            // distToCenterSquared is the distance from ray's origin to Center, squared.
            float distToCenterSquared = oToC.LengthSquared;
            float radiusSquared = Radius * Radius;

            // if the sphere is behind the ray and the ray's origin is outside the sphere...
            if (d < 0 && distToCenterSquared > radiusSquared)
            {
                x = new Vec3F();
                return false;
            }

            // 'm' is the distance from the ray to the center. Pythagorean's theorem.
            float mSquared = distToCenterSquared - d * d;
            if (mSquared > radiusSquared)
            {
                x = new Vec3F();
                return false;
            }

            // 'q' is the distance from the first intersection point to the nearest point
            //  on the ray to Center. Pythagorean's theorem.
            float q = (float)Math.Sqrt(radiusSquared - mSquared);

            // 't' is the distance along 'ray' to the point of first intersection.
            float t;
            if (distToCenterSquared > radiusSquared)
            {
                // ray's origin is outside the sphere.
                t = d - q;
            }
            else
            {
                // ray's origin is inside the sphere.
                t = d + q;
            }

            // the point of intersection is ray's origin plus distance along ray's direction
            x = ray.Origin + t * ray.Direction;
            return true;
        }