public static IEnumerator OneTimeExplosionTest <T> (IExplosionExecutor ee, IPolygonSubtractor sub,
                                                        int numExplosions, float explosionRadius, bool hasHoles, float radius, int numEdges,
                                                        int columns, int rows) where T : DestructibleObject
    {
        // Set a constant seed so that we get the same results every time
        UnityEngine.Random.InitState(12345);

        new GameObject("Main Camera").AddComponent <Camera>().transform.position = new Vector3(0, 50, -100);

        // Meaure the time to create all destructible objects
        CreateRingsAndMeasure <T>(hasHoles, true, radius, numEdges, columns, rows);
        yield return(null);

        List <Explosion> explosions = new List <Explosion>();

        for (int i = 0; i < numExplosions; ++i)
        {
            explosions.Add(new Explosion(UnityEngine.Random.Range(-10, 10), UnityEngine.Random.Range(0, 20),
                                         explosionRadius, 24));
        }

        using (Measure.ProfilerMarkers(ProfilerMarkers.SampleGroupDefinitions)) {
            ProfilerMarkers.ProcessExplosions.Begin();
            ee.ExecuteExplosions(explosions, DestructibleObject.FindAll(), sub);
            ProfilerMarkers.ProcessExplosions.End();
        }
        yield return(null);

        // Wait to observe whether the result is correct
        yield return(WaitFrames(60));

        CleanUp();
    }
Example #2
0
        public static void DO_Subtraction(IPolygonSubtractor sub, DO_Tri_Tri dtObject, float x, float y)
        {
            DTPolygon box = new DTPolygon(square.Contour, L(smallSquare.Contour));

            dtObject.transform.position = new Vector3(x, y, 0);
            dtObject.ApplyPolygonList(L(box));

            Explosion explosion = new Explosion(x + 1, y + 1, 0.2f, 8);

            IterEE.ExecuteExplosions(L(explosion), L(dtObject), sub);
        }
    public static IEnumerator ContinuousExplosionTest <T> (IExplosionExecutor ee, IPolygonSubtractor sub,
                                                           int numExplosions, float explosionRadius, float explosionInterval, bool hasHoles, float radius, int numEdges,
                                                           int columns, int rows, int warmupFrames, int captureFrames) where T : DestructibleObject
    {
        // Set a constant seed so that we get the same results every time
        UnityEngine.Random.InitState(12345);

        new GameObject("Main Camera").AddComponent <Camera>().transform.position = new Vector3(0, 50, -100);

        // Meaure the time to create all destructible objects
        CreateRingsAndMeasure <T>(hasHoles, true, radius, numEdges, columns, rows);

        // Set all objects to static
        var dObjs = DestructibleObject.FindAll();

        foreach (var dObj in dObjs)
        {
            dObj.GetComponent <Rigidbody2D>().bodyType = RigidbodyType2D.Static;
        }
        yield return(null);

        float explosionTimer = 0;

        // To be called every fixed update;
        // Generates a number of explosions every time the timer reaches a fixed interval.
        void explosionGenerator()
        {
            explosionTimer += Time.fixedDeltaTime;
            List <Explosion> explosions = new List <Explosion>();

            while (explosionTimer > explosionInterval)
            {
                explosionTimer -= explosionInterval;
                for (int i = 0; i < numExplosions; ++i)
                {
                    explosions.Add(new Explosion(UnityEngine.Random.Range(-10, 10), UnityEngine.Random.Range(0, 20),
                                                 explosionRadius, 24));
                }
            }

            ProfilerMarkers.ProcessExplosions.Begin();
            ee.ExecuteExplosions(explosions, DestructibleObject.FindAll(), sub);
            ProfilerMarkers.ProcessExplosions.End();
        }

        // Allow objects to collide before we measure physics
        yield return(WarmupFrames(warmupFrames, explosionGenerator));

        // Measure physics
        yield return(CaptureFrames(captureFrames, explosionGenerator));

        CleanUp();
    }
