Files
gtav-src/tools_ng/wildwest/script/3dsMax/Characters/Rigging/deltaMushSkinning/voxelizeGeoSkeleton.ms
T
2025-09-29 00:52:08 +02:00

484 lines
13 KiB
Plaintext
Executable File

clearListener()
filein "rockstar/export/settings.ms" -- This is fast
-- Figure out the project
theProjectRoot = RsConfigGetProjRootDir()
theProject = RSConfigGetProjectName()
theWildWest = RsConfigGetWildWestDir()
theProjectConfig = RsConfigGetProjBinConfigDir()
toolsRoot = RsConfigGetToolsRootDir()
-- filein (RsConfigGetWildWestDir() + "script\\max\\Rockstar_North\\character\\Includes\\FN_Rigging.ms")
filein (theWildWest + "script/3dsMax/_config_files/Wildwest_header.ms")
filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms")
filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_UI.ms")
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
geoArray = #(
#($Geo_Pelvis, $SKEL_Pelvis),
#($Geo_Spine0, $SKEL_Spine0),
#($Geo_Spine1, $SKEL_Spine1),
#($Geo_Spine2, $SKEL_Spine2),
#($Geo_Spine3, $SKEL_Spine3),
#($Geo_Neck_1, $SKEL_Neck_1),
#($Geo_RB_Neck_1, $RB_Neck_1),
#($Geo_Head, $Skel_Head),
#($Geo_L_Clavicle, $Skel_L_Clavicle),
#($Geo_RB_L_ArmRoll, $RB_L_ArmRoll),
#($Geo_L_UpperArm, $SKEL_L_UpperArm),
#($Geo_L_Forearm, $SKEL_L_Forearm),
#($Geo_RB_L_ForeArmRoll, $RB_L_ForeArmRoll),
#($Geo_L_Hand, $SKEL_L_Hand),
#($Geo_L_Finger00, $SKEL_L_Finger00),
#($Geo_L_Finger01, $SKEL_L_Finger01),
#($Geo_L_Finger02, $SKEL_L_Finger02),
#($Geo_L_Finger10, $SKEL_L_Finger10),
#($Geo_L_Finger11, $SKEL_L_Finger11),
#($Geo_L_Finger12, $SKEL_L_Finger12),
#($Geo_L_Finger20, $SKEL_L_Finger20),
#($Geo_L_Finger21, $SKEL_L_Finger21),
#($Geo_L_Finger22, $SKEL_L_Finger22),
#($Geo_L_Finger30, $SKEL_L_Finger30),
#($Geo_L_Finger31, $SKEL_L_Finger31),
#($Geo_L_Finger32, $SKEL_L_Finger32),
#($Geo_L_Finger40, $SKEL_L_Finger40),
#($Geo_L_Finger41, $SKEL_L_Finger41),
#($Geo_L_Finger42, $SKEL_L_Finger42),
#($Geo_R_Clavicle, $SKEL_R_Clavicle),
#($Geo_RB_R_ArmRoll, $RB_R_ArmRoll),
#($Geo_R_UpperArm, $SKEL_R_UpperArm),
#($Geo_R_Forearm, $SKEL_R_Forearm),
#($Geo_RB_R_ForeArmRoll, $RB_R_ForeArmRoll),
#($Geo_R_Hand, $SKEL_R_Hand),
#($Geo_R_Finger00, $SKEL_R_Finger00),
#($Geo_R_Finger01, $SKEL_R_Finger01),
#($Geo_R_Finger02, $SKEL_R_Finger02),
#($Geo_R_Finger10, $SKEL_R_Finger10),
#($Geo_R_Finger11, $SKEL_R_Finger11),
#($Geo_R_Finger12, $SKEL_R_Finger12),
#($Geo_R_Finger20, $SKEL_R_Finger20),
#($Geo_R_Finger21, $SKEL_R_Finger21),
#($Geo_R_Finger22, $SKEL_R_Finger22),
#($Geo_R_Finger30, $SKEL_R_Finger30),
#($Geo_R_Finger31, $SKEL_R_Finger31),
#($Geo_R_Finger32, $SKEL_R_Finger32),
#($Geo_R_Finger40, $SKEL_R_Finger40),
#($Geo_R_Finger41, $SKEL_R_Finger41),
#($Geo_R_Finger42, $SKEL_R_Finger42),
#($Geo_RB_L_ThighRoll, $RB_L_ThighRoll),
#($Geo_L_Thigh, $SKEL_L_Thigh),
#($Geo_L_Calf, $Skel_L_Calf),
#($Geo_L_Foot, $SKEL_L_Foot),
#($Geo_L_Toe0, $SKEL_L_Toe0),
#($Geo_RB_R_ThighRoll, $RB_R_ThighRoll),
#($Geo_R_Thigh, $SKEL_R_Thigh),
#($Geo_R_Calf, $SKEL_R_Calf),
#($Geo_R_Foot, $SKEL_R_Foot),
#($Geo_R_Toe0, $SKEL_R_Toe0)
)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fn rstaSkinHardWeightMesh meshToSkinArray skinDataArray =
(
-- for i = 1 to skinDataArray.count do
-- (
-- format (skinDataArray[i] as string+"\n")
-- )
for meshToSkin in meshToSkinArray do
(
if meshToSkin.modifiers.count >= 1 do
(
for m = meshToSkin.modifiers.count to 1 by -1 do
(
deleteModifier meshToSkin m
)
)
addModifier meshToSkin (Skin())
max modify mode
modPanel.setCurrentObject meshToSkin.modifiers[#Skin]
local skinMOd = meshToSkin.modifiers[#Skin]
skinMOd.bone_limit = 1
for i = 1 to skinDataArray.count do --add the bones into the skin modifier
(
--format ((skinDataArray[i][1] as string)+" skinDataArray["+(i as string)+"][3]: "+(skinDataArray[i][3] as string)+"\n")
if skinDataArray[i][3] == meshToSkin do
(
local boneToAdd = skinDataArray[i][1]
--format ("Adding "+(boneToAdd as string)+" to "+meshToSkin.name+"\n")
local boneUpdateInt = undefined
if i != skinDataArray.count then
(
boneUpdateInt = 0
)
else
(
--ok we're at the count so we need to refresh
boneUpdateInt = 1
)
if boneToAdd != undefined do
(
skinOps.addbone skinMod boneToAdd boneUpdateInt
)
)
)
completeRedraw ()
local boneCount = skinOps.GetNumberBones skinMod
local gbg = ClassOf meshToSkin --hacky way to try and stop the Runtime error: Exceeded the vertex count error
-- local skinnedThis = false
for thisData in skinDataArray do
(
if thisData[3] == meshToSkin do
(
local thisBone = thisData[1]
local thisVertArray = thisData[2]
--find the skin modifier index for thisBone
for b = 1 to boneCount do
(
local tb = skinOps.GetBoneName skinMod b 0
if tb == thisBone.name do
(
--format ("Setting weights for "+thisBone.name+"\n")
--ok we need to skin all the verts in thisVertArray to this bone
for v in thisVertArray do
(
--format ("Setting vert "+(v as string)+" for bone "+(b as string)+" "+thisBone.name+"\n")
skinOps.SetVertexWeights skinMod v b 1.0
-- skinnedThis = true
)
)
)
)
)
-- if skinnedThis == true do
-- (
-- format ("Weights applied to "+meshToSkin.name+"\n")
-- )
)
)
fn RSTA_getBoundingBoxSize bbOx =
(
local xVal = undefined
local yVal = undefined
local zVal = undefined
if bBox[1][1] < bBox[2][1] then
(
xVal = (bBox[1][1] * -1) + bBox[2][1]
)
else
(
xVal = (bBox[2][1] * -1) + bBox[1][1]
)
if bBox[1][2] < bBox[2][2] then
(
yVal = (bBox[1][2] * -1) + bBox[2][2]
)
else
(
yVal = (bBox[2][2] * -1) + bBox[1][2]
)
if bBox[1][3] < bBox[2][3] then
(
zVal = (bBox[1][3] * -1) + bBox[2][3]
)
else
(
zVal = (bBox[2][3] * -1) + bBox[1][3]
)
[xVal,yVal,zVal]
)
fn RSTA_VoxelizeMesh meshObj maxVoxels boneIndex meshToSkinArray skinDataArray geoArray =
(
local startA = timeStamp()
--IT IS ESSENTIAL THAT THE PIVOTPOINT OF THE GEO IS ALIGNED TO ITS CORRESPOONDING JOINT
--first get the boundingbox of the meshObj
--divide the sides by maxVoxels to get the number of iterations
--build a cube volume of voxels then use a meshselect to get the ones that actual fill the meshObj and delete the others outside its volume
if meshObj.scale != [1,1,1] do
(
format ("WARNING! "+meshObj.name+" does not have valid scale. Voxels may be wrong.\n")
)
local realBbox = nodeGetBoundingBox meshObj meshObj.transform
local meshBbox = RSTA_getBoundingBoxSize realBbox
--format ("meshBbox: "+(meshBbox as string)+"\n")
--divide the x y z by maxVoxels and then create the cub based off maxvoxels * largest value
local divX = meshBBox[1] / maxVoxels
--format ("divX: "+(divX as string)+"\n")
local divY = meshBBox[2] / maxVoxels
--format ("divY: "+(divY as string)+"\n")
local divZ = meshBBox[3] / maxVoxels
--format ("divZ: "+(divZ as string)+"\n")
local newVoxelSize = undefined
if divX > divY then
(
if divX > divZ then
(
--divX is biggest
newVoxelSize = divX
)
else
(
--divZ is biggest
newVoxelSize = divZ
)
)
else
(
--divX < divY
if divY > divZ then
(
--divY is biggest
newVoxelSize = divY
)
else
(
--divZ is biggest
newVoxelSize = divZ
)
)
--we need to find the top left most position for the first voxel then iterate across
--we need to build the voxels in the space of the meshObj
local prevX = realBbox[1][1] - (newVoxelSize / 2) --this gets iterated over
local prevY = realBbox[1][2] - (newVoxelSize / 2)
local prevZ = realBbox[1][3] - (newVoxelSize / 2)
local initX = prevX --used to store the initial X position
local initY = prevY
local initZ = prevZ
-- local thisVox = Box length:newVoxelSize width:newVoxelSize height:newVoxelSize pos:[0,0,0] name:"voxName" lengthSegs:1 widthsegs:1 heightsegs:1
for xIt = 1 to maxVoxels do
(
local x = preVx + newVoxelSize
for yIt = 1 to maxVoxels do
(
local y = prevY + newVoxelSize
for zIt = 1 to maxVoxels do
(
local z = prevZ + newVoxelsize
local voxName = ("Vox_"+(substring meshObj.name 5 -1)+"_"+(xIt as string)+"_"+(yIt as string)+"_"+(zIt as string))
local pos = [x,y,z]
local thisVox = Box length:newVoxelSize width:newVoxelSize height:newVoxelSize pos:pos name:voxName lengthSegs:1 widthsegs:1 heightsegs:1
in coordsys meshObj thisVox.position = pos
addModifier thisVox (Vol__Select())
thisVox.modifiers[#Vol__Select].volume = 3
thisVox.modifiers[#Vol__Select].level = 1
thisVox.modifiers[#Vol__Select].node = meshObj
local deleteThis = false
if thisVox.mesh.selectedVerts.count == 0 do
(
deleteThis = true
)
if deleteThis == true then
(
delete thisVox
)
else
(
for meshToSkin in meshToSkinArray do
(
local weSetVert = false
--NEED TO FIND A WAY HERE TO STORE DATA FOR MULTIPLE MESHTOSKIN OBJECTS
--OTHERWISE WE WILL HAVE TO GENERATE THE VOXELS MULTIPLE TIMES
--CAN I DO IT VIA A STRUCT PERHAPS?
if meshToSkin.modifiers[#Vol__Select] == undefined then
(
addModifier meshToSkin (Vol__Select())
meshToSkin.modifiers[#Vol__Select].volume = 3
meshToSkin.modifiers[#Vol__Select].level = 1
meshToSkin.modifiers[#Vol__Select].node = thisVox
)
else
(
meshToSkin.modifiers[#Vol__Select].node = thisVox
)
if meshToSkin.mesh.selectedVerts.count != 0 then
(
local selVerts = meshToSkin.mesh.selectedVerts as bitarray
--format (voxName+" has "+(thisVox.mesh.selectedVerts.count as string)+" verts: "+(selVerts as string)+".\n")
for b = 1 to skinDataArray.count do
(
if skinDataArray[b][1] == geoArray[boneIndex][2] do
(
if skinDataArray[b][3] == meshToSkin do --this is used to track which mesh object in the meshes to skin array these weights are for
(
for v in selVerts do
(
appendIfUnique skinDataArray[b][2] v
weSetVert = true
)
)
)
)
)
)
)
-- if meshObj.name != "Geo_R_Thigh" do
-- (
try(
delete thisVox
)catch()
-- )
if xIt == maxVoxels then
(
prevX = initX
)
else
(
prevX = x
)
if yIt == maxVoxels then
(
prevY = initY
)
else
(
prevY = y
)
if zIt == maxVoxels then
(
prevZ = initZ
)
else
(
prevZ = z
)
)
)
)
gc()
local endA = timeStamp()
format ("Processing voxel generation for "+meshObj.name+" took "+(((endA - startA) / 1000.0) as string)+" seconds\n")
skinDataArray
)
fn voxeliseBasedOfSkeletalGeo geoArray meshesToSkinArray =
(
enableSceneRedraw() --just in case we've previously had a crash
local start = timestamp()
with undo off(
if meshesToSkinArray.count > 0 then
(
disableSceneRedraw()
max create mode
skinDataArray = #()
createDialog progBar width:300 height:30
local geoArrayCount = geoArray.count
for s = 1 to geoArrayCount do
(
local sourceObj = geoArray[s][1]
if sourceObj != undefined then
(
local maxVoxels = 8
for meshToSkin in meshesToSkinArray do
(
local tmpData = #(geoArray[s][2], #(), meshToSkin)
appendIfUnique skinDataArray tmpData
)
skinDataArray = RSTA_VoxelizeMesh sourceObj maxVoxels s meshesToSkinArray skinDataArray geoArray
)
else
(
format ("Source obj (geo) was undefined.\n")
)
progBar.prog.value = (100.*s/geoArrayCount)
)
destroyDialog progbar
enableSceneRedraw()
local end = timestamp()
format ("Completing voxel generation took "+(((end - start) / 1000.0) as string)+" seconds in total.\n")
--now we can actually skin this shit
start = timestamp()
rstaSkinHardWeightMesh meshesToSkinArray skinDataArray
end = timestamp()
format ("Processing hardskinning took "+(((end - start) / 1000.0) as string)+" seconds\n")
)
else
(
format "WARNING meshToSkin was undefined!\n"
)
)
)
meshesToSkinArray = #(
$Uppr_000_R,
$lowr_000_r
)
voxeliseBasedOfSkeletalGeo geoArray meshesToSkinArray