325 lines
9.1 KiB
Plaintext
Executable File
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 $ |