Help weight transfer script

Help weight transfer script

davinwest72
Participant Participant
4,464 Views
24 Replies
Message 1 of 25

Help weight transfer script

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
4,465 Views
24 Replies
Replies (24)
Message 2 of 25

denisT.MaxDoctor
Advisor
Advisor

@davinwest72 wrote:

Version gmax, which is exactly like 3dsmax4.2 ...

 


Are you a time traveler? An ancient artifact hunter? 😲

 

Discreet 3dsmax 4

Magma2000Windows 98, Windows ME, Windows 2000[6]

 

or maybe 3D Studio? 😂

 

denisTMaxDoctor_1-1710226858976.png

 

 

 

Well... Do you want to make it good or easy? Good skin wrapping is a pretty complicated algorithm. What kind of meshes do you want to wrap?

0 Likes
Message 3 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 4 of 25

denisT.MaxDoctor
Advisor
Advisor

Is there no way to convert the data to a more recent version of MAX and, using something like OBJ, import it back in after skin wrapping?

0 Likes
Message 5 of 25

denisT.MaxDoctor
Advisor
Advisor

I'm also concerned about the MAXScript version... at the beginning of the 2000s it was pretty far from up to date, skinning support was very limited, and I'm not sure if skinops have been introduced yet.

0 Likes
Message 6 of 25

denisT.MaxDoctor
Advisor
Advisor

Skin wrapping based on the distance between vertices is very coarse. A much better result is given by a "face-based" algorithm. Both requires a lot of time and memory for large meshes, and something like a Kd-tree search engine is needed to speed it up... This is quite a heavy task for older versions assuming MAXScript implementation.

0 Likes
Message 7 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 8 of 25

denisT.MaxDoctor
Advisor
Advisor

I've been writing scripts for MAX for 25 years now... I'm not saying that what you're trying to do is completely impossible, but I see good reasons to look for alternative solutions.

0 Likes
Message 9 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 10 of 25

denisT.MaxDoctor
Advisor
Advisor
local boneIndices = for k = 1 to k - 1 where boneWeights[k] > 0 collect k

this is wrong for sure...

 

 

What is the typical number of vertices in the source and target meshes?

0 Likes
Message 11 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 12 of 25

denisT.MaxDoctor
Advisor
Advisor

@davinwest72 wrote:

I will reconfigure the line. The source mesh typically has about 400 verts. Target mesh will match or sometimes double that amount. 


These are small meshes. You can do it the way you do it. There's no need for any clever "acceleration".

0 Likes
Message 13 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 14 of 25

denisT.MaxDoctor
Advisor
Advisor

I understand that you're interested in learning how to write scripts. Unfortunately, I don't have the time to explain everything in detail, but I can show you two basic functions that I used in one of my tools. If you take the time to understand them, you'll be able to advance your learning on your own.

 

It's worth mentioning that your current code isn't too far off from working properly.

 

So, are you ready to learn these functions?

0 Likes
Message 15 of 25

davinwest72
Participant
Participant

Edit. Solved.

0 Likes
Message 16 of 25

denisT.MaxDoctor
Advisor
Advisor
fn copySkinData node = 
(
	sk = node.modifiers[skin]
	if iskindof sk Skin do
	(
		max modify mode
		modpanel.setcurrentobject sk
		num = skinops.getnumberbones sk
		bones = for k=1 to num collect 
		(
			skinops.getbonename sk k 0
		)
		weights = for k=1 to skinops.getnumbervertices sk collect
		(
			num = skinops.getvertexweightcount sk k 
			
			_bones = #()
			_names = #()
			_weights = #()
			
			for i=1 to num do
			(
				id = skinops.getvertexweightboneid sk k i
				name = skinops.getbonename sk id 0
				weight = skinops.getvertexweight sk k i
				
				append _bones id 
				append _names name
				append _weights weight 
			)
			
			#(k, _bones, _names, _weights)
		)
		
		#(bones, weights)
	)
)

fn pasteSkinData node data = 
(
	sk = node.modifiers[skin]
	if iskindof sk Skin do
	(
		max modify mode
		modpanel.setcurrentobject sk
		
		bones = data[1]
		num = bones.count
		for k=1 to num do
		(
			if isvalidnode (bone = getnodebyname bones[k]) do 
			(
				skinops.addbone sk bone 1
			)
		)
		skinOps.Invalidate sk 1
		
		weights = data[2]
		num = weights.count
		for k=1 to num do
		(
			_d = weights[k]
			
			_bones = for b in _d[3] collect (finditem bones b)
			skinops.replacevertexweights sk k _bones _d[4]    
		)
		#(skinops.getnumberbones sk, skinops.getnumbervertices sk)
	)
)

 

If you create a map for the source and target vertices, these two functions will suffice for the skin transfer.

0 Likes
Message 17 of 25

davinwest72
Participant
Participant
Edit. Solved.
0 Likes
Message 18 of 25

denisT.MaxDoctor
Advisor
Advisor
fn mapNearestVerts source target = 
(
	fn findNearest p verts = 
	(
		dist = distance p verts[1]
		n = 1
		for k=2 to verts.count where (d = distance p verts[k]) < dist do
		(
			dist = d
			n = k
		)
		n
	)
	
	source_mesh = snapshotasmesh source
	target_mesh = snapshotasmesh target
	
	source_map = #()
	numv = source_map.count = source_mesh.numverts
	
	target_verts = for v=1 to target_mesh.numverts collect (getvert target_mesh v)
	
	for v=1 to numv do source_map[v] = findNearest (getvert source_mesh v) target_verts 
	source_map
)


delete objects

s = geoSphere name:#source radius:25 segs:12 wirecolor:green
t = sphere name:#target radius:25 segs:32 wirecolor:orange


source_map = 
(
	format "source:% target:%\n" (s.mesh.numverts) (t.mesh.numverts)

	t0 = timestamp()
	h0 = heapfree
	
	mm = mapNearestVerts s t

	format "\ttime:% heap:% count:%\n" (timestamp() - t0) (h0 - heapfree) source_map.count
	
	mm
)
0 Likes
Message 19 of 25

denisT.MaxDoctor
Advisor
Advisor

This example shows that we are good with source and target meshes of size ~1.5K and ~0.5K vertices.

You can play around with the number of segments to see how it affects performance

0 Likes
Message 20 of 25

denisT.MaxDoctor
Advisor
Advisor

If we copy from high-res to low-res, no problem here.... but mostly we need to copy from low-res to high-res. In this case, there is a problem because we can't do it well without averaging several near vertices.

0 Likes