// ********
        //
        // Routine:     void FindIslands(List<ModelAssets> Assets)
        // Author:      Mathew Kaustinen, Boomer Labs LLC ([email protected])
        // Purpose:     Take the list of tris (faces) containing vertices. Create a unique "island" for each group of non-contiguous vertices
        //
        // ********
        public static void FindIslands(List<ModelAsset> Assets)
        {
            int[] foundIsland = new int[3];              // where we store shared island values (up to 3) for a given tri

            foreach (ModelAsset asset in Assets)
            {
                // create an array for all of the verts, each entry indicates which island the vert is part of
                int vert_array_size = asset.numberOfVerts; // fix this later, should store verts in the face array 0 indexed, see comment in ReadObjFile
                int[] vert_array = new int[vert_array_size];

                // Set to -1 to indicate that each vertex is not yet part of any island
                for (int i = 0; i < vert_array_size; i++)
                {
                    vert_array[i] = -1;
                }

                // Take a look at each tri (face) and see if any of its vertices are part of an existing island
                // Note that each vertex could be part of a different island, hence all of the extra work to reconcile tris
                // that are part of mulitple islands (that will need collapsing)
                foreach (Tri tri in asset.TriList)
                {
                    // store the 3 indexes in question for tri (ie. face)
                    int vert1 = tri.indexA;
                    int vert2 = tri.indexB;
                    int vert3 = tri.indexC;

                    int     foundCount = 0;     // how many island matches have we found (0 to 3)
                    int     vertIsland1 = -1;   // The associated island for each vertex
                    int     vertIsland2 = -1;
                    int     vertIsland3 = -1;

                    // Check to see if the vertex is already part of an island, do this 3 times (once for each vert)
                    // We know if a vert is part of an island if the vert_array value is not -1
                    if (vert_array[vert1] >= 0)
                    {
                        vertIsland1 = vert_array[vert1];
                        foundCount = 1;
                        foundIsland[0] = vert_array[vert1];
                    }

                    if (vert_array[vert2] >= 0)
                    {
                        vertIsland2 = vert_array[vert2];
                        if (vertIsland2 != vertIsland1) {
                            foundIsland[foundCount] = vert_array[vert2];
                            foundCount++;
                        }
                    }

                    if (vert_array[vert3] >= 0)
                    {
                        vertIsland3 = vert_array[vert3];
                        if ((vertIsland3 != vertIsland1) && (vertIsland3 != vertIsland2))
                        {
                            foundIsland[foundCount] = vert_array[vert3];
                            foundCount++;
                        }
                    }

                    // If we didn't find any islands, then create a new one at the end of the Island List
                    if (foundCount == 0)
                    {
                        int islandCount = asset.Islands.Count();
                        vert_array[vert1] = islandCount;
                        vert_array[vert2] = islandCount;
                        vert_array[vert3] = islandCount;

                        Island newIsland = new Island();
                        newIsland.TriList.Add(tri);
                        // add new island to asset
                        asset.Islands.Add(newIsland);
                    }

                    // Otherwise we need to use (and possibly collapse) islands
                    else
                    {
                        // Easy case, only 1 island is found, so use that for all 3 vertex
                        if (foundCount == 1)
                        {
                            // Set all 3 verts to the found island value
                            vert_array[vert1] = foundIsland[0];
                            vert_array[vert2] = foundIsland[0];
                            vert_array[vert3] = foundIsland[0];

                            // Add the tri to the Island Array
                            asset.Islands[foundIsland[0]].TriList.Add(tri);
                        }
                        else if (foundCount == 2)
                        {
                            // find the lowest value, use that island, prepare the other one for removal
                            int indexToUse = foundIsland[0];
                            int indexToRemove = foundIsland[1];
                            if (indexToRemove < indexToUse)
                            {
                                int temp = indexToUse;
                                indexToUse = indexToRemove;
                                indexToRemove = temp;
                            }
                            // move all of tris that are part of the higher numbered island to the lower
                            foreach (Tri removetri in asset.Islands[indexToRemove].TriList) {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }
                            // since we've moved all of these tris, zero the list for the old island
                            // Eventually we'll probably want to remove the island all together
                            asset.Islands[indexToRemove].TriList.Clear();

                            // replace all references to the remove values
                            for (int i = 0; i < vert_array_size; i++)
                            {
                                if (vert_array[i] == indexToRemove)
                                    vert_array[i] = indexToUse;
                            }

                            // OK, now write the tri that we're working on originally
                            vert_array[vert1] = indexToUse;
                            vert_array[vert2] = indexToUse;
                            vert_array[vert3] = indexToUse;

                            asset.Islands[indexToUse].TriList.Add(tri);
                        }
                        else // rare case where all 3 sides are from different islands
                        {
                            int indexToUse;
                            int indexToRemove1;
                            int indexToRemove2;

                            // Find the lowest value
                            if ((foundIsland[0] < foundIsland[1]) && (foundIsland[0] < foundIsland[2])) {
                                indexToUse = foundIsland[0];
                                indexToRemove1 = foundIsland[1];
                                indexToRemove2 = foundIsland[2];
                            } else if ((foundIsland[1] < foundIsland[0]) && (foundIsland[1] < foundIsland[2])) {
                                indexToUse = foundIsland[1];
                                indexToRemove1 = foundIsland[0];
                                indexToRemove2 = foundIsland [2];
                            } else {
                                indexToUse = foundIsland[2];
                                indexToRemove1 = foundIsland[0];
                                indexToRemove2 = foundIsland [1];

                            }

                            // move all of tris that are part of the higher numbered island to the lower
                            foreach (Tri removetri in asset.Islands[indexToRemove1].TriList)
                            {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }

                            // and again for the third island
                            foreach (Tri removetri in asset.Islands[indexToRemove2].TriList)
                            {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }

                            // since we've moved all of these tris, zero the list for the old island
                            // Eventually we'll probably want to remove the island all together
                            asset.Islands[indexToRemove1].TriList.Clear();
                            asset.Islands[indexToRemove2].TriList.Clear();
                            //asset.Islands.RemoveAt(indextoRemove);    // don't do this now, will mess up island numbering

                            // replace all references to the remove values
                            for (int i = 0; i < vert_array_size; i++)
                            {
                                if ((vert_array[i] == indexToRemove1) || (vert_array[i] == indexToRemove2))
                                    vert_array[i] = indexToUse;
                            }

                            // OK, now write the tri that we're working on originally
                            vert_array[vert1] = indexToUse;
                            vert_array[vert2] = indexToUse;
                            vert_array[vert3] = indexToUse;

                            asset.Islands[indexToUse].TriList.Add(tri);
                        }
                    }
                }
                // Clean up by removing Islands that have no tris, but do this in reverse order (for both speed and stability)
                for (int i = asset.Islands.Count()-1; i>=0; i--)
                {
                    if (asset.Islands[i].TriList.Count() == 0)
                    {
                        asset.Islands.RemoveAt(i);
                    }
                }
            }
        }
