Beispiel #1
0
        // Missing: SweptSpherePlaneOverlap

        #region SegmentAABoxOverlap
        /// <summary>
        /// Indicates if a segment overlaps an AABox
        /// </summary>
        /// <param name="seg"></param>
        /// <param name="AABox"></param>
        /// <returns>bool</returns>
        public static bool SegmentAABoxOverlap(Segment seg, AABox AABox)
        {
            Vector3 p0 = seg.Origin;
            Vector3 p1 = seg.GetEnd();

            float[] faceOffsets = new float[2];

            // The AABox faces are aligned with the world directions. Loop
            // over the 3 directions and do the two tests.
            for (int iDir = 0; iDir < 3; iDir++)
            {
                int jDir = (iDir + 1) % 3;
                int kDir = (iDir + 2) % 3;

                // one plane goes through the origin, one is offset
                faceOffsets[0] = JiggleUnsafe.Get(AABox.MinPos, iDir);
                faceOffsets[1] = JiggleUnsafe.Get(AABox.MaxPos, iDir);

                for (int iFace = 0; iFace < 2; iFace++)
                {
                    // distance of each point from to the face plane
                    float dist0 = JiggleUnsafe.Get(ref p0, iDir) - faceOffsets[iFace];
                    float dist1 = JiggleUnsafe.Get(ref p1, iDir) - faceOffsets[iFace];
                    float frac  = -1.0f;

                    if (dist0 * dist1 < -JiggleMath.Epsilon)
                    {
                        frac = -dist0 / (dist1 - dist0);
                    }
                    else if (System.Math.Abs(dist0) < JiggleMath.Epsilon)
                    {
                        frac = 0.0f;
                    }
                    else if (System.Math.Abs(dist1) < JiggleMath.Epsilon)
                    {
                        frac = 1.0f;
                    }

                    if (frac >= 0.0f)
                    {
                        //Assert(frac <= 1.0f);
                        Vector3 pt = seg.GetPoint(frac);

                        // check the point is within the face rectangle
                        if ((JiggleUnsafe.Get(ref pt, jDir) > JiggleUnsafe.Get(AABox.MinPos, jDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, jDir) < JiggleUnsafe.Get(AABox.MaxPos, jDir) + JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) > JiggleUnsafe.Get(AABox.MinPos, kDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) < JiggleUnsafe.Get(AABox.MaxPos, kDir) + JiggleMath.Epsilon))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Beispiel #2
0
        public static bool SegmentAABoxOverlap(Segment seg, AABox AABox)
        {
            var p0 = seg.Origin;
            var p1 = seg.GetEnd();

            var faceOffsets = new float[2];


            for (var iDir = 0; iDir < 3; iDir++)
            {
                var jDir = (iDir + 1) % 3;
                var kDir = (iDir + 2) % 3;


                faceOffsets[0] = JiggleUnsafe.Get(AABox.MinPos, iDir);
                faceOffsets[1] = JiggleUnsafe.Get(AABox.MaxPos, iDir);

                for (var iFace = 0; iFace < 2; iFace++)
                {
                    var dist0 = JiggleUnsafe.Get(ref p0, iDir) - faceOffsets[iFace];
                    var dist1 = JiggleUnsafe.Get(ref p1, iDir) - faceOffsets[iFace];
                    var frac  = -1.0f;

                    if (dist0 * dist1 < -JiggleMath.Epsilon)
                    {
                        frac = -dist0 / (dist1 - dist0);
                    }
                    else if (System.Math.Abs(dist0) < JiggleMath.Epsilon)
                    {
                        frac = 0.0f;
                    }
                    else if (System.Math.Abs(dist1) < JiggleMath.Epsilon)
                    {
                        frac = 1.0f;
                    }

                    if (frac >= 0.0f)
                    {
                        var pt = seg.GetPoint(frac);


                        if (JiggleUnsafe.Get(ref pt, jDir) > JiggleUnsafe.Get(AABox.MinPos, jDir) - JiggleMath.Epsilon && JiggleUnsafe.Get(ref pt, jDir) < JiggleUnsafe.Get(AABox.MaxPos, jDir) + JiggleMath.Epsilon && JiggleUnsafe.Get(ref pt, kDir) > JiggleUnsafe.Get(AABox.MinPos, kDir) - JiggleMath.Epsilon && JiggleUnsafe.Get(ref pt, kDir) < JiggleUnsafe.Get(AABox.MaxPos, kDir) + JiggleMath.Epsilon)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// Indicates if a segment overlaps an AABox
        /// </summary>
        /// <param name="seg"></param>
        /// <param name="AABox"></param>
        /// <returns>bool</returns>
        public static bool SegmentAABoxOverlap(Segment seg, AABox AABox)
        {
            Vector3 p0 = seg.Origin;
            Vector3 p1 = seg.GetEnd();

            float[] faceOffsets = new float[2];

            // The AABox faces are aligned with the world directions. Loop
            // over the 3 directions and do the two tests.
            for (int iDir = 0; iDir < 3; iDir++)
            {
                int jDir = (iDir + 1) % 3;
                int kDir = (iDir + 2) % 3;

                // one plane goes through the origin, one is offset
                faceOffsets[0] = JiggleUnsafe.Get(AABox.MinPos, iDir);
                faceOffsets[1] = JiggleUnsafe.Get(AABox.MaxPos, iDir);

                for (int iFace = 0; iFace < 2; iFace++)
                {
                    // distance of each point from to the face plane
                    float dist0 = JiggleUnsafe.Get(ref p0, iDir) - faceOffsets[iFace];
                    float dist1 = JiggleUnsafe.Get(ref p1, iDir) - faceOffsets[iFace];
                    float frac = -1.0f;

                    if (dist0 * dist1 < -JiggleMath.Epsilon)
                        frac = -dist0 / (dist1 - dist0);
                    else if (System.Math.Abs(dist0) < JiggleMath.Epsilon)
                        frac = 0.0f;
                    else if (System.Math.Abs(dist1) < JiggleMath.Epsilon)
                        frac = 1.0f;

                    if (frac >= 0.0f)
                    {
                        //Assert(frac <= 1.0f);
                        Vector3 pt = seg.GetPoint(frac);

                        // check the point is within the face rectangle
                        if ((JiggleUnsafe.Get(ref pt, jDir) > JiggleUnsafe.Get(AABox.MinPos, jDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, jDir) < JiggleUnsafe.Get(AABox.MaxPos, jDir) + JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) > JiggleUnsafe.Get(AABox.MinPos, kDir) - JiggleMath.Epsilon) &&
                            (JiggleUnsafe.Get(ref pt, kDir) < JiggleUnsafe.Get(AABox.MaxPos, kDir) + JiggleMath.Epsilon))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
Beispiel #4
0
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            frac   = 0;
            pos    = Vector3.Zero;
            normal = Vector3.Up;

            if (seg.Delta.Y > -JiggleMath.Epsilon)
            {
                return(false);
            }

            Vector3 normalStart;
            float   heightStart;

            GetHeightAndNormal(out heightStart, out normalStart, seg.Origin);

            if (heightStart < 0.0f)
            {
                return(false);
            }

            Vector3 normalEnd;
            float   heightEnd;
            Vector3 end = seg.GetEnd();

            GetHeightAndNormal(out heightEnd, out normalEnd, end);

            if (heightEnd > 0.0f)
            {
                return(false);
            }

            // start is above, end is below...
            float depthEnd = -heightEnd;

            // normal is the weighted mean of these...
            float weightStart = 1.0f / (JiggleMath.Epsilon + heightStart);
            float weightEnd   = 1.0f / (JiggleMath.Epsilon + depthEnd);

            normal = (normalStart * weightStart + normalEnd * weightEnd) /
                     (weightStart + weightEnd);

            frac = heightStart / (heightStart + depthEnd + JiggleMath.Epsilon);

            pos = seg.GetPoint(frac);

            return(true);
        }
Beispiel #5
0
        public override bool SegmentIntersect(out float fracOut, out CollisionSkin skinOut, out Microsoft.Xna.Framework.Vector3 posOut, out Microsoft.Xna.Framework.Vector3 normalOut, JigLibX.Geometry.Segment seg, CollisionSkinPredicate1 collisionPredicate)
        {
            fracOut = float.MaxValue;
            skinOut = null;
            posOut  = normalOut = Vector3.Zero;

            Vector3 min = seg.GetPoint(0);
            Vector3 tmp = seg.GetEnd();
            Vector3 max;

            Vector3.Max(ref min, ref tmp, out max);
            Vector3.Min(ref min, ref tmp, out min);

            BoundingBox box = new BoundingBox(min, max);
            float       frac;
            Vector3     pos;
            Vector3     normal;

            active_.Clear();
            Extract(min, max, active_);

            int nActive = active_.Count;

            for (int i = 0; i != nActive; ++i)
            {
                CollisionSkin skin = active_[i];
                if (collisionPredicate == null || collisionPredicate.ConsiderSkin(skin))
                {
                    if (BoundingBoxHelper.OverlapTest(ref box, ref skin.WorldBoundingBox))
                    {
                        if (skin.SegmentIntersect(out frac, out pos, out normal, seg))
                        {
                            if (frac >= 0 && frac < fracOut)
                            {
                                fracOut   = frac;
                                skinOut   = skin;
                                posOut    = pos;
                                normalOut = normal;
                            }
                        }
                    }
                }
            }
            return(fracOut <= 1);
        }
Beispiel #6
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal,Segment seg)
        {
            frac = 0;
            pos = Vector3.Zero;
            normal = Vector3.Up;

            //if (seg.Delta.Y > -JiggleMath.Epsilon )
            //    return false;

            Vector3 normalStart;
            float heightStart;

            GetHeightAndNormal(out heightStart, out normalStart,seg.Origin);

            if (heightStart < 0.0f)
                return false;

            Vector3 normalEnd;
            float heightEnd;
            Vector3 end = seg.GetEnd();
            GetHeightAndNormal(out heightEnd, out normalEnd,end);

            if (heightEnd > 0.0f)
                return false;

            // start is above, end is below...
            float depthEnd = -heightEnd;

            // normal is the weighted mean of these...
            float weightStart = 1.0f / (JiggleMath.Epsilon + heightStart);
            float weightEnd = 1.0f / (JiggleMath.Epsilon + depthEnd);

            normal = (normalStart * weightStart + normalEnd * weightEnd) /
              (weightStart + weightEnd);

            frac = heightStart / (heightStart + depthEnd + JiggleMath.Epsilon);

            pos = seg.GetPoint(frac);

            return true;
        }
Beispiel #7
0
        /// <summary>
        /// SegmentTriangleDistanceSq
        /// </summary>
        /// <param name="segT"></param>
        /// <param name="triT0"></param>
        /// <param name="triT1"></param>
        /// <param name="seg"></param>
        /// <param name="triangle"></param>
        /// <returns>float</returns>
        public static float SegmentTriangleDistanceSq(out float segT, out float triT0, out float triT1, Segment seg, Triangle triangle)
        {
            // compare segment to all three edges of the triangle
            float distSq = float.MaxValue;

            if (Intersection.SegmentTriangleIntersection(out segT, out triT0, out triT1, seg, triangle))
            {
                segT = triT0 = triT1 = 0.0f;
                return 0.0f;
            }

            float s, t, u;
            float distEdgeSq;
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin, triangle.Edge0));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = t;
                triT1 = 0.0f;
            }
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin, triangle.Edge1));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = 0.0f;
                triT1 = t;
            }
            distEdgeSq = SegmentSegmentDistanceSq(out s, out t, seg, new Segment(triangle.Origin + triangle.Edge0, triangle.Edge2));
            if (distEdgeSq < distSq)
            {
                distSq = distEdgeSq;
                segT = s;
                triT0 = 1.0f - t;
                triT1 = t;
            }

            // compare segment end points to triangle interior
            float startTriSq = PointTriangleDistanceSq(out t, out u, seg.Origin, triangle);
            if (startTriSq < distSq)
            {
                distSq = startTriSq;
                segT = 0.0f;
                triT0 = t;
                triT1 = u;
            }
            float endTriSq = PointTriangleDistanceSq(out t, out u, seg.GetEnd(), triangle);
            if (endTriSq < distSq)
            {
                distSq = endTriSq;
                segT = 1.0f;
                triT0 = t;
                triT1 = u;
            }
            return distSq;
        }
Beispiel #8
0
        /// <summary>
        /// Every skin must support a ray/segment intersection test -
        /// operates on the new value of the primitives
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            Vector3 segEnd = seg.GetEnd();
            frac = float.MaxValue;

            float thisSegLenRelToOrig = 1.0f;
            Segment segCopy = seg;

            pos = normal = Vector3.Zero;

            for (int prim = primitivesNewWorld.Count; prim-- != 0; )
            {
                float thisFrac;
                Vector3 newPosition = pos;

                if (primitivesNewWorld[prim].SegmentIntersect(out thisFrac, out newPosition, out normal, segCopy))
                {
                    pos = newPosition;
                    frac = thisFrac * thisSegLenRelToOrig;
                    segCopy.Delta *= thisFrac;
                    thisSegLenRelToOrig *= frac;
                }
            }

            //System.Diagnostics.Debug.WriteLineIf(frac <= 1.0f, pos);

            return (frac <= 1.0f);
        }
Beispiel #9
0
 static public void AddSegment(Segment seg, ref BoundingBox bb)
 {
     AddPoint(seg.Origin, ref bb);
     AddPoint(seg.GetEnd(), ref bb);
 }
Beispiel #10
0
 /// <summary>
 /// AddSegment
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="bb"></param>
 public static void AddSegment(Segment seg, ref BoundingBox bb)
 {
     AddPoint(seg.Origin,ref bb);
     AddPoint(seg.GetEnd(), ref bb);
 }
Beispiel #11
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal,Segment seg)
        {
            /* Bug with SegmentIntersect, if the segment >= 1 square, then the code fails.
             * We need to start at seg.Origin, and move to seg.Origin + (dx,dz) until one is below and one is above 0)
             */
            frac = 0;
            pos = Vector3.Zero;
            normal = Vector3.Up;
            Vector3 normalStart = Vector3.Zero;
            float heightStart = 0.0f;
            Vector3 normalEnd;
            float heightEnd;

            Vector3 segPos = Vector3.Zero;
            Vector3 segPosEnd = seg.Origin;
            Vector3 segEnd = seg.GetEnd();
            Vector3 segDirection = seg.Delta;
            segDirection.Y = 0;
            JiggleMath.NormalizeSafe(ref segDirection);
            segDirection.Y = seg.Delta.Y * (segDirection.X / seg.Delta.X); // Scale the Y to be make segDirection a scaler of segDelta, but normalized in the XY plane

            float increment = JiggleMath.Min(dx, dz, float.MaxValue); // Move by the smaller of the two dx/dz values so we dont "jump" over a point ... this could be done better

            GetHeightAndNormal(out heightEnd, out normalEnd, seg.Origin);
            bool done = false;
            while (!done)
            {
                segPos = segPosEnd;
                normalStart = normalEnd;
                heightStart = heightEnd;

                segPosEnd += segDirection * increment;

                if ((((segPos.X - segEnd.X) > 0.0f) != ((segPosEnd.X - segEnd.X) > 0.0f)) // We have moved onto the other side of the seg end in X
                    || (((segPos.Z - segEnd.Z) > 0.0f) != ((segPosEnd.Z - segEnd.Z) > 0.0f))) // We have moved onto the other side of the seg end in Z
                {
                    segPosEnd = segEnd;
                }

                GetHeightAndNormal(out heightEnd, out normalEnd, segPosEnd);

                if ((heightStart >= 0.0f && heightEnd <= 0.0f) // Passes down through
                    || (heightStart <= 0.0f && heightEnd >= 0.0f)) // Passes up through
                {
                    done = true;
                    //We intersect here
                }

                if (segEnd.X == segPosEnd.X && segEnd.Z == segPosEnd.Z && !done) // Checking for X,Z handles cases of segments only in Y direction
                {
                    // No intersection found and we are at the end of the ray
                    return false;
                }

            }

            /*Vector3 normalStart;
            float heightStart;

            GetHeightAndNormal(out heightStart, out normalStart,seg.Origin);

            if (heightStart < 0.0f)
                return false;

            Vector3 normalEnd;
            float heightEnd;
            Vector3 end = seg.GetEnd();
            GetHeightAndNormal(out heightEnd, out normalEnd,end);

            if (heightEnd > 0.0f)
                return false;*/

            //Rest of calculations are % based, do not need negatives
            heightStart = System.Math.Abs(heightStart);
            heightEnd = System.Math.Abs(heightEnd);
            // normal is the weighted mean of these...
            float weightStart = 1.0f / (JiggleMath.Epsilon + heightStart);
            float weightEnd = 1.0f / (JiggleMath.Epsilon + heightEnd);

            normal = (normalStart * weightStart + normalEnd * weightEnd) /
              (weightStart + weightEnd);

            frac = heightStart / (heightStart + heightEnd + JiggleMath.Epsilon);

            //pos = seg.GetPoint(frac);
            pos = segPos + (segPosEnd - segPos) * frac;
            return true;
        }