Example #4
0
        public static void BasicPolygroup(IPolygonSubtractor sub)
        {
            List <DTPolygon> subjectPolygroup = L(
                P(V(-2.5f, 0.5f), V(2.5f, 0.5f), V(2.5f, 1.5f), V(-2.5f, 1.5f)),
                P(V(-2.5f, -0.5f), V(2.5f, -0.5f), V(2.5f, 0.5f), V(-2.5f, 0.5f)),
                P(V(-2.5f, -1.5f), V(2.5f, -1.5f), V(2.5f, -0.5f), V(-2.5f, -0.5f))
                );

            List <DTPolygon> clipPolygroup = L(
                P(V(-1.5f, -1.5f), V(-0.5f, -1.5f), V(-0.5f, 1.5f), V(-1.5f, 1.5f)),
                P(V(0.5f, -1.5f), V(1.5f, -1.5f), V(1.5f, 1.5f), V(0.5f, 1.5f))
                );

            List <List <DTPolygon> > expectedPolygroups = L(
                L(
                    P(V(-2.5f, 0.5f), V(-1.5f, 0.5f), V(-1.5f, 1.5f), V(-2.5f, 1.5f)),
                    P(V(-2.5f, -0.5f), V(-1.5f, -0.5f), V(-1.5f, 0.5f), V(-2.5f, 0.5f)),
                    P(V(-2.5f, -1.5f), V(-1.5f, -1.5f), V(-1.5f, -0.5f), V(-2.5f, -0.5f))
                    ),
                L(
                    P(V(-0.5f, 0.5f), V(0.5f, 0.5f), V(0.5f, 1.5f), V(-0.5f, 1.5f)),
                    P(V(-0.5f, -0.5f), V(0.5f, -0.5f), V(0.5f, 0.5f), V(-0.5f, 0.5f)),
                    P(V(-0.5f, -1.5f), V(0.5f, -1.5f), V(0.5f, -0.5f), V(-0.5f, -0.5f))
                    ),
                L(
                    P(V(1.5f, 0.5f), V(2.5f, 0.5f), V(2.5f, 1.5f), V(1.5f, 1.5f)),
                    P(V(1.5f, -0.5f), V(2.5f, -0.5f), V(2.5f, 0.5f), V(1.5f, 0.5f)),
                    P(V(1.5f, -1.5f), V(2.5f, -1.5f), V(2.5f, -0.5f), V(1.5f, -0.5f))
                    )
                );

            // Clipper does this in a weird way and joins only the first polygroup into a single polygon
            List <List <DTPolygon> > expectedPolygroupsJoinedFirst = L(
                L(
                    P(V(-2.5f, -1.5f), V(-1.5f, -1.5f), V(-1.5f, 1.5f), V(-2.5f, 1.5f))
                    ),
                L(
                    P(V(-0.5f, 0.5f), V(0.5f, 0.5f), V(0.5f, 1.5f), V(-0.5f, 1.5f)),
                    P(V(-0.5f, -0.5f), V(0.5f, -0.5f), V(0.5f, 0.5f), V(-0.5f, 0.5f)),
                    P(V(-0.5f, -1.5f), V(0.5f, -1.5f), V(0.5f, -0.5f), V(-0.5f, -0.5f))
                    ),
                L(
                    P(V(1.5f, 0.5f), V(2.5f, 0.5f), V(2.5f, 1.5f), V(1.5f, 1.5f)),
                    P(V(1.5f, -0.5f), V(2.5f, -0.5f), V(2.5f, 0.5f), V(1.5f, 0.5f)),
                    P(V(1.5f, -1.5f), V(2.5f, -1.5f), V(2.5f, -0.5f), V(1.5f, -0.5f))
                    )
                );

            VerifyPolygroups(sub.SubtractPolygroup(subjectPolygroup, clipPolygroup), expectedPolygroups, expectedPolygroupsJoinedFirst);
        }
