예제 #1
0
        public static void FastIntersectOrientedBoxPlane(
            XMVector center,
            XMVector extents,
            XMVector axis0,
            XMVector axis1,
            XMVector axis2,
            XMVector plane,
            out XMVector outside,
            out XMVector inside)
        {
            // Compute the distance to the center of the box.
            XMVector dist = XMVector4.Dot(center, plane);

            // Project the axes of the box onto the normal of the plane.  Half the
            // length of the projection (sometime called the "radius") is equal to
            // h(u) * abs(n dot b(u))) + h(v) * abs(n dot b(v)) + h(w) * abs(n dot b(w))
            // where h(i) are extents of the box, n is the plane normal, and b(i) are the
            // axes of the box.
            XMVector radius = XMVector3.Dot(plane, axis0);

            radius.Y = XMVector3.Dot(plane, axis1).Y;
            radius.Z = XMVector3.Dot(plane, axis2).Z;
            radius   = XMVector3.Dot(extents, radius.Abs());

            // Outside the plane?
            outside = XMVector.Greater(dist, radius);

            // Fully inside the plane?
            inside = XMVector.Less(dist, -radius);
        }
예제 #2
0
        public bool Intersects(BoundingSphere sh)
        {
            XMVector sphereCenter = sh.Center;
            XMVector sphereRadius = XMVector.Replicate(sh.Radius);

            XMVector boxCenter  = this.center;
            XMVector boxExtents = this.extents;

            XMVector boxMin = boxCenter - boxExtents;
            XMVector boxMax = boxCenter + boxExtents;

            //// Find the distance to the nearest point on the box.
            //// for each i in (x, y, z)
            //// if (SphereCenter(i) < BoxMin(i)) d2 += (SphereCenter(i) - BoxMin(i)) ^ 2
            //// else if (SphereCenter(i) > BoxMax(i)) d2 += (SphereCenter(i) - BoxMax(i)) ^ 2

            XMVector d = XMGlobalConstants.Zero;

            // Compute d for each dimension.
            XMVector lessThanMin    = XMVector.Less(sphereCenter, boxMin);
            XMVector greaterThanMax = XMVector.Greater(sphereCenter, boxMax);

            XMVector minDelta = sphereCenter - boxMin;
            XMVector maxDelta = sphereCenter - boxMax;

            // Choose value for each dimension based on the comparison.
            d = XMVector.Select(d, minDelta, lessThanMin);
            d = XMVector.Select(d, maxDelta, greaterThanMax);

            // Use a dot-product to square them and sum them together.
            XMVector d2 = XMVector3.Dot(d, d);

            return(XMVector3.LessOrEqual(d2, XMVector.Multiply(sphereRadius, sphereRadius)));
        }
예제 #3
0
        public bool Intersects(XMVector origin, XMVector direction, out float distance)
        {
            Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed");

            // Load the box.
            XMVector v_center  = this.center;
            XMVector v_extents = this.extents;

            // Adjust ray origin to be relative to center of the box.
            XMVector t_origin = v_center - origin;

            // Compute the dot product againt each axis of the box.
            // Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary.
            XMVector axisDotOrigin    = t_origin;
            XMVector axisDotDirection = direction;

            // if (fabs(AxisDotDirection) <= Epsilon) the ray is nearly parallel to the slab.
            XMVector isParallel = XMVector.LessOrEqual(axisDotDirection.Abs(), CollisionGlobalConstants.RayEpsilon);

            // Test against all three axii simultaneously.
            XMVector inverseAxisDotDirection = axisDotDirection.Reciprocal();
            XMVector t1 = (axisDotOrigin - v_extents) * inverseAxisDotDirection;
            XMVector t2 = (axisDotOrigin + v_extents) * inverseAxisDotDirection;

            // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
            // use the results from any directions parallel to the slab.
            XMVector t_min = XMVector.Select(XMVector.Min(t1, t2), CollisionGlobalConstants.FltMin, isParallel);
            XMVector t_max = XMVector.Select(XMVector.Max(t1, t2), CollisionGlobalConstants.FltMax, isParallel);

            // t_min.x = maximum( t_min.x, t_min.y, t_min.z );
            // t_max.x = minimum( t_max.x, t_max.y, t_max.z );
            t_min = XMVector.Max(t_min, XMVector.SplatY(t_min));  // x = max(x,y)
            t_min = XMVector.Max(t_min, XMVector.SplatZ(t_min));  // x = max(max(x,y),z)
            t_max = XMVector.Min(t_max, XMVector.SplatY(t_max));  // x = min(x,y)
            t_max = XMVector.Min(t_max, XMVector.SplatZ(t_max));  // x = min(min(x,y),z)

            // if ( t_min > t_max ) return false;
            XMVector noIntersection = XMVector.Greater(XMVector.SplatX(t_min), XMVector.SplatX(t_max));

            // if ( t_max < 0.0f ) return false;
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(XMVector.SplatX(t_max), XMGlobalConstants.Zero));

            // if (IsParallel && (-Extents > AxisDotOrigin || Extents < AxisDotOrigin)) return false;
            XMVector parallelOverlap = axisDotOrigin.InBounds(v_extents);

            noIntersection = XMVector.OrInt(noIntersection, XMVector.AndComplementInt(isParallel, parallelOverlap));

            if (!Internal.XMVector3AnyTrue(noIntersection))
            {
                // Store the x-component to *pDist
                t_min.StoreFloat(out distance);
                return(true);
            }

            distance = 0.0f;
            return(false);
        }
