[Closed] Can't create fast split/crack algorithm
I need to split object into chunks of given size.
I wrote few versions of script, but each was too slow.
undo off
(
local startTime = timeStamp()
disableSceneRedraw()
progressStart "Chooping geometry..."
local object = $
resetXForm object
convertToMesh object
meshOp.autoedge object object.Edges 0 -- make all faces triangles
convertToPoly object
local chunkSize = 80
local Xsize = object.max.x - object.min.x
local Xchunks = ceil ((Xsize as float)/chunkSize)
local XchunkSize = (Xsize as float)/Xchunks
local Ysize = object.max.y - object.min.y
local Ychunks = ceil ((Ysize as float)/chunkSize)
local YchunkSize = (Ysize as float)/Ychunks
format "
X chunks: %, Y chunks %" Xchunks Ychunks
local chunkFaces = for i=1 to Xchunks*Ychunks collect #()
local pos, idx
local faceCount = polyop.getNumFaces object
for i=1 to faceCount do
(
pos = polyop.getFaceCenter object i
pos -= object.min
idx = (ceil (pos.x/XchunkSize)) + (Xchunks * (floor (pos.y/YchunkSize)))
append chunkFaces[idx] i
progressUpdate (100*i/faceCount)
)
local chunkName, chunks = #()
for i=1 to chunkFaces.count do
(
if chunkFaces[i].count > 0 then
(
object.wirecolor = random white black
chunkName = (uniqueName "Chunk_")
polyop.detachFaces object chunkFaces[i] delete:false asNode:true name:chunkName
append chunks (getNodeByName chunkName)
progressUpdate (100*i/chunkFaces.count)
)
)
delete object
enableSceneRedraw()
progressEnd()
print chunks
print( "Chooping time: " + (((timeStamp()-startTime)/1000.) as string) + "s" )
)
For me execution time for Teapot with radius 400 and 40 segments is more than one minute.
This script will chooping game map before export.
I saw “split chelenge” thread, but I not found better isue.
Try this:
undo off
(
local startTime = timeStamp()
disableSceneRedraw()
progressStart "Chooping geometry..."
local object = $
resetXForm object
convertToMesh object
meshOp.autoedge object object.Edges 0 -- make all faces triangles
convertToPoly object
local chunkSize = 80
local Xsize = object.max.x - object.min.x
local Xchunks = ceil ((Xsize as float)/chunkSize)
local XchunkSize = (Xsize as float)/Xchunks
local Ysize = object.max.y - object.min.y
local Ychunks = ceil ((Ysize as float)/chunkSize)
local YchunkSize = (Ysize as float)/Ychunks
format "
X chunks: %, Y chunks %" Xchunks Ychunks
local chunkFaces = for i=1 to Xchunks*Ychunks collect #{} --this is now a bitarray
local pos, idx
local faceCount = polyop.getNumFaces object
for i=1 to faceCount do
(
pos = polyop.getFaceCenter object i
pos -= object.min
idx = (ceil (pos.x/XchunkSize)) + (Xchunks * (floor (pos.y/YchunkSize)))
chunkFaces[idx][i] = true --we set the bit with face index to true to collect it
progressUpdate (100*i/faceCount)
)
local chunkName, chunks = #()
for i=1 to chunkFaces.count do
(
if chunkFaces[i].count > 0 then
(
newObject = copy object --clone the object
newObject.wirecolor = random black white --assign random color
newObject.name = uniqueName "Chunk_" --assign new name
polyOp.deleteFaces newObject (#{1..faceCount}-chunkFaces[i]) --delete all faces but the ones we want
append chunks newObject
progressUpdate (100*i/chunkFaces.count)
)
)
delete object
enableSceneRedraw()
progressEnd()
print chunks
print( "Chopping time: " + (((timeStamp()-startTime)/1000.) as string) + "s" )
)
Basically, detaching faces to a new node seems to be slower than cloning the node and deleting all faces that are not the ones you want. On my machine, the time for 400 radius 40 segments teapot went down from 49 seconds to 22 seconds.
Note that I switched the chunkFaces array to an array of bitarrays to be able to invert it quickly.
You code won’t works for me.
It throws “unknown system exception” (in middle of process O.o) at line:
newObject = copy object --clone the object
But in your method I don't need longer to work on editable_poly.
I needed that because of the meshOp no provides detach to node operation.
So I used mesh instead of poly and now it works, and works much faster.
Time shrink from 54s to 3s!
Thanks so much
Here is final code:
undo off
(
local startTime = timeStamp()
disableSceneRedraw()
progressStart "Chooping geometry..."
local object = $
resetXForm object
convertToMesh object
meshOp.autoedge object object.Edges 0 -- make all faces triangles
local chunkSize = 80
local Xsize = object.max.x - object.min.x
local Xchunks = ceil ((Xsize as float)/chunkSize)
local XchunkSize = (Xsize as float)/Xchunks
local Ysize = object.max.y - object.min.y
local Ychunks = ceil ((Ysize as float)/chunkSize)
local YchunkSize = (Ysize as float)/Ychunks
--format "
X chunks: %, Y chunks %" Xchunks Ychunks
local chunkFaces = for i=1 to Xchunks*Ychunks collect #{} --this is now a bitarray
local pos, idx
local faceCount = object.numFaces
for i=1 to faceCount do
(
pos = meshop.getFaceCenter object i
pos -= object.min
idx = (ceil (pos.x/XchunkSize)) + (Xchunks * (floor (pos.y/YchunkSize)))
chunkFaces[idx][i] = true --we set the bit with face index to true to collect it
progressUpdate (100*i/faceCount)
)
local chunkName, chunks = #()
for i=1 to chunkFaces.count do
(
if chunkFaces[i].numberset > 0 then
(
local newObject = copy object --clone the object
newObject.wirecolor = random black white --assign random color
newObject.name = uniqueName "Chunk_" --assign new name
meshOp.deleteFaces newObject (#{1..faceCount}-chunkFaces[i]) --delete all faces but the ones we want
append chunks newObject
)
progressUpdate (100*i/chunkFaces.count)
)
delete object -- delete original
enableSceneRedraw()
progressEnd()
--print chunks
print( "Chopping time: " + (((timeStamp()-startTime)/1000.) as string) + "s" )
)
Awesome, glad it works!
Not sure why it would crash on the copying – what version of Max was that in?
Um it crashing also with mesh, but on larger objects than with poly.
I using max 2010
I have no idea for that. I will mess wit garbage collecting.
EDIT: gc() no solves problem
It crashed mine too after running on a 100×100 plane. I’m using max 9 sp2 x64.
I created relay simple script that has same problem:
convertToMesh $
copies = #()
for i=1 to 3000 do
(
local c = copy $
c.pos = random [-100,-100,-100] [100,100,100]
local faces = #{}
--for j=1 to c.numFaces do if (random 0 1) == 1 then faces[j] = true -- random faces
faces = #{1..20} -- first 20 faces
meshOp.deleteFaces c.mesh faces--*/
append copies c
)
print copies
It happens often for custom object (rarely for primitives)
I tried fix that, but no success
I created a plane with 100×100 segments and run the above code. My memory went up to 17GB, but no crash. My heapSize was 74973184L (75MB) due to other scripts run before that. My Heap is set to 64MB initial size in the Preferences. The machine has 16 GB RAM.
Out of curiosity, how much is your Heap size? And is this in 32 or 64 bit?
It seems memory problem.
After some changes it gives me “out of memory” error dialog.
It works when new objects are deleted soon after delete the faces (only one chunk is exists at the moment). It makes possible to export chunks during detaching them.
[CENSORED WORDS HERE]
It still throwing the exception when copying.
Now I have no idea how to do it:banghead: