Object oriented programming, once again.
May 20th, 2008 by Helge Mathee - Viewed 3575 times - Popularity: 39% [?]So the keen folks at the german XSI forum (http://www.xsiforum.de) discussed the topic of generating separate objects out of all of the polygon islands making up a polygonmesh. Even though this doesn’t seem to be a too tricky scripting problem, using commands to achieve this split-up can slow down XSI quite alot, especially if the source mesh contains a huge amount of polygon islands. Therefore I tried to come up with a object oriented solution, and here it is.
I put some effort into commenting the script accordingly, so that it may be used for learning purposes.
cheers!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | // query the geometry data var obj = selection(0); var geo = obj.Activeprimitive.Geometry; var polygons = geo.Polygons; // create an array to track which polygon has been visited var polygonVisited = []; var polygonsLeft = polygons.Count; // fill up the array to say: "no polygon has been visited yet" for(var i=0;i<polygons .count;i++) { polygonVisited[i] = false; } // create some helper variables var clusterIndices = []; var currentRow = []; // log the start of the process logmessage("Starting with "+polygonsLeft+" polygons..."); // loop until there are no polygons left // or there are still items in the cluster array while(polygonsLeft > 0 || clusterIndices.length > 0) { // if there are no items in the next row... if(currentRow.length == 0) { // if there are items in the cluster index array if(clusterIndices.length > 0) { // log the creation of the cluster logmessage("Creating cluster with "+clusterIndices.length+" elements..."); // create a new mesh containing all of these polygons // first, create an array containing all pointindices // and two additional point hash arrays // of which one is used to determine if a point is already used // and the second one is used to map the original index to the new one var pointIndices = []; var pointUsed = []; var pointNewIndex = []; for(var i=0;i<clusterIndices.length;i++) { var poly = polygons.item(clusterIndices[i]); var pointIndexArray = poly.points.indexArray.toArray(); //(VBS to JScript conversion) // loop through all points and check if it they are used for(var j=0;j<pointIndexArray.length;j++) { var index = pointIndexArray[j]; if(!pointUsed[index]) { pointNewIndex[index] = pointIndices.length; pointIndices.push(index); pointUsed[index] = true; } } } // now, create the array of the positions of all points of this island var islandPos = []; for(var i=0;i<pointIndices.length;i++) { var point = geo.points.item(pointIndices[i]); islandPos.push(point.position.x); islandPos.push(point.position.y); islandPos.push(point.position.z); } // now we need to create the description of the polygons var islandPoly = []; // for that we loop over the polygons of the island again // and record their pointindices, well, actually the remapped // indices (given by the pointNewIndex hash array) for(var i=0;i<clusterIndices.length;i++) { var poly = polygons.item(clusterIndices[i]); var pointIndexArray = poly.points.indexArray.toArray(); //(VBS to JScript conversion) // first add the number of points of this polygon // to this polygon's description islandPoly.push(pointIndexArray.length); // now add the remapped index for each point to the description for(var j=0;j<pointIndexArray.length;j++) { var index = pointIndexArray[j]; islandPoly.push(pointNewIndex[index]); } } obj.Parent.AddPolygonMesh(islandPos,islandPoly,obj.name+"_island"); clusterIndices = []; // if there are no polyons left we can stop now if(polygonsLeft == 0) break; } // loop over the polygons and try to find // one which hasn't been visited yet for(var i=0;i<polygons.Count;i++) { if(polygonVisited[i] == false) { currentRow.push(i); clusterIndices.push(i); polygonVisited[i] = true; polygonsLeft--; break; } } } // define the nextrow after the current row var nextRow = []; // loop over all items in the current row for(var i=0;i<currentRow.length;i++) { var polygon = polygons.item(currentRow[i]); var neighbors = polygon.NeighborPolygons(); // loop through all of the neighbors and add them to the nextRow for(var j=0;j<neighbors.count;j++) { // check if the neighbor has been // visited yet var neighbor = neighbors.item(j).index; if(polygonVisited[neighbor]==false) { // add the neighbor to the next row nextRow.push(neighbor); clusterIndices.push(neighbor); polygonVisited[neighbor] = true; polygonsLeft--; break; } } } currentRow = nextRow; } selection.SetAsText(obj.name+"_island*"); |
Popularity: 39% [?]




Cool stuff as usual :-)
Just wondered if you had any performance stats? Not only to see how fast it runs on a dense mesh, but also to see how it compares to writing a similar script with commands?
Cheers
Andy
Hey Helge,
If you ever port this to C++ to get better performance, you should consider using CGeometryAccessor instead of the geometry API. CGeometryAccessor is more scalable and much faster to access the geometry data than the geometry API which is a pain when dealing with very large meshes.
-mab
[...] More >>PHP Object-Oriented SolutionsSome Interesting BlogsRecruitment to PHP DEVELOPER | WalkinFeedSoftimage Blog » Blog Archive » Object oriented programming, once again.A gentle introduction to the 5th Polymath project « The Math Less TraveledAlley Tramp/Over [...]