484 lines
13 KiB
Plaintext
Executable File
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 |