예제 #4
0
        public static void FastIntersectSpherePlane(XMVector center, XMVector radius, XMVector plane, out XMVector outside, out XMVector inside)
        {
            XMVector dist = XMVector4.Dot(center, plane);

            // Outside the plane?
            outside = XMVector.Greater(dist, radius);

            // Fully inside the plane?
            inside = XMVector.Less(dist, -radius);
        }
예제 #5
0
        public static void FastIntersectFrustumPlane(
            XMVector point0,
            XMVector point1,
            XMVector point2,
            XMVector point3,
            XMVector point4,
            XMVector point5,
            XMVector point6,
            XMVector point7,
            XMVector plane,
            out XMVector outside,
            out XMVector inside)
        {
            // Find the min/max projection of the frustum onto the plane normal.
            XMVector min, max, dist;

            min = max = XMVector3.Dot(plane, point0);

            dist = XMVector3.Dot(plane, point1);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point2);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point3);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point4);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point5);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point6);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            dist = XMVector3.Dot(plane, point7);
            min  = XMVector.Min(min, dist);
            max  = XMVector.Max(max, dist);

            XMVector planeDist = -XMVector.SplatW(plane);

            // Outside the plane?
            outside = XMVector.Greater(min, planeDist);

            // Fully inside the plane?
            inside = XMVector.Less(max, planeDist);
        }
        public bool Intersects(XMVector v0, XMVector v1, XMVector v2)
        {
            // Load the sphere.
            XMVector v_center = this.center;
            XMVector v_radius = XMVector.Replicate(this.radius);

            // Compute the plane of the triangle (has to be normalized).
            XMVector n = XMVector3.Normalize(XMVector3.Cross(v1 - v0, v2 - v0));

            // Assert that the triangle is not degenerate.
            Debug.Assert(!XMVector3.Equal(n, XMGlobalConstants.Zero), "Reviewed");

            // Find the nearest feature on the triangle to the sphere.
            XMVector dist = XMVector3.Dot(v_center - v0, n);

            // If the center of the sphere is farther from the plane of the triangle than
            // the radius of the sphere, then there cannot be an intersection.
            XMVector noIntersection = XMVector.Less(dist, -v_radius);

            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(dist, v_radius));

            // Project the center of the sphere onto the plane of the triangle.
            XMVector point = v_center - (n * dist);

            // Is it inside all the edges? If so we intersect because the distance
            // to the plane is less than the radius.
            XMVector intersection = Internal.PointOnPlaneInsideTriangle(point, v0, v1, v2);

            // Find the nearest point on each edge.
            XMVector radiusSq = v_radius * v_radius;

            // Edge 0,1
            point = Internal.PointOnLineSegmentNearestPoint(v0, v1, v_center);

            // If the distance to the center of the sphere to the point is less than
            // the radius of the sphere then it must intersect.
            intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq));

            // Edge 1,2
            point = Internal.PointOnLineSegmentNearestPoint(v1, v2, v_center);

            // If the distance to the center of the sphere to the point is less than
            // the radius of the sphere then it must intersect.
            intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq));

            // Edge 2,0
            point = Internal.PointOnLineSegmentNearestPoint(v2, v0, v_center);

            // If the distance to the center of the sphere to the point is less than
            // the radius of the sphere then it must intersect.
            intersection = XMVector.OrInt(intersection, XMVector.LessOrEqual(XMVector3.LengthSquare(v_center - point), radiusSq));

            return(XMVector4.EqualInt(XMVector.AndComplementInt(intersection, noIntersection), XMVector.TrueInt));
        }
