Ejemplo n.º 1
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);
        }
        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);
        }