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

325 lines
9.1 KiB
Plaintext
Executable File

--run this script with your skinned mesh selected.
--this is a combination of my own functions for finding the bone we want to lose and what its closest remaining parent would be (get put into a fromToBones array)
--and also making use of some of Stews functions from autolod.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bonesToKeep = #( --array of all bones we want to keep
"SKEL_ROOT",
"SKEL_Pelvis",
"SKEL_L_Thigh",
"SKEL_L_Calf",
"SKEL_L_Foot",
"SKEL_L_Toe0",
"SKEL_R_Thigh",
"SKEL_R_Calf",
"SKEL_R_Foot",
"SKEL_R_Toe0",
"SKEL_Spine_Root",
"SKEL_Spine0",
"SKEL_Spine1",
"SKEL_Spine2",
"SKEL_Spine3",
"SKEL_L_Clavicle",
"SKEL_L_UpperArm",
"SKEL_L_Forearm",
"SKEL_L_Hand",
"SKEL_L_Finger00",
"SKEL_L_Finger01",
"SKEL_L_Finger02",
"SKEL_L_Finger10",
"SKEL_L_Finger11",
"SKEL_L_Finger12",
"SKEL_L_Finger20",
"SKEL_L_Finger21",
"SKEL_L_Finger22",
"SKEL_L_Finger30",
"SKEL_L_Finger31",
"SKEL_L_Finger32",
"SKEL_L_Finger40",
"SKEL_L_Finger41",
"SKEL_L_Finger42",
"SKEL_R_Clavicle",
"SKEL_R_UpperArm",
"SKEL_R_Forearm",
"SKEL_R_Hand",
"SKEL_R_Finger00",
"SKEL_R_Finger10",
"SKEL_R_Finger11",
"SKEL_R_Finger12",
"SKEL_R_Finger20",
"SKEL_R_Finger21",
"SKEL_R_Finger22",
"SKEL_R_Finger30",
"SKEL_R_Finger31",
"SKEL_R_Finger32",
"SKEL_R_Finger40",
"SKEL_R_Finger41",
"SKEL_R_Finger42",
"SKEL_Neck_1",
"SKEL_Head",
"mover"
)
fromToBones = #(--this will be a dynamically generated 2d array containing the original bone (such as a roll bone) and what its weight will be moved to
#(), --this will contain the initial bone
#() --this will contain the bone to move weights to
)
skinModBones = #()
vertSkinValues = #()
boneNames = #()
--get the skinned verts for a mesh (theMesh) and add them to the vertSkinValues array
fn buildSkinDataArray theMesh =
(
print ("Getting vertex skin weights from " + theMesh.name)
vertSkinValues = #()
vertCount = skinOps.getNumberVertices theMesh.modifiers[#skin]
for x=1 to vertCount do
(
vertArray = #()
BNumber = skinOps.getVertexWeightCount theMesh.modifiers[#skin] x
for i = 1 to BNumber do
(
boneID = skinOps.getVertexWeightBoneId theMesh.modifiers[#skin] x i
boneName = skinOps.GetBoneName theMesh.modifiers[#skin] boneID 0
boneWeight = skinOps.getVertexWeight theMesh.modifiers[#skin] x i
tempArray = #(boneID, boneName, boneWeight)
append vertArray tempArray
)
append vertSkinValues vertArray
)
print ("vertex skin weights grabbed from " + theMesh.name)
--now im gonna try something funky and check if the bones in the array are bones to remove and if they are then i'll change them to the toBone
)--end vertSkin
--check the vert weights for the bone we want to remove (fromBone). If found, we add the weight on the the parent bone (toBone).
fn replaceWeights fromBone toBone =
(
toBoneId = findItem skinModBones (getNodeByName toBone)
-- loop through all the verts in the object
for vertNoArray=1 to vertSkinValues.count do --for every vert do
(
-- Get the influence data for each vert
currentVertData = vertSkinValues[vertNoArray]
weightToMove = 0
for vertBoneArray=1 to currentVertData.count do --for every weight do
(
if fromBone == currentVertData[vertBoneArray][2] do
(
addedWeight = false
weightToMove = currentVertData[vertBoneArray][3]
--lets check the other weights on this vert for a match with our parent bone
for recheckVertBoneArray=1 to currentVertData.count do
(
if currentVertData[recheckVertBoneArray][2] == toBone do
(
-- If we have a match, then the destination bone already exists, create a composite weight
weightToAdd = currentVertData[recheckVertBoneArray][3]
weightToWrite = weightToAdd + weightToMove
currentVertData[recheckVertBoneArray][3] = weightToWrite -- set parent to new weight
currentVertData[vertBoneArray][3] = 0 -- clear child weight
addedWeight = true -- set the flag to say we've created an updated weight set.
)--end add weight loop
)
-- what if we didn't find a good parent bone?
-- we need to kill the dirty child and repalce it with the correct parent
if addedWeight != true do
(
currentVertData[vertBoneArray][2] = toBone
addedWeight = true
)--end new bone and weight loop
)--end found toBone loop
)
)
)--end replaceWeights
fn prepBoneNames geo =
(
boneNames = #()
selBoneCount = skinOps.GetNumberBones geo.modifiers[#Skin]
--get the bone name order
for sb=1 to selBoneCount do
(
singleBoneName = skinOps.GetBoneName geo.modifiers[#Skin] sb 0
append boneNames singleBoneName
)
)
--update the skinning on the LOD mesh using our filtered vertSkinValues array
fn updateLODSkin theMesh =
(
meshName = theMesh.name
for vertNum = 1 to vertSkinValues.count do
(
tempBoneArray = #()
tempWeightArray = #()
for affectingBones=1 to vertSkinValues[vertNum].count do
(
boneID = findItem boneNames vertSkinValues[vertNum][affectingBones][2]
append tempBoneArray boneID
append tempWeightArray vertSkinValues[vertNum][affectingBones][3]
)
theVert = vertNum
theSkin = theMesh.modifiers[#skin]
boneArray = tempBoneArray
weightArray = tempWeightArray
--skinOps.unNormalizeVertex theskin theVert true
skinOps.ReplaceVertexWeights theskin theVert boneArray weightArray
--skinOps.unNormalizeVertex theskin theVert false
)
print ("skinning updated on " + theMesh.name)
)--end updateLODSkin
fn findBoneRecursive currentBone = -- Find a bone recursively if needed, iterate up the parent tree to find a bone which exists within the bonesToKeep array
(
foundResult = findItem bonesToKeep currentBone.Name
if foundResult != 0 then
(
-- found the bone in the bonesToKeep array so return it
return currentBone
print (currentBone.Name+" doesnt need changing")
)
else
(
-- did not find the bone, so search for its parent
return findBoneRecursive currentBone.parent
print ("found that")
)
)
fn checkSkinBones = --find the bones in skin mod and see if they are toi be kept and if not record what their replacement will be
(
print "starting checkSkinBones"
for i = 1 to skinModBones.count do --now add data of original bone plus its final bone into a paired array
(
myBone = findBoneRecursive skinModBones[i]
-- print myBone.name as string -- This is the upmost parent which is in the bonesToKeep array
-- print ("Appending "+sceneBones[i].name+" into fromToBones ["+(i as string)+"][1] array")
append fromToBones[1] skinModBones[i].name --put in the original bone
-- print ("Appending "+myBone.name+" into fromToBones ["+(i as string)+"][2] array")
append fromToBones[2] myBone.name --put in the bone we need to move the weight to
)
print "fromToBones array built"
)
fn buildSkinModBoneList geo = --query all bones in the skin modifier and put them into a array so we can loop trhu them
(
skinModBones = #() --ensure its empty
noOfBones = skinops.getNumberBones geo.modifiers[#Skin]
for b = 1 to noOfBones do --build the array of bones in the skin modifier
(
boneName = skinOps.GetBoneName geo.modifiers[#Skin] b 1
realBoneObj = getnodeByName boneName
appendIfUnique skinModBones realBoneObj
)
print "buildSkinModBoneList done."
)
fn runReplaceWeight geo = --using the fromToBOnes array call Stews replaceWeight script
(
tmpSel = selection as array
-- Use selection.count here Matt
-- selection[1] will also return the first item in a selection
if tmpSel.count == 1 then
(
if geo.modifiers[#Skin] != undefined then
(
max modify mode
modPanel.setCurrentObject geo.modifiers[#Skin]
buildSkinDataArray geo --build an array of all the verts in the mesh
buildSkinModBoneList geo --generate an array of all bones in the skin modifier
checkSkinBones()
print ("fromToBones count = "+(fromToBones[1].count as string))
for i = 1 to fromToBones[1].count do
(
-- compare the data in both arrays, if they do not match we need to flip.
if fromToBones[1][i] != fromToBones[2][i] then
(
replaceWeights fromToBones[1][i] fromToBones[2][i] --create arrays of the new weighting data
prepBoneNames geo
updateLODSkin geo --now we have the arrays setup do the actual skin weighting
)
)
print ("Weight switching complete")
)
else
(
messagebox ("WARNING! Selection "+geo.name+" has no skin modifier!") beep:true
)
)
else
(
messagebox ("WARNING! Please run on just one mesh") beep:true
)
)
clearListener()
runReplaceWeight $