Home Technical Talk

Maxscript skin help

polycounter lvl 18
Offline / Send Message
Rick Stirling polycounter lvl 18
I'd like to do the following in max (version 7)

In the skin modifier, select a vert and hit a button that creates a data set of all bones and weights of that vert.

Then select another vert, and hit paste - the data gets copied.

There would be a mirror option too, if if was enabled the the bones used would be mirrored, so L_Clavicle would become R_Clavicle etc.

Any ideas?

First things first. This code will select a specic vert:

skinOps.SelectVertices $.modifiers[#Skin] #{XXX}
where XXX is the vert I want selected. I cant seem to select a vert however, and have max tell me the id number of the vert I have selected.

I need that because this:

skinOps.GetVertexWeightCount $.modifiers[#Skin] XXX

Tells me how many bones that vert is weighted to.

THen once I know how many, I can use this:

skinOps.GetVertexWeightBoneID

to get the id numbers of those bones

skinOps.SetVertexWeights will be used to set the weight



So, i've tried to doa little work, but I'm stuck at hte start.

Any help?

Replies

  • FatAssasin
    Offline / Send Message
    FatAssasin polycounter lvl 18
    This is kind of lame (that you have to do it this way), but it works:

    <font class="small">Code:</font><hr /><pre>skinMod = selection[1].modifiers[#Skin]
    n = skinOps.getNumberVertices skinMod
    selVert = 0
    for i = 1 to n do (if skinops.isVertexSelected skinMod i == 1 then selVert = i)
    selVert</pre><hr />
  • Rick Stirling
    Offline / Send Message
    Rick Stirling polycounter lvl 18
    Yay! That sorted it.

    In the interest of meing nice, here is the script too.

    Why did I write this? Well, max 7 has a skin weight mirror facility. Unfortunatley the scale I have to work at means that the threshold value is often too small, and I always have a few weights that won't copy - 0.001 is too small, 0.002 is too big.

    This script will let you select a vert, press copy, then select a vert and press paste. It automatically mirrors.

    you MAY need to change the mirroring section depending on your bones names.

    global BoneArray
    global BoneNArray
    global WeightArray
    global PasteArray


    -- Pass the vert id to extract all the weights to arrays
    fn CopyWeight theVert =
    (
    -- Empty the arrays
    BoneArray = #()
    BoneNArray =#()
    WeightArray = #()

    theSkin = $.modifiers[#skin]
    BNumber = skinOps.getVertexWeightCount theSkin theVert
    BN = BNumber as string

    for i = 1 to BNumber do
    (
    boneID = skinOps.getVertexWeightBoneId theSkin theVert i
    boneName = skinOps.GetBoneName theSkin boneID 0
    boneWeight = skinOps.getVertexWeight theSkin theVert i

    append BoneArray boneID
    append BoneNArray boneName
    append WeightArray boneWeight
    )
    )




    fn PasteWeight pVert =
    (
    disableSceneredraw()

    theSkin = $.modifiers[#skin]

    print "these are the stored arrays for copying"
    print pastearray
    print weightarray

    skinOps.ReplaceVertexWeights theskin pVert pasteArray WeightArray


    enableSceneredraw()
    redrawViews()
    )



    fn find_mirror arrayIndex =
    (
    -- Build arrays of all the bones in the system
    theSkin = $.modifiers[#skin]
    totalbones = skinops.getnumberbones theSkin

    totalBoneNArray =#()

    for i = 1 to totalbones do
    (
    boneName = skinOps.GetBoneName theSkin i 0
    append totalBoneNArray boneName
    )



    -- Now we know all the bones, lets parse of list of weighted bones


    SB = BoneNArray[arrayIndex] as string
    boneToFind=SB

    -- Find bone names beginning with CHAR
    if (substring SB 1 4 == "Char") then
    (
    BNprefix=substring SB 1 7 as string
    BNsuffix= substring SB 8 255 as string

    newPrefix=BNprefix
    if BNprefix == "Char L " then newPrefix= "Char R "
    if BNprefix == "Char R " then newPrefix= "Char L "

    boneToFind = newPrefix + BNsuffix
    )

    if (substring SB 2 1 == " ") then
    (
    BNprefix=substring SB 1 2 as string
    BNsuffix= substring SB 3 255 as string

    newPrefix=BNprefix
    if BNprefix == "L " then newPrefix= "R "
    if BNprefix == "R " then newPrefix= "L "

    boneToFind = newPrefix + BNsuffix
    )

    -- ok, at this stage we have an arracy of bone names, and we know what name
    -- we are looking for. so cycle the array and find the index!
    theIndex = 0

    -- Do we need to find a new bone?

    if (boneToFind != SB) then
    (
    print bonearray
    for i = 1 to totalbones do
    (
    thecheck= totalBoneNArray as string
    if thecheck == bonetofind then theIndex = i
    )

    pasteArray[arrayIndex]=theIndex

    )
    )



    rollout blank "Single Skin Copy and Paste"
    (
    label lbl1 "Select vert, press copy, then select vert and press paste." pos:[9,8] width:197 height:48
    button ButtonC "Copy" pos:[18,40] width:75 height:24
    button ButtonP "Paste" pos:[110,40] width:75 height:24


    on ButtonP pressed do
    (
    theSkin = selection[1].modifiers[#Skin]
    n = skinOps.getNumberVertices theSkin

    selVert=0

    for i = 1 to n do
    (
    if (skinops.isVertexSelected theSkin i == 1) then
    (
    selVert=i
    )
    )

    -- Call the copy function
    PasteWeight selVert
    )




    on ButtonC pressed do
    (
    -- Get vert id
    theSkin = selection[1].modifiers[#Skin]
    n = skinOps.getNumberVertices theSkin

    selVert=0

    for i = 1 to n do
    (
    if (skinops.isVertexSelected theSkin i == 1) then
    (
    selVert=i
    )
    )

    -- Call the copy function
    CopyWeight selVert

    -- We now have 3 arrays - bone id, bone name, and bone weight.
    -- some of the bones might need to be mirrored so for each bone, find the possible mirror
    n = BoneArray.count
    pastearray = bonearray

    for i = 1 to n do
    (
    find_mirror i
    )
    )
    )

    -- Create floater
    theNewFloater = newRolloutFloater "Rollout title" 220 100

    -- Add the rollout section
    addRollout blank theNewFloater
Sign In or Register to comment.