Files
2025-09-29 00:52:08 +02:00

273 lines
6.7 KiB
Plaintext
Executable File

/*
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 <Mesh mesh> <Integer mapChannel>
--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()