예제 #7
0
        public static XMVector SlerpV(XMVector q0, XMVector q1, XMVector t)
        {
            Debug.Assert(t.Y == t.X && t.Z == t.X && t.W == t.X, "Reviewed");

            //// Result = Q0 * sin((1.0 - t) * Omega) / sin(Omega) + Q1 * sin(t * Omega) / sin(Omega)

            XMVector oneMinusEpsilon = XMVector.FromFloat(1.0f - 0.00001f, 1.0f - 0.00001f, 1.0f - 0.00001f, 1.0f - 0.00001f);

            XMVector cosOmega = XMQuaternion.Dot(q0, q1);
            XMVector zero     = XMVector.Zero;
            XMVector control  = XMVector.Less(cosOmega, zero);
            XMVector sign     = XMVector.Select(XMGlobalConstants.One, XMGlobalConstants.NegativeOne, control);

            cosOmega = XMVector.Multiply(cosOmega, sign);
            control  = XMVector.Less(cosOmega, oneMinusEpsilon);

            XMVector sinOmega = XMVector
                                .NegativeMultiplySubtract(cosOmega, cosOmega, XMGlobalConstants.One)
                                .Sqrt();

            XMVector omega = XMVector.ATan2(sinOmega, cosOmega);

            XMVector signMask = XMVector.SignMask;
            XMVector v01      = XMVector.ShiftLeft(t, zero, 2);

            signMask = XMVector.ShiftLeft(signMask, zero, 3);
            v01      = XMVector.XorInt(v01, signMask);
            v01      = XMVector.Add(XMGlobalConstants.IdentityR0, v01);

            XMVector invSinOmega = sinOmega.Reciprocal();

            XMVector s0 = XMVector
                          .Multiply(v01, omega)
                          .Sin();

            s0 = XMVector.Multiply(s0, invSinOmega);
            s0 = XMVector.Select(v01, s0, control);

            XMVector s1 = XMVector.SplatY(s0);

            s0 = XMVector.SplatX(s0);
            s1 = XMVector.Multiply(s1, sign);

            XMVector result = XMVector.Multiply(q0, s0);

            result = XMVector.MultiplyAdd(q1, s1, result);

            return(result);
        }
        public bool Intersects(XMVector origin, XMVector direction, out float distance)
        {
            Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed");

            XMVector v_center = this.center;
            XMVector v_radius = XMVector.Replicate(this.radius);

            // l is the vector from the ray origin to the center of the sphere.
            XMVector l = v_center - origin;

            // s is the projection of the l onto the ray direction.
            XMVector s = XMVector3.Dot(l, direction);

            XMVector l2 = XMVector3.Dot(l, l);

            XMVector r2 = v_radius * v_radius;

            // m2 is squared distance from the center of the sphere to the projection.
            XMVector m2 = l2 - (s * s);

            XMVector noIntersection;

            // If the ray origin is outside the sphere and the center of the sphere is
            // behind the ray origin there is no intersection.
            noIntersection = XMVector.AndInt(XMVector.Less(s, XMGlobalConstants.Zero), XMVector.Greater(l2, r2));

            // If the squared distance from the center of the sphere to the projection
            // is greater than the radius squared the ray will miss the sphere.
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(m2, r2));

            // The ray hits the sphere, compute the nearest intersection point.
            XMVector q  = (r2 - m2).Sqrt();
            XMVector t1 = s - q;
            XMVector t2 = s + q;

            XMVector originInside = XMVector.LessOrEqual(l2, r2);
            XMVector t            = XMVector.Select(t1, t2, originInside);

            if (XMVector4.NotEqualInt(noIntersection, XMVector.TrueInt))
            {
                // Store the x-component to *pDist.
                t.StoreFloat(out distance);
                return(true);
            }

            distance = 0.0f;
            return(false);
        }