Beispiel #12
0
        /// <summary>
        /// SegmentIntersect
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="pos"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns>bool</returns>
        public override bool SegmentIntersect(out float frac, out Vector3 pos, out Vector3 normal, Segment seg)
        {
            /* Bug with SegmentIntersect, if the segment >= 1 square, then the code fails.
             * We need to start at seg.Origin, and move to seg.Origin + (dx,dz) until one is below and one is above 0)
             */
            frac   = 0;
            pos    = Vector3.Zero;
            normal = Vector3.Up;
            Vector3 normalStart = Vector3.Zero;
            float   heightStart = 0.0f;
            Vector3 normalEnd;
            float   heightEnd;

            Vector3 segPos       = Vector3.Zero;
            Vector3 segPosEnd    = seg.Origin;
            Vector3 segEnd       = seg.GetEnd();
            Vector3 segDirection = seg.Delta;

            segDirection.Y = 0;
            JiggleMath.NormalizeSafe(ref segDirection);
            segDirection.Y = seg.Delta.Y * (segDirection.X / seg.Delta.X); // Scale the Y to be make segDirection a scaler of segDelta, but normalized in the XY plane

            float increment = JiggleMath.Min(dx, dz, float.MaxValue);      // Move by the smaller of the two dx/dz values so we dont "jump" over a point ... this could be done better

            GetHeightAndNormal(out heightEnd, out normalEnd, seg.Origin);
            bool done = false;

            while (!done)
            {
                segPos      = segPosEnd;
                normalStart = normalEnd;
                heightStart = heightEnd;

                segPosEnd += segDirection * increment;

                if ((((segPos.X - segEnd.X) > 0.0f) != ((segPosEnd.X - segEnd.X) > 0.0f)) || // We have moved onto the other side of the seg end in X
                    (((segPos.Z - segEnd.Z) > 0.0f) != ((segPosEnd.Z - segEnd.Z) > 0.0f)))    // We have moved onto the other side of the seg end in Z
                {
                    segPosEnd = segEnd;
                }


                GetHeightAndNormal(out heightEnd, out normalEnd, segPosEnd);

                if ((heightStart >= 0.0f && heightEnd <= 0.0f) || // Passes down through
                    (heightStart <= 0.0f && heightEnd >= 0.0f))    // Passes up through
                {
                    done = true;
                    //We intersect here
                }

                if (segEnd.X == segPosEnd.X && segEnd.Z == segPosEnd.Z && !done) // Checking for X,Z handles cases of segments only in Y direction
                {
                    // No intersection found and we are at the end of the ray
                    return(false);
                }
            }

            /*Vector3 normalStart;
             * float heightStart;
             *
             * GetHeightAndNormal(out heightStart, out normalStart,seg.Origin);
             *
             * if (heightStart < 0.0f)
             *  return false;
             *
             * Vector3 normalEnd;
             * float heightEnd;
             * Vector3 end = seg.GetEnd();
             * GetHeightAndNormal(out heightEnd, out normalEnd,end);
             *
             * if (heightEnd > 0.0f)
             *  return false;*/

            //Rest of calculations are % based, do not need negatives
            heightStart = System.Math.Abs(heightStart);
            heightEnd   = System.Math.Abs(heightEnd);
            // normal is the weighted mean of these...
            float weightStart = 1.0f / (JiggleMath.Epsilon + heightStart);
            float weightEnd   = 1.0f / (JiggleMath.Epsilon + heightEnd);

            normal = (normalStart * weightStart + normalEnd * weightEnd) /
                     (weightStart + weightEnd);

            frac = heightStart / (heightStart + heightEnd + JiggleMath.Epsilon);

            //pos = seg.GetPoint(frac);
            pos = segPos + (segPosEnd - segPos) * frac;
            return(true);
        }