Example #5
0
        public static void ConvexBasic(IPolygonSubtractor sub)
        {
            // Basic corner clips (produces an 'L' shape)
            DTPolygon clip0 = Translate(square, V(-1, -1));                        // bottom left
            DTPolygon clip1 = Translate(square, V(1, -1));                         // bottom right
            DTPolygon clip2 = Translate(square, V(1, 1));                          // top right
            DTPolygon clip3 = Translate(square, V(-1, 1));                         // top left
            // Basic edge clips (produces a 'C' shape)
            DTPolygon clip4 = Translate(narrowRect, V(0, -1));                     // bottom
            DTPolygon clip5 = Translate(shortRect, V(1, 0));                       // right
            DTPolygon clip6 = Translate(narrowRect, V(0, 1));                      // top
            DTPolygon clip7 = Translate(shortRect, V(-1, 0));                      // left
            // Diamond clip (produces 4 triangles)
            DTPolygon clip8 = P(V(0, -1.5f), V(1.5f, 0), V(0, 1.5f), V(-1.5f, 0)); // start with bottom vertex

            // Basic corner clips (produces an 'L' shape)
            List <DTPolygon> expected0 = L(P(V(0, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0)));
            List <DTPolygon> expected1 = L(P(V(-1, -1), V(0, -1), V(0, 0), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected2 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 0), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0, 0), V(-1, 0)));
            // Basic edge clips (produces a 'C' shape)
            List <DTPolygon> expected4 = L(P(V(-1, -1), V(-0.5f, -1), V(-0.5f, 0), V(0.5f, 0), V(0.5f, -1), V(1, -1), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected5 = L(P(V(-1, -1), V(1, -1), V(1, -0.5f), V(0, -0.5f), V(0, 0.5f), V(1, 0.5f), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected6 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0.5f, 1), V(0.5f, 0), V(-0.5f, 0), V(-0.5f, 1), V(-1, 1)));
            List <DTPolygon> expected7 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0.5f), V(0, 0.5f), V(0, -0.5f), V(-1, -0.5f)));
            // Diamond clip (produces 4 triangles)
            List <DTPolygon> expected8 = L(
                P(V(-1, -0.5f), V(-1, -1), V(-0.5f, -1)),
                P(V(0.5f, -1), V(1, -1), V(1, -0.5f)),
                P(V(1, 0.5f), V(1, 1), V(0.5f, 1)),
                P(V(-0.5f, 1), V(-1, 1), V(-1, 0.5f))
                );

            // Complete removal
            List <DTPolygon> empty = new List <DTPolygon>();

            VerifyPolygons(sub.Subtract(square, clip0), expected0);
            VerifyPolygons(sub.Subtract(square, clip1), expected1);
            VerifyPolygons(sub.Subtract(square, clip2), expected2);
            VerifyPolygons(sub.Subtract(square, clip3), expected3);
            VerifyPolygons(sub.Subtract(square, clip4), expected4);
            VerifyPolygons(sub.Subtract(square, clip5), expected5);
            VerifyPolygons(sub.Subtract(square, clip6), expected6);
            VerifyPolygons(sub.Subtract(square, clip7), expected7);
            VerifyPolygons(sub.Subtract(square, clip8), expected8);

            // Complete removal
            VerifyPolygons(sub.Subtract(smallSquare, square), empty);
        }
    public static IEnumerator SimpleTest <T>(IExplosionExecutor ee, IPolygonSubtractor sub) where T : DestructibleObject
    {
        // Set a constant seed so that we get the same results every time
        UnityEngine.Random.InitState(12345);

        new GameObject("Main Camera").AddComponent <Camera>().transform.position = new Vector3(0, 50, -100);

        // Meaure the time to create all destructible objects
        T ring;

        using (Measure.ProfilerMarkers(ProfilerMarkers.SampleGroupDefinitions)) {
            ProfilerMarkers.Creation.Begin();
            ring = CreateRingObject <T>(true, 1, 4);
            ProfilerMarkers.Creation.End();

            ring.GetComponent <Rigidbody2D>().bodyType = RigidbodyType2D.Static;
        }
        yield return(null);

        ring.transform.position = new Vector2(0, 0);

        List <Explosion> explosions = new List <Explosion>()
        {
            new Explosion(-2, 0, 2, 4),
            new Explosion(2, 0, 2, 4),
        };

        using (Measure.ProfilerMarkers(ProfilerMarkers.SampleGroupDefinitions)) {
            ProfilerMarkers.ProcessExplosions.Begin();
            ee.ExecuteExplosions(explosions, DestructibleObject.FindAll(), sub);
            ProfilerMarkers.ProcessExplosions.End();
        }
        yield return(null);

        // Wait to observe whether the result is correct
        yield return(WaitFrames(60));

        CleanUp();
    }
Example #7
0
        public static void ConvexCasesProducingHoles(IPolygonSubtractor sub)
        {
            // Diamond hole in center
            DTPolygon clip0 = smallDiamond;
            // Diamond holes touching edge
            DTPolygon clip1 = Translate(smallDiamond, V(0, -0.5f)); // bottom
            DTPolygon clip2 = Translate(smallDiamond, V(0.5f, 0));  // right
            DTPolygon clip3 = Translate(smallDiamond, V(0, 0.5f));  // top
            DTPolygon clip4 = Translate(smallDiamond, V(-0.5f, 0)); // left
            // Exact diamond clip (produces 4 triangles)
            DTPolygon clip5 = diamond;

            // Diamond hole in center
            List <DTPolygon> expected0 = L(new DTPolygon(
                                               square.Contour,
                                               L(smallDiamond.Contour.AsEnumerable().Reverse().ToList())
                                               ));
            // Diamond holes touching edge
            List <DTPolygon> expected1     = L(P(V(-1, -1), V(0, -1), V(-0.5f, -0.5f), V(0, 0), V(0.5f, -0.5f), V(0, -1), V(1, -1), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected1Hole = L(new DTPolygon(
                                                   square.Contour,
                                                   L(clip1.Contour.AsEnumerable().Reverse().ToList())
                                                   ));
            List <DTPolygon> expected2     = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0.5f, -0.5f), V(0, 0), V(0.5f, 0.5f), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected2Hole = L(new DTPolygon(
                                                   square.Contour,
                                                   L(clip2.Contour.AsEnumerable().Reverse().ToList())
                                                   ));
            List <DTPolygon> expected3     = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0.5f, 0.5f), V(0, 0), V(-0.5f, 0.5f), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected3Hole = L(new DTPolygon(
                                                   square.Contour,
                                                   L(clip3.Contour.AsEnumerable().Reverse().ToList())
                                                   ));
            List <DTPolygon> expected4     = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0), V(-0.5f, 0.5f), V(0, 0), V(-0.5f, -0.5f), V(-1, 0)));
            List <DTPolygon> expected4Hole = L(new DTPolygon(
                                                   square.Contour,
                                                   L(clip4.Contour.AsEnumerable().Reverse().ToList())
                                                   ));
            // Exact diamond clip (produces 4 triangles)
            List <DTPolygon> expected5 = L(
                P(V(-1, 0), V(-1, -1), V(0, -1)),
                P(V(0, -1), V(1, -1), V(1, 0)),
                P(V(1, 0), V(1, 1), V(0, 1)),
                P(V(0, 1), V(-1, 1), V(-1, 0))
                );
            List <DTPolygon> expected5Hole = L(new DTPolygon(
                                                   square.Contour,
                                                   L(clip5.Contour.AsEnumerable().Reverse().ToList())
                                                   ));
            List <DTPolygon> expected5Single0 = L(P(V(-1, -1), V(0, -1), V(-1, 0), V(0, 1), V(1, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected5Single1 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, -1), V(-1, 0), V(0, 1), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected5Single2 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(1, 0), V(0, -1), V(-1, 0), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected5Single3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0), V(0, 1), V(1, 0), V(0, -1), V(-1, 0)));

            VerifyPolygons(sub.Subtract(square, clip0), expected0);
            VerifyPolygons(sub.Subtract(square, clip1), expected1, expected1Hole);
            VerifyPolygons(sub.Subtract(square, clip2), expected2, expected2Hole);
            VerifyPolygons(sub.Subtract(square, clip3), expected3, expected3Hole);
            VerifyPolygons(sub.Subtract(square, clip4), expected4, expected4Hole);
            VerifyPolygons(sub.Subtract(square, clip5), expected5, expected5Hole, expected5Single0, expected5Single1, expected5Single2, expected5Single3);
        }
