/* RSN_CleanMesh Stores map channel data then exports an FBX of the mesh Then re-imports the FBX and restores the map channel data Neil.Gregory@RockstarNorth.com 12/2011 */ struct meshData ( name = undefined, attrs = #(), material = undefined, parent = undefined, children = undefined )--END OF STRUCT struct meshCPVData ( vtxPositionsExport = #(), --unique mesh vertex positions as Point3 array vtxPositionsImport = #(), channels = #(), --#("name", channelindex, #(vtxPositionsIndex, mapVtxIndex, colour),#(vtxPositionsIndex, mapVtxIndex, colour), #(vtxPositionsIndex, mapVtxIndex, colour),.....) channelNames = #("Alpha", "Illum", "Colour", "UV", "MaskUV", \ "NULL", "NULL", "NULL", "NULL", "NULL", \ "NULL", "Terrain", "NULL", "MicroMovement", "NULL", \ "Tint", "PedEnv", "PedFat"), fn storeMapChannels obj = ( --flush channels #() channels = #() --get all vert positions and stuff into vtxPositions vtxPositionsExport = for v = 1 to (getNumVerts obj) collect getvert obj v numMaps = meshop.getNumMaps obj --interface speedup meshOpGetMapFace = meshop.getMapFace meshOpGetVert = meshop.getvert meshOpGetMapVert = meshop.getMapVert --find all the channels with data in for chn = 2 to (numMaps - 1) do ( --update progress progressUpdate (100.0 *(chn+3) / numMaps) local channelArray = #() if (meshop.getMapSupport obj chn) == true then ( --print chn --channel name id append channelArray channelNames[chn+3] --index append channelArray chn for mapFace = 1 to (meshop.getNumMapFaces obj chn) do ( mapFaceVerts = meshOpGetMapFace obj chn mapFace mapFaceVerts = #(mapFaceVerts.x as Integer, mapFaceVerts.y as Integer, mapFaceVerts.z as Integer) faceVerts = getFace $ mapFace faceVerts = #(faceVerts.x as Integer, faceVerts.y as Integer, faceVerts.z as Integer) --format "mapFaceVerts: % faceVerts: % \n" mapFaceVerts faceVerts for mv = 1 to 3 do ( mapVertIdx = mapFaceVerts[mv] --using index get the vertex from the array and grab its pos vPos = meshOpGetVert obj faceVerts[mv] --now find the same position in the vtxPositions array vtxPosIdx = findItem vtxPositionsExport vPos --map vert value mapVertVal = meshOpGetMapVert obj chn mapVertIdx channelArray[mapVertIdx+2] = #(vtxPosIdx, mapFace, mv, mapVertVal) ) ) ) --add to the channels append channels channelArray ) --set the number of map channels to 0 so FBX doesnt save any meshop.setNumMaps obj 0 ), fn restoreMapChannels obj = ( --check we have some channel data if channels.count == 0 then return false meshop.setNumMaps obj (channels.count + 1) vtxPositionsImport = for v = 1 to (getNumVerts obj) collect getvert obj v --iterate channels stored and re-apply to the the obj for chan = 1 to channels.count do ( if channels[chan].count != 0 then ( --array --get the idx channelIdx = channels[chan][2] --print channelIdx if channels[chan][1] != undefined then ChannelInfo.NameChannel obj 3 channelIdx channels[chan][1] --setup map channel meshop.setMapSupport obj channelIdx true --iterate miss first 2 as they are channel meta data for vtx = 3 to channels[chan].count do ( --get the map face idx mapFace = channels[chan][vtx][2] --get the mapvert in the face mapFaceVerts = meshop.getMapFace obj channelIdx mapFace --the mapvert we want to set mapVertIdx = mapFaceVerts[channels[chan][vtx][3]] --now set the value on it meshop.setMapVert obj channelIdx mapVertIdx channels[chan][vtx][4] ) ) else --just add an empty channel ( channelCount = meshop.getNumMaps obj -- +1 if chan > 1 then meshop.setNumMaps obj (channelCount + 1) ) ) ) )--END OF STRUCT fn cleanMesh = ( --timing start = timestamp() --mesh data inst mData = meshData() --selection obj = $selection as array if obj.count == 0 then ( messagebox "Nothing selected!" title:"Error" return false ) --setup a progressbar progressStart "Clean Mesh:" obj = obj[1] --store the name mData.name = obj.name --print mData.name --break() --store the attrs local attrClass = GetAttrClass obj local attrCount = GetNumAttr attrClass mData.attrs = for i = 1 to attrCount collect GetAttr obj i --store the material mData.material = obj.material -- --store the cpv data -- --turn it to a mesh, it will come back in as one anyway addModifier obj (turn_to_mesh()) collapseStack obj --create a meshCPVData instance cpvData = meshCPVData() cpvData.storeMapChannels obj --meshop.getMapSupport obj chn --meshop.getNumMapVerts --iterate verts getting position, looking up index in vtxPositions, store that with vertex colour --store the parent in heirarchy if any mData.parent = obj.parent mData.children = (readvalue (("$"+obj.name+"/*") as stringstream)) as Array --export as fbx exportSuccess = exportFile (GetDir #export + "/cleanMesh.fbx" ) #noPrompt selectedOnly:true --delete obj obj.name = (obj.name + "_OLD") --print obj.name delSuccess = delete obj --delSuccess = 1 if delSuccess == 1 then ( --reimport from fbx if exportSuccess then ( --delete old object --break() FbxImporterSetParam "Mode" "merge" importSuccess = importFile (GetDir #export + "/cleanMesh.fbx" ) #noPrompt if not importSuccess then ( messagebox "Failed to import" title:"Error.." return false ) ) else ( messageBox "Failed to export" title:"Error.." return false ) newObj = getNodeByName mData.name --restore attrs to imported object for i = 1 to mData.attrs.count do setAttr newObj i mData.attrs[i] --restore material to imported object newObj.material = mData.material --restore the map channels cpvData.restoreMapChannels newObj --restore imported object into heirarchy if mData.parent != undefined then newObj.parent = mData.parent if mData.children != undefined then ( for child in mData.children do ( child.parent = newObj ) ) --display newObj.displayByLayer = false newObj.showVertexColors = on newObj.vertexColorType = 0 --clean up mData = undefined ) end = timeStamp() format "Processing took % seconds\n" ((end - start) / 1000.0) ) cleanMesh()