private XVector3 BisectionSearch(XVector3 origin, XVector3 end, float min, float max)
        {
            float    mid    = (min + max) / 2;
            XVector3 newEnd = end + mid * XVector3.Normalize(end - origin);
            float    minDot = float.MaxValue;

            for (int i = 0; i < _verts.Length; i++)
            {
                float dot = XVector3.Dot(XVector3.Normalize(origin - newEnd), XVector3.Normalize(_verts[i] - newEnd));
                if (dot < -_Epsilon)
                {
                    return(BisectionSearch(origin, end, mid, max));
                }
                if (minDot > dot)
                {
                    minDot = dot;
                }
            }

            if (minDot > _Epsilon)
            {
                return(BisectionSearch(origin, end, min, mid));
            }
            return(newEnd);
        }
        private void GetReferencePoint()
        {
            bool  assigned = false;
            float min      = float.MaxValue;

            var ji = XVector3.Normalize(_verts[0] - _verts[1]);
            var jk = XVector3.Normalize(_verts[2] - _verts[1]);
            var kl = XVector3.Normalize(_verts[3] - _verts[2]);
            var il = XVector3.Normalize(_verts[3] - _verts[0]);
            var ij = -ji;
            var kj = -jk;
            var lk = -kl;
            var li = -il;

            float[] dots = { XVector3.Dot(ij, il), XVector3.Dot(ji, jk),
                             XVector3.Dot(kj, kl), XVector3.Dot(lk, li) };

            for (int n = 0; n < dots.Length; n++)
            {
                if (dots[n] > -_Epsilon && min > dots[n] && (dots[(n + 3) % dots.Length] > -_Epsilon ||
                                                             dots[(n + 1) % dots.Length] > -_Epsilon))
                {
                    assigned = true;
                    Start    = _verts[n];
                    Corner   = _verts[(n + 1) % dots.Length];
                    min      = dots[n];
                }
            }
            if (!assigned)
            {
                Start  = _verts[0];
                Corner = _verts[1];
            }
        }
        private int ExponentialSearch(XVector3 origin, XVector3 end, int step = -1)
        {
            var newEnd = end + Exp(step) * XVector3.Normalize(end - origin);

            for (int i = 0; i < _verts.Length; i++)
            {
                float dot = XVector3.Dot(XVector3.Normalize(origin - newEnd), XVector3.Normalize(_verts[i] - newEnd));
                if (dot < 0)
                {
                    return(ExponentialSearch(origin, end, step + 1));
                }
            }
            return(step);
        }