예제 #9
0
        public static XMVector RgbToSrgb(XMVector rgb)
        {
            XMVector cutoff   = XMVector.FromFloat(0.0031308f, 0.0031308f, 0.0031308f, 1.0f);
            XMVector linear   = XMVector.FromFloat(12.92f, 12.92f, 12.92f, 1.0f);
            XMVector scale    = XMVector.FromFloat(1.055f, 1.055f, 1.055f, 1.0f);
            XMVector bias     = XMVector.FromFloat(0.055f, 0.055f, 0.055f, 0.0f);
            XMVector invGamma = XMVector.FromFloat(1.0f / 2.4f, 1.0f / 2.4f, 1.0f / 2.4f, 1.0f);

            XMVector v  = rgb.Saturate();
            XMVector v0 = XMVector.Multiply(v, linear);
            XMVector v1 = XMVector.Subtract(XMVector.Multiply(scale, XMVector.Pow(v, invGamma)), bias);

            XMVector select = XMVector.Less(v, cutoff);

            v = XMVector.Select(v1, v0, select);
            return(XMVector.Select(rgb, v, XMGlobalConstants.Select1110));
        }
예제 #10
0
        public static void FastIntersectAxisAlignedBoxPlane(XMVector center, XMVector extents, XMVector plane, out XMVector outside, out XMVector inside)
        {
            // Compute the distance to the center of the box.
            XMVector dist = XMVector4.Dot(center, plane);

            // Project the axes of the box onto the normal of the plane.  Half the
            // length of the projection (sometime called the "radius") is equal to
            // h(u) * abs(n dot b(u))) + h(v) * abs(n dot b(v)) + h(w) * abs(n dot b(w))
            // where h(i) are extents of the box, n is the plane normal, and b(i) are the
            // axes of the box. In this case b(i) = [(1,0,0), (0,1,0), (0,0,1)].
            XMVector radius = XMVector3.Dot(extents, plane.Abs());

            // Outside the plane?
            outside = XMVector.Greater(dist, radius);

            // Fully inside the plane?
            inside = XMVector.Less(dist, -radius);
        }
예제 #11
0
        public static void SquadSetup(out XMVector a, out XMVector b, out XMVector c, XMVector q0, XMVector q1, XMVector q2, XMVector q3)
        {
            XMVector ls12 = XMQuaternion.LengthSquare(XMVector.Add(q1, q2));
            XMVector ld12 = XMQuaternion.LengthSquare(XMVector.Subtract(q1, q2));
            XMVector sq2  = q2.Negate();

            XMVector control1 = XMVector.Less(ls12, ld12);

            sq2 = XMVector.Select(q2, sq2, control1);

            XMVector ls01 = XMQuaternion.LengthSquare(XMVector.Add(q0, q1));
            XMVector ld01 = XMQuaternion.LengthSquare(XMVector.Subtract(q0, q1));
            XMVector sq0  = q0.Negate();

            XMVector ls23 = XMQuaternion.LengthSquare(XMVector.Add(sq2, q3));
            XMVector ld23 = XMQuaternion.LengthSquare(XMVector.Subtract(sq2, q3));
            XMVector sq3  = q3.Negate();

            XMVector control0 = XMVector.Less(ls01, ld01);
            XMVector control2 = XMVector.Less(ls23, ld23);

            sq0 = XMVector.Select(q0, sq0, control0);
            sq3 = XMVector.Select(q3, sq3, control2);

            XMVector invQ1 = XMQuaternion.Inverse(q1);
            XMVector invQ2 = XMQuaternion.Inverse(sq2);

            XMVector ln_q0 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ1, sq0));
            XMVector ln_q2 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ1, sq2));
            XMVector ln_q1 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ2, q1));
            XMVector ln_q3 = XMQuaternion.Ln(XMQuaternion.Multiply(invQ2, sq3));

            XMVector negativeOneQuarter = XMVector.FromSplatConstant(-1, 2);

            XMVector expQ02 = XMVector.Multiply(XMVector.Add(ln_q0, ln_q2), negativeOneQuarter);
            XMVector expQ13 = XMVector.Multiply(XMVector.Add(ln_q1, ln_q3), negativeOneQuarter);

            expQ02 = XMQuaternion.Exp(expQ02);
            expQ13 = XMQuaternion.Exp(expQ13);

            a = XMQuaternion.Multiply(q1, expQ02);
            b = XMQuaternion.Multiply(sq2, expQ13);
            c = sq2;
        }