Beispiel #2
0
        // ********
        //
        // Routine:     void FindIslands(List<ModelAssets> Assets)
        // Author:      Mathew Kaustinen, Boomer Labs LLC ([email protected])
        // Purpose:     Take the list of tris (faces) containing vertices. Create a unique "island" for each group of non-contiguous vertices
        //
        // ********
        public static void FindIslands(List <ModelAsset> Assets)
        {
            int[] foundIsland = new int[3];              // where we store shared island values (up to 3) for a given tri

            foreach (ModelAsset asset in Assets)
            {
                // create an array for all of the verts, each entry indicates which island the vert is part of
                int   vert_array_size = asset.numberOfVerts; // fix this later, should store verts in the face array 0 indexed, see comment in ReadObjFile
                int[] vert_array      = new int[vert_array_size];

                // Set to -1 to indicate that each vertex is not yet part of any island
                for (int i = 0; i < vert_array_size; i++)
                {
                    vert_array[i] = -1;
                }

                // Take a look at each tri (face) and see if any of its vertices are part of an existing island
                // Note that each vertex could be part of a different island, hence all of the extra work to reconcile tris
                // that are part of mulitple islands (that will need collapsing)
                foreach (Tri tri in asset.TriList)
                {
                    // store the 3 indexes in question for tri (ie. face)
                    int vert1 = tri.indexA;
                    int vert2 = tri.indexB;
                    int vert3 = tri.indexC;

                    int foundCount  = 0;        // how many island matches have we found (0 to 3)
                    int vertIsland1 = -1;       // The associated island for each vertex
                    int vertIsland2 = -1;
                    int vertIsland3 = -1;

                    // Check to see if the vertex is already part of an island, do this 3 times (once for each vert)
                    // We know if a vert is part of an island if the vert_array value is not -1
                    if (vert_array[vert1] >= 0)
                    {
                        vertIsland1    = vert_array[vert1];
                        foundCount     = 1;
                        foundIsland[0] = vert_array[vert1];
                    }

                    if (vert_array[vert2] >= 0)
                    {
                        vertIsland2 = vert_array[vert2];
                        if (vertIsland2 != vertIsland1)
                        {
                            foundIsland[foundCount] = vert_array[vert2];
                            foundCount++;
                        }
                    }

                    if (vert_array[vert3] >= 0)
                    {
                        vertIsland3 = vert_array[vert3];
                        if ((vertIsland3 != vertIsland1) && (vertIsland3 != vertIsland2))
                        {
                            foundIsland[foundCount] = vert_array[vert3];
                            foundCount++;
                        }
                    }

                    // If we didn't find any islands, then create a new one at the end of the Island List
                    if (foundCount == 0)
                    {
                        int islandCount = asset.Islands.Count();
                        vert_array[vert1] = islandCount;
                        vert_array[vert2] = islandCount;
                        vert_array[vert3] = islandCount;

                        Island newIsland = new Island();
                        newIsland.TriList.Add(tri);
                        // add new island to asset
                        asset.Islands.Add(newIsland);
                    }

                    // Otherwise we need to use (and possibly collapse) islands
                    else
                    {
                        // Easy case, only 1 island is found, so use that for all 3 vertex
                        if (foundCount == 1)
                        {
                            // Set all 3 verts to the found island value
                            vert_array[vert1] = foundIsland[0];
                            vert_array[vert2] = foundIsland[0];
                            vert_array[vert3] = foundIsland[0];

                            // Add the tri to the Island Array
                            asset.Islands[foundIsland[0]].TriList.Add(tri);
                        }
                        else if (foundCount == 2)
                        {
                            // find the lowest value, use that island, prepare the other one for removal
                            int indexToUse    = foundIsland[0];
                            int indexToRemove = foundIsland[1];
                            if (indexToRemove < indexToUse)
                            {
                                int temp = indexToUse;
                                indexToUse    = indexToRemove;
                                indexToRemove = temp;
                            }
                            // move all of tris that are part of the higher numbered island to the lower
                            foreach (Tri removetri in asset.Islands[indexToRemove].TriList)
                            {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }
                            // since we've moved all of these tris, zero the list for the old island
                            // Eventually we'll probably want to remove the island all together
                            asset.Islands[indexToRemove].TriList.Clear();

                            // replace all references to the remove values
                            for (int i = 0; i < vert_array_size; i++)
                            {
                                if (vert_array[i] == indexToRemove)
                                {
                                    vert_array[i] = indexToUse;
                                }
                            }

                            // OK, now write the tri that we're working on originally
                            vert_array[vert1] = indexToUse;
                            vert_array[vert2] = indexToUse;
                            vert_array[vert3] = indexToUse;

                            asset.Islands[indexToUse].TriList.Add(tri);
                        }
                        else // rare case where all 3 sides are from different islands
                        {
                            int indexToUse;
                            int indexToRemove1;
                            int indexToRemove2;

                            // Find the lowest value
                            if ((foundIsland[0] < foundIsland[1]) && (foundIsland[0] < foundIsland[2]))
                            {
                                indexToUse     = foundIsland[0];
                                indexToRemove1 = foundIsland[1];
                                indexToRemove2 = foundIsland[2];
                            }
                            else if ((foundIsland[1] < foundIsland[0]) && (foundIsland[1] < foundIsland[2]))
                            {
                                indexToUse     = foundIsland[1];
                                indexToRemove1 = foundIsland[0];
                                indexToRemove2 = foundIsland [2];
                            }
                            else
                            {
                                indexToUse     = foundIsland[2];
                                indexToRemove1 = foundIsland[0];
                                indexToRemove2 = foundIsland [1];
                            }

                            // move all of tris that are part of the higher numbered island to the lower
                            foreach (Tri removetri in asset.Islands[indexToRemove1].TriList)
                            {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }

                            // and again for the third island
                            foreach (Tri removetri in asset.Islands[indexToRemove2].TriList)
                            {
                                asset.Islands[indexToUse].TriList.Add(removetri);
                            }

                            // since we've moved all of these tris, zero the list for the old island
                            // Eventually we'll probably want to remove the island all together
                            asset.Islands[indexToRemove1].TriList.Clear();
                            asset.Islands[indexToRemove2].TriList.Clear();
                            //asset.Islands.RemoveAt(indextoRemove);    // don't do this now, will mess up island numbering

                            // replace all references to the remove values
                            for (int i = 0; i < vert_array_size; i++)
                            {
                                if ((vert_array[i] == indexToRemove1) || (vert_array[i] == indexToRemove2))
                                {
                                    vert_array[i] = indexToUse;
                                }
                            }

                            // OK, now write the tri that we're working on originally
                            vert_array[vert1] = indexToUse;
                            vert_array[vert2] = indexToUse;
                            vert_array[vert3] = indexToUse;

                            asset.Islands[indexToUse].TriList.Add(tri);
                        }
                    }
                }
                // Clean up by removing Islands that have no tris, but do this in reverse order (for both speed and stability)
                for (int i = asset.Islands.Count() - 1; i >= 0; i--)
                {
                    if (asset.Islands[i].TriList.Count() == 0)
                    {
                        asset.Islands.RemoveAt(i);
                    }
                }
            }
        }