Example #8
0
        public static void ConvexDegenerateNoIntersection(IPolygonSubtractor sub)
        {
            // Half-overlapping edges
            DTPolygon clip0 = Translate(diamond, V(0.5f, -1.5f));          // bottom right edge shared, Q shifted down-left
            DTPolygon clip1 = Translate(diamond, V(1.5f, -0.5f));          // bottom right edge shared, Q shifted up-right
            DTPolygon clip2 = Translate(diamond, V(1.5f, 0.5f));           // top right edge shared, Q shifted down-right
            DTPolygon clip3 = Translate(diamond, V(0.5f, 1.5f));           // top right edge shared, Q shifted up-left
            DTPolygon clip4 = Translate(diamond, V(-0.5f, 1.5f));          // top left edge shared, Q shifted up-right
            DTPolygon clip5 = Translate(diamond, V(-1.5f, 0.5f));          // top left edge shared, Q shifted down-left
            DTPolygon clip6 = Translate(diamond, V(-1.5f, -0.5f));         // bottom left edge shared, Q shifted up-left
            DTPolygon clip7 = Translate(diamond, V(-0.5f, -1.5f));         // bottom left edge shared, Q shifted down-right
            // P edge completely inside Q edge
            DTPolygon clip8  = Translate(diamond, V(0.75f, -0.75f));       // bottom right edge inside Q edge
            DTPolygon clip9  = Translate(diamond, V(0.75f, 0.75f));        // top right edge inside Q edge
            DTPolygon clip10 = Translate(diamond, V(-0.75f, 0.75f));       // top left edge inside Q edge
            DTPolygon clip11 = Translate(diamond, V(-0.75f, -0.75f));      // bottom left edge inside Q edge
            // P edge completely contains Q edge
            DTPolygon clip12 = Translate(smallDiamond, V(0.75f, -0.75f));  // bottom right edge contains Q edge
            DTPolygon clip13 = Translate(smallDiamond, V(0.75f, 0.75f));   // top right edge contains Q edge
            DTPolygon clip14 = Translate(smallDiamond, V(-0.75f, 0.75f));  // top left edge contains Q edge
            DTPolygon clip15 = Translate(smallDiamond, V(-0.75f, -0.75f)); // bottom left edge contains Q edge
            // P edge and Q edge are the same
            DTPolygon clip16 = Translate(diamond, V(1, -1));               // bottom right edge same
            DTPolygon clip17 = Translate(diamond, V(1, 1));                // top right edge same
            DTPolygon clip18 = Translate(diamond, V(-1, 1));               // top left edge same
            DTPolygon clip19 = Translate(diamond, V(-1, -1));              // bottom left edge same
            // Single shared vertex (octagon)
            DTPolygon clip20 = Translate(octagon, V(-2, -2));              // octagon, bottom left vertex same
            DTPolygon clip21 = Translate(octagon, V(2, -2));               // octagon, bottom right vertex same
            DTPolygon clip22 = Translate(octagon, V(2, 2));                // octagon, top left vertex same
            DTPolygon clip23 = Translate(octagon, V(-2, 2));               // octagon, top right vertex same
            // Single shared vertex (diamond)
            DTPolygon clip24 = Translate(diamond, V(-1, -2));              // diamond top, square bottom left vertex same
            DTPolygon clip25 = Translate(diamond, V(1, -2));               // diamond top, square bottom right vertex same
            DTPolygon clip26 = Translate(diamond, V(-1, 2));               // diamond bottom, square top left vertex same
            DTPolygon clip27 = Translate(diamond, V(1, 2));                // diamond bottom, square top right vertex same
            // Q single vertex inside P edge
            DTPolygon clip28 = Translate(square, V(1.5f, -1.5f));          // bottom right edge contains Q vertex
            DTPolygon clip29 = Translate(square, V(1.5f, 1.5f));           // top right edge contains Q vertex
            DTPolygon clip30 = Translate(square, V(-1.5f, 1.5f));          // top left edge contains Q vertex
            DTPolygon clip31 = Translate(square, V(-1.5f, -1.5f));         // bottom left edge contains Q vertex
            // P single vertex inside Q edge
            DTPolygon clip32 = Translate(diamond, V(-1.5f, -1.5f));        // bottom left vertex in Q edge
            DTPolygon clip33 = Translate(diamond, V(1.5f, -1.5f));         // bottom right vertex in Q edge
            DTPolygon clip34 = Translate(diamond, V(1.5f, 1.5f));          // top right vertex in Q edge
            DTPolygon clip35 = Translate(diamond, V(-1.5f, 1.5f));         // top left vertex in Q edge

            List <DTPolygon> expectedSquare       = L(square);
            List <DTPolygon> expectedDiamond      = L(diamond);
            List <DTPolygon> expectedSmallDiamond = L(smallDiamond);
            List <DTPolygon> expectedOctagon      = L(octagon);

            VerifyPolygons(sub.Subtract(diamond, clip0), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip1), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip2), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip3), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip4), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip5), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip6), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip7), expectedDiamond);
            VerifyPolygons(sub.Subtract(smallDiamond, clip8), expectedSmallDiamond);
            VerifyPolygons(sub.Subtract(smallDiamond, clip9), expectedSmallDiamond);
            VerifyPolygons(sub.Subtract(smallDiamond, clip10), expectedSmallDiamond);
            VerifyPolygons(sub.Subtract(smallDiamond, clip11), expectedSmallDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip12), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip13), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip14), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip15), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip16), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip17), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip18), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip19), expectedDiamond);
            VerifyPolygons(sub.Subtract(octagon, clip20), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip21), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip22), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip23), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip24), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip25), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip26), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip27), expectedOctagon);
            VerifyPolygons(sub.Subtract(diamond, clip28), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip29), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip30), expectedDiamond);
            VerifyPolygons(sub.Subtract(diamond, clip31), expectedDiamond);
            VerifyPolygons(sub.Subtract(octagon, clip32), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip33), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip34), expectedOctagon);
            VerifyPolygons(sub.Subtract(octagon, clip35), expectedOctagon);
        }