예제 #12
0
        public static XMVector PointOnLineSegmentNearestPoint(XMVector s1, XMVector s2, XMVector p)
        {
            XMVector dir        = s1 - s1;
            XMVector projection = XMVector3.Dot(p, dir) - XMVector3.Dot(s1, dir);
            XMVector lengthSq   = XMVector3.Dot(dir, dir);

            XMVector t     = projection * lengthSq.Reciprocal();
            XMVector point = s1 + (t * dir);

            // t < 0
            XMVector selectS1 = XMVector.Less(projection, XMGlobalConstants.Zero);

            point = XMVector.Select(point, s1, selectS1);

            // t > 1
            XMVector selectS2 = XMVector.Greater(projection, lengthSq);

            point = XMVector.Select(point, s2, selectS2);

            return(point);
        }
예제 #13
0
        public static XMVector Orthogonal(XMVector v)
        {
            XMVector zero = XMVector.Zero;
            XMVector z    = XMVector.SplatZ(v);

            XMVector yzyy      = new XMVector(v.Y, v.Z, v.Y, v.Y);
            XMVector negativeV = XMVector.Subtract(zero, v);

            XMVector z_isNegative   = XMVector.Less(z, zero);
            XMVector yzyyIsNegative = XMVector.Less(yzyy, zero);

            XMVector s = XMVector.Add(yzyy, z);
            XMVector d = XMVector.Subtract(yzyy, z);

            XMVector select = XMVector.EqualInt(z_isNegative, yzyyIsNegative);

            XMVector r0 = new XMVector(s.X, negativeV.X, negativeV.X, negativeV.X);
            XMVector r1 = new XMVector(d.X, v.X, v.X, v.X);

            return(XMVector.Select(r1, r0, select));
        }
예제 #14
0
        public static XMVector ClampLengthV(XMVector v, XMVector lengthMin, XMVector lengthMax)
        {
            Debug.Assert(lengthMin.Y == lengthMin.X && lengthMin.Z == lengthMin.X && lengthMin.W == lengthMin.X, "Reviewed");
            Debug.Assert(lengthMax.Y == lengthMax.X && lengthMax.Z == lengthMax.X && lengthMax.W == lengthMax.X, "Reviewed");
            Debug.Assert(XMVector4.GreaterOrEqual(lengthMin, XMGlobalConstants.Zero), "Reviewed");
            Debug.Assert(XMVector4.GreaterOrEqual(lengthMax, XMGlobalConstants.Zero), "Reviewed");
            Debug.Assert(XMVector4.GreaterOrEqual(lengthMax, lengthMin), "Reviewed");

            XMVector lengthSq         = XMVector4.LengthSquare(v);
            XMVector zero             = XMVector.Zero;
            XMVector reciprocalLength = lengthSq.ReciprocalSqrt();

            XMVector infiniteLength = XMVector.EqualInt(lengthSq, XMGlobalConstants.Infinity);
            XMVector zeroLength     = XMVector.Equal(lengthSq, zero);

            XMVector normal = XMVector.Multiply(v, reciprocalLength);
            XMVector length = XMVector.Multiply(lengthSq, reciprocalLength);

            XMVector select = XMVector.EqualInt(infiniteLength, zeroLength);

            length = XMVector.Select(lengthSq, length, select);
            normal = XMVector.Select(lengthSq, normal, select);

            XMVector controlMax = XMVector.Greater(length, lengthMax);
            XMVector controlMin = XMVector.Less(length, lengthMin);

            XMVector clampLength = XMVector.Select(length, lengthMax, controlMax);

            clampLength = XMVector.Select(clampLength, lengthMin, controlMin);

            XMVector result = XMVector.Multiply(normal, clampLength);

            // Preserve the original vector (with no precision loss) if the length falls within the given range
            XMVector control = XMVector.EqualInt(controlMax, controlMin);

            result = XMVector.Select(result, v, control);

            return(result);
        }
예제 #15
0
        public static void FastIntersectTrianglePlane(XMVector v0, XMVector v1, XMVector v2, XMVector plane, out XMVector outside, out XMVector inside)
        {
            // Plane0
            XMVector dist0 = XMVector4.Dot(v0, plane);
            XMVector dist1 = XMVector4.Dot(v1, plane);
            XMVector dist2 = XMVector4.Dot(v2, plane);

            XMVector minDist = XMVector.Min(dist0, dist1);

            minDist = XMVector.Min(minDist, dist2);

            XMVector maxDist = XMVector.Max(dist0, dist1);

            maxDist = XMVector.Max(maxDist, dist2);

            XMVector zero = XMGlobalConstants.Zero;

            // Outside the plane?
            outside = XMVector.Greater(minDist, zero);

            // Fully inside the plane?
            inside = XMVector.Less(maxDist, zero);
        }
