Align UV script optimizations


#21

here’s what I suggested doing with uv-mesh representation
don’t know why but subsequent execution of this code doing twice as fast than the first run after max start


t1=timestamp();hf = heapfree
max create mode
with redraw off
(
	
-- example scene
sp = 
(
	max create mode
	delete objects
	sp = teapot name:"test_mesh" mapcoords:on isSelected:true
	addmodifier sp (Uvwmap maptype:0)
	sp = converttopoly sp
	for k=1 to 3 do polyop.attach sp (copy sp)
	update sp
	
	sp
)




fn GetAllMeshElements node =
(
	local tmesh = snapshotasmesh node
	local faces = #{1..tmesh.numfaces}
	local verts = for v = 1 to tmesh.numverts collect #()
	local undone = #{1..tmesh.numverts}
	local elements = #()
	
	for j in faces do
	(
		f = getface tmesh j

		append verts[f[1]] j
		append verts[f[2]] j
		append verts[f[3]] j		
		
	)

	for i in faces do
	(		
		element = #(i)
		for j in element where faces[j] do
		(
			faces[j] = false
			f = getface tmesh j
			
			if undone[f[1]] do (join element verts[f[1]]; undone[f[1]] = false )
			if undone[f[2]] do (join element verts[f[2]]; undone[f[2]] = false )
			if undone[f[3]] do (join element verts[f[3]]; undone[f[3]] = false )
			
		)		
		append elements (element as bitarray)
	)
	
	elements
)

sel = selection[1]
convertToMesh sel

tri = snapshotasmesh sel
meshUV = mesh mesh:tri
channelInfo.CopyChannel meshUV 3 1
channelInfo.PasteChannel meshUV 1 0
collapseStack meshUV

elems = GetAllMeshElements meshUV

meshop_getVertsUsingFace = meshop.getVertsUsingFace

vts = #()
vts.count = tri.numverts
for el in elems do
(
	fv = meshop_getVertsUsingFace meshUV el
	
	shift = [ 1e9, 1e9, 0 ]
	
	for v in fv do
	(
		vts[v] = vv = getVert meshUV v
				
		if vv.x < shift.x do shift.x = vv.x
		if vv.y < shift.y do shift.y = vv.y
	)
	
	for v in fv do setvert meshUV v (vts[v] - shift)
		
)

update meshUV

channelInfo.CopyChannel  meshUV 1 0
channelInfo.PasteChannel sel 3 1
delete meshUV
free tri
)
	

format "Time: %sec. Mem: %\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)

#22

Could you post an example of the scene you usually work with? (preferably MAX 2020 version). I need to see the type of data you have. How best to optimize depends on it.


#23

It’s easy not to use a snapshot for a mesh, as well as any conversion to mesh geometry at all. I do this in order to use the methods of meshop mapfaces to elements that are not part of polyop.
I assume that after improving the code and algorithms, we can increase the performance up to 4 times continuing to use only pure maxscript.


#24

Here is an example file.
Katwijk.max (25.9 MB)

You can ignore the roofs, only the walls are relevant.

@Serejah I did a quick test and it seems fast, but I’m not sure how fast. I only tried a small portion of the example file. It was faster than my original script anyway.

I did a test in Blender, which is the source app for the buildings, and it did it in about 4 min 45 sec. I first clicked left, and then bottom. Maybe it could do it twice as fast if there was a button for bottom left align, but there’s not.


#25

I’ve made the test - do all using c++ :
roofs :
CPP SDK elements:22610 time:205

walls:
CPP SDK elements:137464 time:4315

the time in msec… :wink: it definitely beats the Blender


#26

not bad for 131391 uv elements :slight_smile:


#27

walls are 137464 elements… what I found


#28

Very nice :slight_smile:
I guess I will have to learn a bit more to progress further :wink:
@denisT What’s your opinion on python in Max?


#29

Most likely your number is more correct. I just copy pasted uvs to mesh and used MNMeshElements to check the count. And maybe it isn’t a valid method at all.


#30

I think that is possible to make pure MXS version which can do the job for about 40-60 sec


#31

Oh wow, that would still be fantastic! So there is still reason for me to dig deeper :+1:


#32

Serejah,
do you remember that MXS algorithm to find all mesh geom elements? You already found it once on this forum…


#33

this was a greatest thread of all times


#34

I posted above my updated version of Jorge’s code. If I remember correctly it was working bit faster, but I didn’t do muchs tests to see if it doesn;t break on some corner case scenarios


#35

Thanks! :+1:
I will try to make this UV shift thing based on fast element search using only MXS… the same I do in my cpp code


#36

I didn’t expect this kind of help, I really appreciate it, both of you :pray:


#37

and finally:

fn shiftPolyMapAllElements node ch:1  =
(
	local faces = #{1..node.numfaces}
	local numtverts = polyop.getnummapverts node ch
	local verts = for v = 1 to numtverts collect #()
	local undone = #{1..numtverts}
	local elements = #()
	
	getmapface = polyop.getmapface 
	getmapvert = polyop.getmapvert
	setmapvert = polyop.setmapvert
		
	for f in faces do
	(
		tvv = getmapface node ch f
		for tv in tvv do append verts[tv] f
	)

	for i in faces do
	(		
		element = #(i)
		tverts = #()
		for j in element where faces[j] do
		(
			faces[j] = off
			f = getmapface node ch j
			
			for k=1 to f.count do
			(
				v = f[k]
				if undone[v] do 
				(
					join element verts[v]
					append tverts v 
					undone[v] = off 
				)
			)
		)
		
		u = 1e9
		v = 1e9
		
		pp = for tv in tverts collect
		(
			p = getmapvert node ch tv
			if p.x < u do u = p.x
			if p.y < v do v = p.y
			p
		)
		shift = [u,v,0]
		
		k = 1
		--format ">> % = %\n" tverts.count tverts
		for tv in tverts do
		(
			setmapvert node ch tv (pp[k] - shift) 
			k += 1
		)

		append elements tverts.count
	)
	
	update node
	elements
)
undo "Shift POLY Elements" on
(
	gc()
	node = $
	converttopoly node -- for undo!!!
	t1 = timestamp()
	m1 = heapfree
	elements = shiftPolyMapAllElements node
	format "MXS POLY elements:% time:% memory:%  >> %\n" (try(elements.count) catch(-1)) (timestamp() - t1) (m1 - heapfree) elements
)

WALLS:
MXS POLY elements:137464 time:4237 memory:268027116L >> #(5, 4, 5, 4, 5, 4, 5, 4, 13, 12, 11, 12, 7, 4, 4, 8, 4, 19, 4, 4, …)

pure MXS is ~4 sec on my machine (!)

Blender sucks! :stuck_out_tongue_closed_eyes:


#38

Thank you for restoring my faith, oh wise one :pray:
Seriously though, that’s pretty awesome :exploding_head:
I’ll try it out tomorrow!
Thanks for the help! I hope others find it useful too!
If anyone needs to bottom left align 100k+ UV islands, they will find this thread :grin:


#39

Tried it and it works great. Very fast! I can now do this step in Max :slight_smile:
Out of interest, what are the main differences from the first script I made, that result in such an improvement?


#40

do you see any sign of an unwrap in the code?
the rest is just a very clever algorithm to lookup for uv elements
moving verts is simple, knowing which ones to move is not :wink: