Example #1
0
        internal static Intersection TestIntersectionTerrainSpherePerfect(GeoTerrainTriangle triangle, Hitbox caller, Hitbox collider, ref Vector3 offsetCaller)
        {
            Vector3 untranslatedPositionOfCaller = caller.Owner.Position + offsetCaller - collider.Owner.Position;

            float sphereRadius         = caller.Owner.Scale.X / 2;
            float lowestPointOfSphere  = untranslatedPositionOfCaller.Y - sphereRadius;
            float highestPointOfSphere = untranslatedPositionOfCaller.Y + sphereRadius;

            bool doPreciseTest = IsBetweenOrdered(lowestPointOfSphere, triangle.heightMinUntranslated, triangle.heightMaxUntranslated) ||
                                 IsBetweenOrdered(highestPointOfSphere, triangle.heightMinUntranslated, triangle.heightMaxUntranslated);

            if (doPreciseTest != true)
            {
                if (lowestPointOfSphere >= triangle.heightMinUntranslated && highestPointOfSphere <= triangle.heightMaxUntranslated)
                {
                    doPreciseTest = true;
                }
                else if (lowestPointOfSphere <= triangle.heightMinUntranslated && highestPointOfSphere >= triangle.heightMaxUntranslated)
                {
                    doPreciseTest = true;
                }
            }

            if (doPreciseTest)
            {
                float heightOnTriangle = triangle.InterpolateHeight(untranslatedPositionOfCaller.X, untranslatedPositionOfCaller.Z);

                float difference = heightOnTriangle - lowestPointOfSphere;
                if (difference < 0)
                {
                    return(null);
                }
                float differenceTowardsTriangleNormal = Vector3.Dot(new Vector3(0, difference, 0), triangle.Normal);

                Vector3      mtvUp = new Vector3(0, difference, 0);
                Vector3      mtv   = triangle.Normal * differenceTowardsTriangleNormal;
                Intersection o     = new Intersection(collider.Owner, caller, collider, mtv, mtvUp, collider.mMesh.Name, triangle.Normal);
                return(o);
            }
            return(null);
        }