예제 #16
0
        public bool Intersects(XMVector v0, XMVector v1, XMVector v2)
        {
            XMVector zero = XMGlobalConstants.Zero;

            // Load the box.
            XMVector v_center  = this.center;
            XMVector v_extents = this.extents;

            XMVector boxMin = v_center - v_extents;
            XMVector boxMax = v_center + v_extents;

            // Test the axes of the box (in effect test the AAB against the minimal AAB
            // around the triangle).
            XMVector triMin = XMVector.Min(XMVector.Min(v0, v1), v2);
            XMVector triMax = XMVector.Max(XMVector.Max(v0, v1), v2);

            // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then disjoint
            XMVector disjoint = XMVector.OrInt(XMVector.Greater(triMin, boxMax), XMVector.Greater(boxMin, triMax));

            if (Internal.XMVector3AnyTrue(disjoint))
            {
                return(false);
            }

            // Test the plane of the triangle.
            XMVector normal = XMVector3.Cross(v1 - v0, v2 - v0);
            XMVector dist   = XMVector3.Dot(normal, v0);

            // Assert that the triangle is not degenerate.
            Debug.Assert(!XMVector3.Equal(normal, zero), "Reviewed");

            // for each i in (x, y, z) if n(i) >= 0 then v_min(i)=b_min(i), v_max(i)=b_max(i)
            // else v_min(i)=b_max(i), v_max(i)=b_min(i)
            XMVector normalSelect = XMVector.Greater(normal, zero);
            XMVector v_min        = XMVector.Select(boxMax, boxMin, normalSelect);
            XMVector v_max        = XMVector.Select(boxMin, boxMax, normalSelect);

            // if n dot v_min + d > 0 || n dot v_max + d < 0 then disjoint
            XMVector minDist = XMVector3.Dot(v_min, normal);
            XMVector maxDist = XMVector3.Dot(v_max, normal);

            XMVector noIntersection = XMVector.Greater(minDist, dist);

            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(maxDist, dist));

            // Move the box center to zero to simplify the following tests.
            XMVector tV0 = v0 - v_center;
            XMVector tV1 = v1 - v_center;
            XMVector tV2 = v2 - v_center;

            // Test the edge/edge axes (3*3).
            XMVector e0 = tV1 - tV0;
            XMVector e1 = tV2 - tV1;
            XMVector e2 = tV0 - tV2;

            // Make w zero.
            e0.W = zero.W;
            e1.W = zero.W;
            e2.W = zero.W;

            XMVector axis;
            XMVector p0, p1, p2;
            XMVector min, max;
            XMVector radius;

            //// Axis == (1,0,0) x e0 = (0, -e0.z, e0.y)
            axis = new XMVector(e1.W, -e0.Z, e1.Y, e1.X);
            p0   = XMVector3.Dot(tV0, axis);
            //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
            p2             = XMVector3.Dot(tV2, axis);
            min            = XMVector.Min(p0, p2);
            max            = XMVector.Max(p0, p2);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (1,0,0) x e1 = (0, -e1.z, e1.y)
            axis = new XMVector(e1.W, -e1.Z, e1.Y, e1.X);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (1,0,0) x e2 = (0, -e2.z, e2.y)
            axis = new XMVector(e2.W, -e2.Z, e2.Y, e2.X);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,1,0) x e0 = (e0.z, 0, -e0.x)
            axis = new XMVector(e0.Z, e0.W, -e0.X, e0.Y);
            p0   = XMVector3.Dot(tV0, axis);
            //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
            p2             = XMVector3.Dot(tV2, axis);
            min            = XMVector.Min(p0, p2);
            max            = XMVector.Max(p0, p2);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,1,0) x e1 = (e1.z, 0, -e1.x)
            axis = new XMVector(e1.Z, e1.W, -e1.X, e1.Y);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,0,1) x e2 = (e2.z, 0, -e2.x)
            axis = new XMVector(e2.Z, e2.W, -e2.X, e2.Y);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,0,1) x e0 = (-e0.y, e0.x, 0)
            axis = new XMVector(-e0.Y, e0.X, e0.W, e0.Z);
            p0   = XMVector3.Dot(tV0, axis);
            //// p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
            p2             = XMVector3.Dot(tV2, axis);
            min            = XMVector.Min(p0, p2);
            max            = XMVector.Max(p0, p2);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,0,1) x e1 = (-e1.y, e1.x, 0)
            axis = new XMVector(-e1.Y, e1.X, e1.W, e1.Z);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            //// Axis == (0,0,1) x e2 = (-e2.y, e2.x, 0)
            axis = new XMVector(-e2.Y, e2.X, e2.W, e2.Z);
            p0   = XMVector3.Dot(tV0, axis);
            p1   = XMVector3.Dot(tV1, axis);
            //// p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
            min            = XMVector.Min(p0, p1);
            max            = XMVector.Max(p0, p1);
            radius         = XMVector3.Dot(v_extents, axis.Abs());
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(min, radius));
            noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(max, -radius));

            return(XMVector4.NotEqualInt(noIntersection, XMVector.TrueInt));
        }
