Notifications
Clear all

[Closed] Transfer Skin Data

 MZ1

I want to create a script to transfer skin data between two objects with different vertex and bone data. like skin utility (Export Import Skin Data). This is my first try that works on simple objects, but too slow on complex objects:



fn PrepareModifyPanel Obj Md: =
(
   if selection.count != 1 or selection[1] != Obj do select Obj
   max modify mode
   resumeEditing()
   classof Obj
   if Md != unsupplied and Md != undefined and modPanel.getCurrentObject() != Md do modPanel.setCurrentObject Md
)

fn GetBoneIndex SkinMd Bn = 
(
   if isvalidnode Bn then
   (
      boneNames = for i =1 to (skinOps.GetNumberBones SkinMd) collect (skinOps.GetBoneName SkinMd i 0)
      findItem boneNames Bn.name
   )
   else 0
)

fn GetEffectedVertexes SkinMd BoneId =
(
   Verts = #()
   for v = 1 to skinops.getnumbervertices SkinMd do
   (
      for w = 1 to skinops.getvertexweightcount SkinMd v do
      (
         if skinops.getvertexweightboneid SkinMd v w == BoneId \
         and skinops.getvertexweight SkinMd v w != 0 do append Verts v
      )
   )
   Verts
)

fn CopyPasteSkinData SourceObj: TargetObj: SourceBone: TargetBone: Threshold:20 =
(
   if isvalidnode SourceObj and isvalidnode TargetObj and isvalidnode SourceBone and isvalidnode TargetBone do
   (
      SourceSkinMd = SourceObj.modifiers[#Skin]
      TargetSkinMd = TargetObj.modifiers[#Skin]
      if SourceSkinMd != undefined and TargetSkinMd != undefined do
      (   
         Glb.Fns.PrepareModifyPanel SourceObj Md:SourceSkinMd
         SourceVertCount = skinOps.GetNumberVertices SourceSkinMd
         SourceBoneId = Glb.Fns.GetBoneIndex SourceSkinMd SourceBone
         Verts = Glb.Fns.GetEffectedVertexes SourceSkinMd SourceBoneId
         Poses = #()
         Values = #()
         for i in Verts do
         (
            append Poses (getVert SourceObj.mesh i)
            append Values (skinOps.GetVertexWeight SourceSkinMd i SourceBoneId)
         )
         
         Glb.Fns.PrepareModifyPanel TargetObj Md:TargetSkinMd
         TargetVertCount = skinOps.GetNumberVertices TargetSkinMd
         TargetBoneId = Glb.Fns.GetBoneIndex TargetSkinMd TargetBone
         for i = 1 to Verts.count do
         (
            for j = 1 to TargetVertCount do
            (
               if (distance (getVert TargetObj.mesh j) Poses[i]) <= Threshold do skinOps.setVertexWeights TargetSkinMd j TargetBoneId Values[i]
            )      
         )
      )
   )
)

My question is how we can make this faster? I think bottleneck is here:


         for i = 1 to Verts.count do
         (
            for j = 1 to TargetVertCount do
            (
               if (distance (getVert TargetObj.mesh j) Poses[i]) <= Threshold do skinOps.setVertexWeights TargetSkinMd j TargetBoneId Values[i]
            )      
         ) 

6 Replies

Humm the bone names are all different?

1 Reply
 MZ1
(@mz1)
Joined: 10 months ago

Posts: 0

Sorry for long delay, Let say we have two different character with different skeletal and mesh but in same place. and we want to copy skin data for only vertexes around the foot. before copy I rename the target bone to source bone, then after copy I will rename it back to the original.

The way i got about doing this (sry can’t post the code as it references way too many different lib calls and I just do not have the time to dig all the functions right now)

But basically if the bone names are not different this is what I do.

  • I make a copy of the skinData mesh, then go through the skinDataMesh object properties. I gather the name of all the bones.
  • Once I have all the bone, I add them all to a skin modifier on the Copied SkinDataMesh.
  • Then i use the built in SkinWithSkinData call to get a perfectly skinned mesh.
  • After that i Skin Wrap the target mesh to the Copied SkinDataMesh and then convert to skin.
  • All of this is done through script and takes no time at all. (Much higher poly meshes cant slow the process down)

This are the setting I use for the skinWrap:

ObjectToSkin.modifiers[#Skin_Wrap].engine = 0
ObjectToSkin.modifiers[#Skin_Wrap].falloff = 0.001
ObjectToSkin.modifiers[#Skin_Wrap].weightallverts = on
ObjectToSkin.modifiers[#Skin_Wrap].ConvertToSkin true

If the bone names are different I would find a relationship between the two… but it can be tricky, do they have the same bone name with different prefix or suffix?

1 Reply
 MZ1
(@mz1)
Joined: 10 months ago

Posts: 0

My goal is to copy only one bone and leave the rest with no touch.

I wrote a script to do the same thing for a game modding community… to transfer skin data from one skeleton to another for the same character mesh. Feel free to use what you can from it. You can download it here:

https://jkhub.org/files/file/2774-transfer-skin-data-maxscript/

 MZ1

I want to transfer skin data on different mesh not swapping skeletal on same mesh.