// ******** // // 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); } } } }
// ******** // // 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); } } } }