예제 #17
0
        public static bool Intersects(XMVector origin, XMVector direction, XMVector v0, XMVector v1, XMVector v2, out float uCoordinate, out float vCoordinate, out float distance)
        {
            Debug.Assert(Internal.XMVector3IsUnit(direction), "Reviewed");

            XMVector zero = XMGlobalConstants.Zero;

            XMVector e1 = v1 - v0;
            XMVector e2 = v2 - v0;

            // p = Direction ^ e2;
            XMVector p = XMVector3.Cross(direction, e2);

            // det = e1 * p;
            XMVector det = XMVector3.Dot(e1, p);

            XMVector u, v, t;

            if (XMVector3.GreaterOrEqual(det, CollisionGlobalConstants.RayEpsilon))
            {
                // Determinate is positive (front side of the triangle).
                XMVector s = origin - v0;

                // u = s * p;
                u = XMVector3.Dot(s, p);

                XMVector noIntersection = XMVector.Less(u, zero);
                noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(u, det));

                // q = s ^ e1;
                XMVector q = XMVector3.Cross(s, e1);

                // v = Direction * q;
                v = XMVector3.Dot(direction, q);

                noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(v, zero));
                noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(u + v, det));

                // t = e2 * q;
                t = XMVector3.Dot(e2, q);

                noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(t, zero));

                if (XMVector4.EqualInt(noIntersection, XMVector.TrueInt))
                {
                    uCoordinate = 0.0f;
                    vCoordinate = 0.0f;
                    distance    = 0.0f;
                    return(false);
                }
            }
            else if (XMVector3.LessOrEqual(det, CollisionGlobalConstants.RayNegEpsilon))
            {
                // Determinate is negative (back side of the triangle).
                XMVector s = origin - v0;

                // u = s * p;
                u = XMVector3.Dot(s, p);

                XMVector noIntersection = XMVector.Greater(u, zero);
                noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(u, det));

                // q = s ^ e1;
                XMVector q = XMVector3.Cross(s, e1);

                // v = Direction * q;
                v = XMVector3.Dot(direction, q);

                noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(v, zero));
                noIntersection = XMVector.OrInt(noIntersection, XMVector.Less(u + v, det));

                // t = e2 * q;
                t = XMVector3.Dot(e2, q);

                noIntersection = XMVector.OrInt(noIntersection, XMVector.Greater(t, zero));

                if (XMVector4.EqualInt(noIntersection, XMVector.TrueInt))
                {
                    uCoordinate = 0.0f;
                    vCoordinate = 0.0f;
                    distance    = 0.0f;
                    return(false);
                }
            }
            else
            {
                // Parallel ray.
                uCoordinate = 0.0f;
                vCoordinate = 0.0f;
                distance    = 0.0f;
                return(false);
            }

            // (u / det) and (v / dev) are the barycentric coordinates of the intersection.

            u = XMVector.Divide(u, det);
            v = XMVector.Divide(v, det);
            t = XMVector.Divide(t, det);

            // Store the x-component to *pDist
            u.StoreFloat(out uCoordinate);
            v.StoreFloat(out vCoordinate);
            t.StoreFloat(out distance);

            return(true);
        }