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(); }
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(); }
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); }
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(); }
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); }
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); }
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)); }
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); }