Example #9
0
        public static void ConvexDegenerateIntersection(IPolygonSubtractor sub)
        {
            // Shared corners (produces an 'L' shape)
            DTPolygon clip0 = Translate(smallSquare, V(-0.5f, -0.5f)); // bottom left
            DTPolygon clip1 = Translate(smallSquare, V(0.5f, -0.5f));  // bottom right
            DTPolygon clip2 = Translate(smallSquare, V(0.5f, 0.5f));   // top right
            DTPolygon clip3 = Translate(smallSquare, V(-0.5f, 0.5f));  // top left
            // Q edge inside P edge (produces a 'C' shape)
            DTPolygon clip4 = Translate(smallSquare, V(0, -0.5f));     // bottom
            DTPolygon clip5 = Translate(smallSquare, V(0.5f, 0));      // right
            DTPolygon clip6 = Translate(smallSquare, V(0, 0.5f));      // top
            DTPolygon clip7 = Translate(smallSquare, V(-0.5f, 0));     // left
            // Half same
            DTPolygon clip8  = Translate(shortRect, V(0, -0.5f));      // bottom half
            DTPolygon clip9  = Translate(narrowRect, V(0.5f, 0));      // right half
            DTPolygon clip10 = Translate(shortRect, V(0, 0.5f));       // top half
            DTPolygon clip11 = Translate(narrowRect, V(-0.5f, 0));     // left half
            // Diamond on corners
            DTPolygon clip12 = Translate(diamond, V(-1, -1));          // bottom left
            DTPolygon clip13 = Translate(diamond, V(1, -1));           // bottom right
            DTPolygon clip14 = Translate(diamond, V(1, 1));            // top right
            DTPolygon clip15 = Translate(diamond, V(-1, 1));           // top left
            // Diamond on edges
            DTPolygon clip16 = Translate(diamond, V(0, -1));           // bottom
            DTPolygon clip17 = Translate(diamond, V(1, 0));            // right
            DTPolygon clip18 = Translate(diamond, V(0, 1));            // top
            DTPolygon clip19 = Translate(diamond, V(-1, 0));           // left

            // Basic corner clips (produces an 'L' shape)
            List <DTPolygon> expected0 = L(P(V(0, 0), V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0)));
            List <DTPolygon> expected1 = L(P(V(-1, -1), V(0, -1), V(0, 0), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected2 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 0), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected3 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(0, 0), V(-1, 0)));
            // Basic edge clips (produces a 'C' shape)
            List <DTPolygon> expected4 = L(P(V(-1, -1), V(-0.5f, -1), V(-0.5f, 0), V(0.5f, 0), V(0.5f, -1), V(1, -1), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected5 = L(P(V(-1, -1), V(1, -1), V(1, -0.5f), V(0, -0.5f), V(0, 0.5f), V(1, 0.5f), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected6 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0.5f, 1), V(0.5f, 0), V(-0.5f, 0), V(-0.5f, 1), V(-1, 1)));
            List <DTPolygon> expected7 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0.5f), V(0, 0.5f), V(0, -0.5f), V(-1, -0.5f)));
            // Half same
            List <DTPolygon> expected8  = L(P(V(-1, 0), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected9  = L(P(V(-1, -1), V(0, -1), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected10 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(-1, 0)));
            List <DTPolygon> expected11 = L(P(V(0, -1), V(1, -1), V(1, 1), V(0, 1)));
            // Diamond on corners
            List <DTPolygon> expected12 = L(P(V(0, -1), V(1, -1), V(1, 1), V(-1, 1), V(-1, 0)));
            List <DTPolygon> expected13 = L(P(V(-1, -1), V(0, -1), V(1, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected14 = L(P(V(-1, -1), V(1, -1), V(1, 0), V(0, 1), V(-1, 1)));
            List <DTPolygon> expected15 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 1), V(-1, 0)));
            // Diamond on edges
            List <DTPolygon> expected16 = L(P(V(-1, -1), V(0, 0), V(1, -1), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected17 = L(P(V(-1, -1), V(1, -1), V(0, 0), V(1, 1), V(-1, 1)));
            List <DTPolygon> expected18 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(0, 0), V(-1, 1)));
            List <DTPolygon> expected19 = L(P(V(-1, -1), V(1, -1), V(1, 1), V(-1, 1), V(0, 0)));

            // Complete removal
            List <DTPolygon> empty = new List <DTPolygon>();

            // Complete removal
            VerifyPolygons(sub.Subtract(square, square), empty);

            VerifyPolygons(sub.Subtract(square, clip0), expected0);
            VerifyPolygons(sub.Subtract(square, clip1), expected1);
            VerifyPolygons(sub.Subtract(square, clip2), expected2);
            VerifyPolygons(sub.Subtract(square, clip3), expected3);
            VerifyPolygons(sub.Subtract(square, clip4), expected4);
            VerifyPolygons(sub.Subtract(square, clip5), expected5);
            VerifyPolygons(sub.Subtract(square, clip6), expected6);
            VerifyPolygons(sub.Subtract(square, clip7), expected7);
            VerifyPolygons(sub.Subtract(square, clip8), expected8);
            VerifyPolygons(sub.Subtract(square, clip9), expected9);
            VerifyPolygons(sub.Subtract(square, clip10), expected10);
            VerifyPolygons(sub.Subtract(square, clip11), expected11);
            VerifyPolygons(sub.Subtract(square, clip12), expected12);
            VerifyPolygons(sub.Subtract(square, clip13), expected13);
            VerifyPolygons(sub.Subtract(square, clip14), expected14);
            VerifyPolygons(sub.Subtract(square, clip15), expected15);
            VerifyPolygons(sub.Subtract(square, clip16), expected16);
            VerifyPolygons(sub.Subtract(square, clip17), expected17);
            VerifyPolygons(sub.Subtract(square, clip18), expected18);
            VerifyPolygons(sub.Subtract(square, clip19), expected19);
        }
 public static IEnumerator OneTimeExplosionTestLargeComplexRings <T>(IExplosionExecutor ee, IPolygonSubtractor sub)
     where T : DestructibleObject
 {
     yield return(OneTimeExplosionTest <T>(ee, sub, 10, 1, true, 10.0f, 240, 2, 1));
 }
 public static IEnumerator OneTimeExplosionTestManyRings <T>(IExplosionExecutor ee, IPolygonSubtractor sub)
     where T : DestructibleObject
 {
     yield return(OneTimeExplosionTest <T>(ee, sub, 100, 1, true, 1.0f, 24, 10, 10));
 }
 public static IEnumerator ContinuousExplosionTestManyRings <T>(IExplosionExecutor ee, IPolygonSubtractor sub)
     where T : DestructibleObject
 {
     yield return(ContinuousExplosionTest <T>(ee, sub, 1, 1, Time.fixedDeltaTime, true, 1.0f, 24, 10, 10, 100, 200));
 }
Example #13
0
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            foreach (var exp in explosions)
            {
                List <List <DTPolygon> > relevantObjectPolygons = new List <List <DTPolygon> >();
                List <int> relevantObjectIndices = new List <int>();
                for (int i = 0; i < dtObjectList.Count; ++i)
                {
                    var dtObj = dtObjectList[i];

                    // Do basic AABB-circle check to see whether we can skip processing this destructible object with this explosion
                    int bc = DTUtility.BoundsCheck(dtObj, exp);
                    if (bc == -1)
                    {
                        // Object is not affected by explosion
                        continue;
                    }
                    else if (bc == 1)
                    {
                        // Object is completely removed by explosion
                        dtObjectList[i] = null;
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Add object to the input list for the subtractor
                        relevantObjectPolygons.Add(dtObj.GetTransformedPolygonList());
                        relevantObjectIndices.Add(i);
                        continue;
                    }
                }

                var result = subtractor.SubtractBulk(relevantObjectPolygons, new DTPolygon[] { exp.DTPolygon });

                // Iterate results corresponding to each input polygon group
                for (int i = 0; i < result.Count; i++)
                {
                    // Add new destructible objects for any output polygons that could not be matched with an input polygon
                    if (i >= relevantObjectPolygons.Count)
                    {
                        GameObject         go        = new GameObject();
                        DestructibleObject newObj    = go.AddComponent <DestructibleObject>();
                        List <DTPolygon>   polygroup = result[i][0];
                        newObj.ApplyTransformedPolygonList(polygroup);
                        pendingAdditions.Add(newObj);

                        continue;
                    }

                    // We know that these output polygons correspond to one or more pieces of this existing destructible object
                    DestructibleObject dtObj = dtObjectList[relevantObjectIndices[i]];

                    if (result[i].Count == 0)
                    {
                        // If no output polygons, remove the current destrucible object
                        dtObjectList[relevantObjectIndices[i]] = null;
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                        foreach (List <DTPolygon> polygroup in result[i])
                        {
                            if (polygroup != result[i].Last())
                            {
                                // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity
                                GameObject         go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                                DestructibleObject newObj = go.GetComponent <DestructibleObject>();

                                // Apply the new clipped polygon
                                newObj.ApplyTransformedPolygonList(polygroup);

                                // Add it to the objectList, but not until after finished processing this explosion
                                pendingAdditions.Add(newObj);
                                continue;
                            }
                            else
                            {
                                // Reuse the existing GameObject by applying the new clipped polygon to it
                                dtObj.ApplyTransformedPolygonList(polygroup);
                                continue;
                            }
                        }
                    }
                }

                // Delete any entries that were set to null
                for (int i = 0; i < dtObjectList.Count; ++i)
                {
                    if (dtObjectList[i] == null)
                    {
                        dtObjectList.RemoveAt(i--);
                    }
                }

                // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
                dtObjectList.AddRange(pendingAdditions);
                pendingAdditions.Clear();
            }
        }
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            ORourkeSubtractor oRourkeSub = (ORourkeSubtractor)subtractor;

            if (oRourkeSub == null)
            {
                throw new NotSupportedException("This explosion executor only supports ORourkeSubtractor");
            }

            TriangleNetTriangulator.Instance.callCount = 0;

            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            foreach (var exp in explosions)
            {
                for (int i = 0; i < dtObjectList.Count; i++)
                {
                    // Remove this object from the list if it has been destroyed
                    if (dtObjectList[i] == null)
                    {
                        dtObjectList.RemoveAt(i--);
                        continue;
                    }
                    // Cast this DO to an advanced DO
                    var dtObj = (DO_Advanced_Triangle_Clip_Collide)dtObjectList[i];
                    if (dtObj == null)
                    {
                        throw new NotSupportedException("This explosion executor only supports DO_Advanced_Triangle_Clip_Collide");
                    }

                    // Do basic AABB-circle check to see whether we can skip processing this destructible object with this explosion
                    int bc = DTUtility.BoundsCheck(dtObj, exp);
                    if (bc == -1)
                    {
                        // Object is not affected by explosion
                        continue;
                    }
                    else if (bc == 1)
                    {
                        // Object is completely removed by explosion
                        dtObjectList.RemoveAt(i--);
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }

                    // Leave the polygroup in local coordinates and transform the explosion instead to the DO's space.
                    // Note that this is stored in the subject DO and will be referenced by all PolygroupModifiers,
                    // so changes to the original DO will affect all PolygroupModifiers. This shouldn't cause any
                    // problems since we only need the indices anyway.
                    PolygroupModifier inputPolygroup       = dtObj.GetPolygroup();
                    List <Vector2>    transformedExplosion = dtObj.InverseTransformPoints(exp.DTPolygon.Contour);

                    // Subtract explosion polygon from destructible object polygon group
                    DTProfilerMarkers.SubtractPolygroup.Begin();
                    List <PolygroupModifier> result = oRourkeSub.AdvancedSubtractPolygroup(inputPolygroup, transformedExplosion);
                    DTProfilerMarkers.SubtractPolygroup.End();

                    int count = result.Count();
                    if (count == 0)
                    {
                        // If no output polygons, remove the current destrucible object
                        dtObjectList.RemoveAt(i--);
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                        for (int j = 0; j < result.Count; j++)
                        {
                            if (j < result.Count - 1)
                            {
                                // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity and also maintain the same collider + mesh
                                GameObject go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                                var        newObj = go.GetComponent <DO_Advanced_Triangle_Clip_Collide>();
                                newObj.SetPolygroup(new PolygroupModifier(new DTConvexPolygroup(inputPolygroup.originalPolygroup), inputPolygroup.keptIndices, null));

                                // Apply the new clipped polygon list
                                newObj.ApplyPolygroupModifier(result[j]);

                                // Add it to the objectList, but not until after finished processing this explosion
                                pendingAdditions.Add(newObj);
                                continue;
                            }
                            else
                            {
                                // Reuse the existing GameObject by applying the new clipped polygon to it
                                dtObj.ApplyPolygroupModifier(result[j]);
                                continue;
                            }
                        }
                    }
                }
                // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
                dtObjectList.AddRange(pendingAdditions);
                pendingAdditions.Clear();
            }

            Debug.Log("# Objects:" + dtObjectList.Count);
            Debug.Log("# Polygons:" + dtObjectList.Sum(obj => obj.GetTransformedPolygonList().Count));
            Debug.Log("# Triangulation Calls:" + TriangleNetTriangulator.Instance.callCount);
        }
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            var explosionPolygons     = explosions.Select(e => e.DTPolygon);
            var dtObjectPolygons      = dtObjectList.Select(o => o.GetTransformedPolygonList());
            int numInputPolygonGroups = dtObjectPolygons.Count();

            var result = subtractor.SubtractBulk(dtObjectPolygons, explosionPolygons);

            // Iterate results corresponding to each input polygon group
            for (int i = 0; i < result.Count; i++)
            {
                // Add new destructible objects for any output polygon groups that could not be matched with an input polygon group
                if (i >= numInputPolygonGroups)
                {
                    GameObject         go        = new GameObject();
                    DestructibleObject newObj    = go.AddComponent <DestructibleObject>();
                    List <DTPolygon>   polygroup = result[i][0];
                    newObj.ApplyTransformedPolygonList(polygroup);
                    pendingAdditions.Add(newObj);

                    continue;
                }

                // We know that these output polygons correspond to one or more pieces of this existing destructible object
                DestructibleObject dtObj = dtObjectList[i];

                if (result[i].Count == 0)
                {
                    // If no output polygons, remove the current destrucible object
                    dtObjectList[i] = null;
                    UnityEngine.Object.Destroy(dtObj.gameObject);
                    continue;
                }
                else
                {
                    // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                    foreach (List <DTPolygon> polygroup in result[i])
                    {
                        if (polygroup != result[i].Last())
                        {
                            // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity
                            GameObject         go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                            DestructibleObject newObj = go.GetComponent <DestructibleObject>();

                            // Apply the new clipped polygon
                            newObj.ApplyTransformedPolygonList(polygroup);

                            // Add it to the objectList, but not until after finished processing this explosion
                            pendingAdditions.Add(newObj);
                            continue;
                        }
                        else
                        {
                            // Reuse the existing GameObject by applying the new clipped polygon to it
                            dtObj.ApplyTransformedPolygonList(polygroup);
                            continue;
                        }
                    }
                }
            }

            // Delete any entries that were set to null
            for (int i = 0; i < dtObjectList.Count; ++i)
            {
                if (dtObjectList[i] == null)
                {
                    dtObjectList.RemoveAt(i--);
                }
            }

            // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
            dtObjectList.AddRange(pendingAdditions);
            pendingAdditions.Clear();
        }
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            TriangleNetTriangulator.Instance.callCount = 0;

            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            foreach (var exp in explosions)
            {
                for (int i = 0; i < dtObjectList.Count; i++)
                {
                    DestructibleObject dtObj = dtObjectList[i];

                    // Do basic AABB-circle check to see whether we can skip processing this destructible object with this explosion
                    int bc = DTUtility.BoundsCheck(dtObj, exp);
                    if (bc == -1)
                    {
                        // Object is not affected by explosion
                        continue;
                    }
                    else if (bc == 1)
                    {
                        // Object is completely removed by explosion
                        dtObjectList.RemoveAt(i--);
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }

                    List <DTPolygon> inputPolygroup = dtObj.GetTransformedPolygonList();

                    // Subtract explosion polygon from destructible object polygon group
                    DTProfilerMarkers.SubtractPolygroup.Begin();
                    List <List <DTPolygon> > result = subtractor.SubtractPolygroup(inputPolygroup, new List <DTPolygon>()
                    {
                        exp.DTPolygon
                    });
                    DTProfilerMarkers.SubtractPolygroup.End();

                    int count = result.Count();
                    if (count == 0)
                    {
                        // If no output polygons, remove the current destrucible object
                        dtObjectList.RemoveAt(i--);
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                        foreach (List <DTPolygon> polygroup in result)
                        {
                            if (polygroup != result.Last())
                            {
                                // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity
                                GameObject         go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                                DestructibleObject newObj = go.GetComponent <DestructibleObject>();

                                // Apply the new clipped polygon list
                                newObj.ApplyTransformedPolygonList(polygroup);

                                // Add it to the objectList, but not until after finished processing this explosion
                                pendingAdditions.Add(newObj);
                                continue;
                            }
                            else
                            {
                                // Reuse the existing GameObject by applying the new clipped polygon to it
                                dtObj.ApplyTransformedPolygonList(polygroup);
                                continue;
                            }
                        }
                    }
                }
                // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
                dtObjectList.AddRange(pendingAdditions);
                pendingAdditions.Clear();
            }

            Debug.Log("# Objects:" + dtObjectList.Count);
            Debug.Log("# Polygons:" + dtObjectList.Sum(obj => obj.GetTransformedPolygonList().Count));
            Debug.Log("# Triangulation Calls:" + TriangleNetTriangulator.Instance.callCount);
        }