Hey guys,
So I've created a really fast attach algorithm for attaching large arrays of objects together. I searched the forum and didn't find any other threads mentioning this method so I'm assuming it's unique.
I call it "Cluster Attach". Basically, instead of just attaching one object to the previous object over and over until all objects are attached, it progressively attaches and clusters objects into smaller and smaller groups of remaining objects until only the final object remains. It's extremely simple, and for some reason it reduces the amount of time it takes to attach large groups of objects together by a huge amount.
For example, I did some tests where I attach 1000 teapots together. A typical linear approach (where you just cumulatively attach objects together one after the other) took [b]119.7 seconds[/b] to complete.
However, using the cluster attach method, the operation took only[b] 5.7 seconds[/b] to complete. Also, if you simply pass the cluster function an array of editable_poly meshes, and take out the line that converts non-editable_polys to editable_polys on the fly, the time can be nearly halved.
(For those wondering, undo was disabled with "undo off" for both of these tests. Usually the answer to "how can I speed up large attach operations" is to disable undo, but as you can see, the cluster approach offers even further speed improvements)
I was so surprised by the results that I decided to come here and post the generalized functions for people to use, as well as a little script with a rollout that demonstrates the two algorithms side by side, and prints out the amount of time each one takes to complete.
[b]Linear Attach (slow) Algorithm:[/b]
---pass an array of geometry nodes to this function and it will return the combined result
function linearAttach objArr =
(
converttopoly objArr[1]
undo off
(
for q in 2 to objArr.count do
(
polyop.attach objArr[1] objArr[q]
)
)
return objArr[1]
)
[b]Cluster Attach (fast) Algorithm:[/b]
---pass an array of geometry nodes to this function and it will return the combined result
function clusterAttach objArr =
(
j = 1
count = objArr.count
undo off
(
while objArr.count > 1 do
(
if classof objArr[j] != Editable_Poly then converttopoly objArr[j]
polyop.attach objArr[j] objArr[j+1]
deleteItem objArr (j+1)
j += 1
if (j + 1) > objArr.count then j = 1
)
)
return objArr[1]
)
Here is a sample script you can run to test the two algorithms side by side. You can manually enter the number of teapots to be generated (they'll be generated in a grid-like pattern so you can see them individually), and the total attach time gets printed to the listener after the algorithm completes.
try(destroydialog teaRoll)catch()
rollout teaRoll "Roll"
(
spinner numPots "# Teapots: " type:#integer range:[1,5000,250]
button pressMe "Cluster Attach"
button pressMe2 "Linear Attach"
progressbar prog1 "" value:0
function makeTeapots total=
(
teaArr = #()
posX = 0
posY = 0
for q in 1 to total do
(
posX += 10
if posX > 1000 then
(
posY += 50
posX = 0
)
teaArr[q] = teapot()
teaArr[q].pos.x = posX
teaArr[q].pos.y = posY
)
return teaArr
)
function clusterAttach objArr =
(
j = 1
count = objArr.count
undo off
(
while objArr.count > 1 do
(
prog1.value = (1 - ([objArr.count/count](http://objArr.count/count) as float))*100
if classof objArr[j] != Editable_Poly then converttopoly objArr[j]
polyop.attach objArr[j] objArr[j+1]
deleteItem objArr (j+1)
j += 1
if (j + 1) > objArr.count then j = 1
)
)
return objArr[1]
)
function linearAttach objArr =
(
converttopoly objArr[1]
undo off
(
for q in 2 to objArr.count do
(
prog1.value = (q/objArr.count as float)*100
polyop.attach objArr[1] objArr[q]
)
)
return objArr[1]
)
on pressMe pressed do
(
delete $*
teaArr = makeTeapots numPots.value
tStart = timestamp()
clusterAttach teaArr
prog1.value = 0
tEnd = timestamp ()
print ("Attach finished. Total time: " + ((tEnd-tStart)/1000.0) as string + "s")
)
on pressMe2 pressed do
(
delete $*
teaArr = makeTeapots numPots.value
tStart = timestamp()
linearAttach teaArr
prog1.value = 0
tEnd = timestamp ()
print ("Attach finished. Total time: " + ((tEnd-tStart)/1000.0) as string + "s")
)
)
createdialog teaRoll
Anyways, I've often been frustrated by how slow it can be to attach huge numbers of objects together with maxscript, and I imagine other people have been too since I found a good number of threads asking how to speed things up....so hopefully people will find the cluster method helpful!