Example #2
0
        internal static Intersection TestIntersectionSATForTerrain(GeoTerrainTriangle triangle, Hitbox caller, Hitbox collider, ref Vector3 offsetCaller)
        {
            if (caller.Owner.IsSpherePerfect())
            {
                return(TestIntersectionTerrainSpherePerfect(triangle, caller, collider, ref offsetCaller));
            }

            float   shape1Min, shape1Max, shape2Min, shape2Max;
            Vector3 o = collider.Owner.Position;

            float mtvDistance    = float.MaxValue;
            float mtvDirection   = 1;
            float mtvDistanceUp  = float.MaxValue;
            float mtvDirectionUp = 1;

            MTVTemp   = Vector3.Zero;
            MTVTempUp = Vector3.Zero;
            int collisionNormalIndex = -2;

            bool allTrue = true;

            // Test #1
            SatTest(ref triangle.Normal, ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
            SatTestOffset(ref triangle.Normal, ref triangle.Vertices, out shape2Min, out shape2Max, ref o);

            if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
            {
                bool modifyCollisionNormal = CalculateOverlap(ref triangle.Normal, ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                                              ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp,
                                                              ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                if (modifyCollisionNormal)
                {
                    collisionNormalIndex = -1; // -1 = normal from triangle
                }
                for (int j = 0; j < caller.mNormals.Length; j++)
                {
                    SatTest(ref caller.mNormals[j], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                    SatTestOffset(ref caller.mNormals[j], ref triangle.Vertices, out shape2Min, out shape2Max, ref o);
                    if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                    {
                        bool modifyCollisionNormalInLoop = CalculateOverlap(ref caller.mNormals[j], ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                                                            ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp,
                                                                            ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                        if (modifyCollisionNormalInLoop)
                        {
                            collisionNormalIndex = j;
                        }
                    }
                    else
                    {
                        allTrue = false;
                        break;
                    }
                }
                if (allTrue)
                {
                    Intersection tempIntersection;
                    Vector3      rayPos          = caller.Owner.GetLargestHitbox().mCenter + offsetCaller + KWEngine.WorldUp * KWEngine.CurrentWorld.WorldDistance;
                    float        heightOnTerrain = triangle.InterpolateHeight(rayPos.X - o.X, rayPos.Z - o.Z);
                    MTVTempUp.Y = heightOnTerrain - caller.Owner.Position.Y;
                    MTVTempUp.X = 0;
                    MTVTempUp.Z = 0;

                    if (collisionNormalIndex == -1)
                    {
                        tempIntersection = new Intersection(collider.Owner, caller, collider, MTVTemp, MTVTempUp, collider.Owner.Name, triangle.Normal);
                    }
                    else
                    {
                        tempIntersection = new Intersection(collider.Owner, caller, collider, MTVTemp, MTVTempUp, collider.Owner.Name, caller.Normals[collisionNormalIndex]);
                    }
                    return(tempIntersection);
                }
            }
            return(null);
        }
Example #3
0
        internal static Intersection TestIntersection(Hitbox caller, Hitbox collider, Vector3 offsetCaller)
        {
            if (caller.Owner.IsSpherePerfect() && !collider.Owner.IsSpherePerfect())
            {
                return(TestIntersectionSphereConvexHull(caller, collider, offsetCaller));
            }
            else if (caller.Owner.IsSpherePerfect() && collider.Owner.IsSpherePerfect())
            {
                return(TestIntersectionSphereSphere(caller, collider, offsetCaller));
            }
            else if (!caller.Owner.IsSpherePerfect() && collider.Owner.IsSpherePerfect())
            {
                return(TestIntersectionConvexHullSphere(caller, collider, offsetCaller));
            }

            float mtvDistance    = float.MaxValue;
            float mtvDirection   = 1;
            float mtvDistanceUp  = float.MaxValue;
            float mtvDirectionUp = 1;

            MTVTemp   = Vector3.Zero;
            MTVTempUp = Vector3.Zero;
            int collisionNormalIndex = 0;

            for (int i = 0; i < caller.mNormals.Length; i++)
            {
                float shape1Min, shape1Max, shape2Min, shape2Max;
                SatTest(ref caller.mNormals[i], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                SatTest(ref caller.mNormals[i], ref collider.mVertices, out shape2Min, out shape2Max, ref ZeroVector);
                if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                {
                    return(null);
                }
                else
                {
                    bool m = CalculateOverlap(ref caller.mNormals[i], ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                              ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                    if (m)
                    {
                        collisionNormalIndex = i;
                    }
                }
            }

            for (int i = 0; i < collider.mNormals.Length; i++)
            {
                float shape1Min, shape1Max, shape2Min, shape2Max;
                SatTest(ref collider.mNormals[i], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                SatTest(ref collider.mNormals[i], ref collider.mVertices, out shape2Min, out shape2Max, ref ZeroVector);
                if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                {
                    return(null);
                }
                else
                {
                    bool m = CalculateOverlap(ref collider.mNormals[i], ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                              ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                    if (m)
                    {
                        collisionNormalIndex = caller.mNormals.Length + i;
                    }
                }
            }

            if (MTVTemp == Vector3.Zero)
            {
                return(null);
            }

            Vector3 collisionSurfaceNormal;

            if (collisionNormalIndex < caller.mNormals.Length)
            {
                collisionSurfaceNormal = caller.mNormals[collisionNormalIndex];
            }
            else
            {
                collisionSurfaceNormal = collider.mNormals[collisionNormalIndex - caller.mNormals.Length];
            }

            Intersection o = new Intersection(collider.Owner, caller, collider, MTVTemp, MTVTempUp, collider.mMesh.Name, collisionSurfaceNormal);

            return(o);
        }
Example #4
0
        private static Intersection TestIntersectionConvexHullSphere(Hitbox caller, Hitbox collider, Vector3 offsetCaller)
        {
            float mtvDistance    = float.MaxValue;
            float mtvDirection   = 1;
            float mtvDistanceUp  = float.MaxValue;
            float mtvDirectionUp = 1;

            MTVTemp   = Vector3.Zero;
            MTVTempUp = Vector3.Zero;
            bool useSphereNormal = false;

            float   sphereRadius = collider.Owner.Scale.X / 2;
            Vector3 collisionSurfaceNormal = new Vector3(0, 0, 0);
            float   shape1Min, shape1Max, shape2Min, shape2Max;

            for (int i = 0; i < caller.mNormals.Length; i++)
            {
                SatTest(ref caller.mNormals[i], ref caller.mVertices, out shape1Min, out shape1Max, ref ZeroVector);
                shape2Min = Vector3.Dot(collider.GetCenter() - caller.mNormals[i] * sphereRadius, caller.mNormals[i]);
                shape2Max = Vector3.Dot(collider.GetCenter() + caller.mNormals[i] * sphereRadius, caller.mNormals[i]);

                if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                {
                    return(null);
                }
                else
                {
                    bool m = CalculateOverlap(ref caller.mNormals[i], ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                              ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                    if (m)
                    {
                        collisionSurfaceNormal = Vector3.NormalizeFast((caller.mCenter + offsetCaller) - collider.mCenter);
                    }
                }
            }
            //collider is sphere:
            Vector3 sphereToHullDirectionVector = Vector3.NormalizeFast((caller.GetCenter() + offsetCaller) - collider.GetCenter());

            SatTest(ref sphereToHullDirectionVector, ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
            shape2Min = Vector3.Dot(collider.GetCenter() - sphereToHullDirectionVector * sphereRadius, sphereToHullDirectionVector);
            shape2Max = Vector3.Dot(collider.GetCenter() + sphereToHullDirectionVector * sphereRadius, sphereToHullDirectionVector);

            if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
            {
                return(null);
            }
            else
            {
                bool m = CalculateOverlap(ref sphereToHullDirectionVector, ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                          ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                if (m)
                {
                    useSphereNormal = true;
                }
            }

            if (MTVTemp == Vector3.Zero)
            {
                return(null);
            }

            Intersection o = new Intersection(collider.Owner, caller, collider, MTVTemp, MTVTempUp, collider.mMesh.Name, useSphereNormal ? sphereToHullDirectionVector : collisionSurfaceNormal);

            return(o);
        }
Example #5
0
        private static Intersection TestIntersectionSphereConvexHull(Hitbox caller, Hitbox collider, Vector3 offsetCaller)
        {
            float mtvDistance    = float.MaxValue;
            float mtvDirection   = 1;
            float mtvDistanceUp  = float.MaxValue;
            float mtvDirectionUp = 1;

            MTVTemp   = Vector3.Zero;
            MTVTempUp = Vector3.Zero;

            float sphereRadius = caller.Owner.Scale.X / 2;
            int   bestCollisionIndex = 0;
            float shape1Min, shape1Max, shape2Min, shape2Max;

            for (int i = 0; i < collider.mNormals.Length; i++)
            {
                shape1Min = Vector3.Dot((caller.GetCenter() + offsetCaller) - collider.mNormals[i] * sphereRadius, collider.mNormals[i]);
                shape1Max = Vector3.Dot((caller.GetCenter() + offsetCaller) + collider.mNormals[i] * sphereRadius, collider.mNormals[i]);
                SatTest(ref collider.mNormals[i], ref collider.mVertices, out shape2Min, out shape2Max, ref ZeroVector);

                if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                {
                    return(null);
                }
                else
                {
                    bool m = CalculateOverlap(ref collider.mNormals[i], ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                              ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                    if (m)
                    {
                        bestCollisionIndex = i;
                    }
                }
            }
            Vector3 hullToSphereDirectionVector = Vector3.NormalizeFast((caller.GetCenter() + offsetCaller) - collider.GetCenter());

            shape1Min = Vector3.Dot((caller.GetCenter() + offsetCaller) - hullToSphereDirectionVector * sphereRadius, hullToSphereDirectionVector);
            shape1Max = Vector3.Dot((caller.GetCenter() + offsetCaller) + hullToSphereDirectionVector * sphereRadius, hullToSphereDirectionVector);
            SatTest(ref hullToSphereDirectionVector, ref collider.mVertices, out shape2Min, out shape2Max, ref ZeroVector);
            if (!Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
            {
                return(null);
            }
            else
            {
                bool m = CalculateOverlap(ref hullToSphereDirectionVector, ref shape1Min, ref shape1Max, ref shape2Min, ref shape2Max,
                                          ref mtvDistance, ref mtvDistanceUp, ref MTVTemp, ref MTVTempUp, ref mtvDirection, ref mtvDirectionUp, ref caller.mCenter, ref collider.mCenter, ref offsetCaller);
                if (m)
                {
                    bestCollisionIndex = -100;
                }
            }

            if (MTVTemp == Vector3.Zero)
            {
                return(null);
            }

            Intersection o = new Intersection(collider.Owner, caller, collider, MTVTemp, MTVTempUp, collider.mMesh.Name, bestCollisionIndex == -100 ? hullToSphereDirectionVector : collider.mNormals[bestCollisionIndex]);

            return(o);
        }
Example #6
0
        internal static List <Vector3> ClipFaces(Hitbox caller, Hitbox collider)
        {
            List <Vector3> callerVertices          = new List <Vector3>(caller.mVertices);
            List <Vector3> collisionVolumeVertices = new List <Vector3>();

            // Clip caller against collider faces:
            for (int colliderFaceIndex = 0; colliderFaceIndex < collider.mMesh.Faces.Length; colliderFaceIndex++)
            {
                GeoMeshFace colliderClippingFace       = collider.mMesh.Faces[colliderFaceIndex];
                Vector3     colliderClippingFaceVertex = collider.mVertices[colliderClippingFace.Vertices[0]];
                Vector3     colliderClippingFaceNormal = colliderClippingFace.Flip ? collider.mNormals[colliderClippingFace.Normal] : -collider.mNormals[colliderClippingFace.Normal];
                for (int callerVertexIndex = 0; callerVertexIndex < callerVertices.Count; callerVertexIndex++)
                {
                    Vector3 callerVertex1 = callerVertices[callerVertexIndex];
                    Vector3 callerVertex2 = callerVertices[(callerVertexIndex + 1) % callerVertices.Count];
                    Vector3 lineDirection = Vector3.NormalizeFast(callerVertex2 - callerVertex1);

                    bool callerVertex1InsideRegion = HelperIntersection.IsInFrontOfPlane(ref callerVertex1, ref colliderClippingFaceNormal, ref colliderClippingFaceVertex);
                    bool callerVertex2InsideRegion = HelperIntersection.IsInFrontOfPlane(ref callerVertex2, ref colliderClippingFaceNormal, ref colliderClippingFaceVertex);

                    if (callerVertex1InsideRegion)
                    {
                        if (callerVertex2InsideRegion)
                        {
                            if (!collisionVolumeVertices.Contains(callerVertex2))
                            {
                                collisionVolumeVertices.Add(callerVertex2);
                            }
                        }
                        else
                        {
                            Vector3?clippedVertex = ClipLineToPlane(ref callerVertex2, ref lineDirection, ref colliderClippingFaceVertex, ref colliderClippingFaceNormal);
                            if (clippedVertex != null && !collisionVolumeVertices.Contains(clippedVertex.Value))
                            {
                                collisionVolumeVertices.Add(clippedVertex.Value);
                            }
                        }
                    }
                    else
                    {
                        if (callerVertex2InsideRegion)
                        {
                            Vector3?clippedVertex = ClipLineToPlane(ref callerVertex1, ref lineDirection, ref colliderClippingFaceVertex, ref colliderClippingFaceNormal);
                            if (clippedVertex != null && !collisionVolumeVertices.Contains(clippedVertex.Value))
                            {
                                collisionVolumeVertices.Add(clippedVertex.Value);
                            }
                            if (!collisionVolumeVertices.Contains(callerVertex2))
                            {
                                collisionVolumeVertices.Add(callerVertex2);
                            }
                        }
                    }
                }
                callerVertices.Clear();
                for (int i = 0; i < collisionVolumeVertices.Count; i++)
                {
                    callerVertices.Add(collisionVolumeVertices[i]);
                }
                collisionVolumeVertices.Clear();
            }
            return(callerVertices);
        }
Example #7
0
        internal static void TestIntersectionSATForTerrain(ref List <GeoTerrainTriangle> tris, Hitbox caller, Hitbox collider, Vector3 offsetCaller)
        {
            trianglesMTV.Clear();
            float   shape1Min, shape1Max, shape2Min, shape2Max;
            Vector3 o = collider.Owner.Position;

            for (int i = 0; i < tris.Count; i++)
            {
                GeoTerrainTriangle triangle = tris[i];

                // Test #1
                SatTest(ref triangle.Normal, ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                SatTestOffset(ref triangle.Normal, ref triangle.Vertices, out shape2Min, out shape2Max, ref o);

                if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                {
                    // Test #2:
                    SatTest(ref caller.mNormals[0], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                    SatTestOffset(ref caller.mNormals[0], ref triangle.Vertices, out shape2Min, out shape2Max, ref o);
                    if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                    {
                        // Test #3:
                        SatTest(ref caller.mNormals[1], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                        SatTestOffset(ref caller.mNormals[1], ref triangle.Vertices, out shape2Min, out shape2Max, ref o);
                        if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                        {
                            // Test #4:
                            SatTest(ref caller.mNormals[2], ref caller.mVertices, out shape1Min, out shape1Max, ref offsetCaller);
                            SatTestOffset(ref caller.mNormals[2], ref triangle.Vertices, out shape2Min, out shape2Max, ref o);
                            if (Overlaps(shape1Min, shape1Max, shape2Min, shape2Max))
                            {
                                // Test #5: B-A x Hitbox-X-Axis
                                Vector3 subVector = triangle.Vertices[1] - triangle.Vertices[0];
                                //Vector3.Subtract(ref triangle.Vertices[1], ref triangle.Vertices[0], out Vector3 subVector);
                                Vector3.Cross(ref subVector, ref caller.mNormals[0], out Vector3 axisFive);