Notifications
Clear all

[Closed] Improve speed of "Create box()"

Hi, is there anyway to improve the speed of this script:
Currently it takes ~10sec with n at 15 and I would like to use way larger n but at the current performance its a not really practical.

EDIT: (Added 3dsMax 2014 results)

[ORIGINAL] (UPDATED)
3dsMax 2015:
: (n15 / 3375boxes) [Time: 9.5 sec] [Mem: 904296L]
: (n50 / 125000 boxes) [Time: ~ 2h ] [Mem: 2882104L]

3dsMax 2014:
: (n15 / 3375boxes) [Time: 9.503 sec]
[I]– > : Patan77 [/I]

fn fn_createBoxSpeedTest = ( 
	delete objects 
	gc()
	local timeStart = timestamp()
	with undo false
	with redraw off
	--delete $polyobj
	local polyobj = editable_mesh name:"polyObj" 
	local n = 15
	convertTo polyobj  Editable_Poly
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				local b = box()
				rng = (random 0.1 1)
				b.length = rng
				b.width = rng
				b.height = rng
				b.center = [x,y,z]
				polyop.attach polyobj b
			)
		)
	)
	polyobj.wirecolor = [255,0,0]
	gc()
	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()

thanks in advance


Currently Fastest Version :

[ multi-threaded ]

3dsMax 2014
n15: Time: 0.005sec Mem: 416L
n50: Time: 0.027sec Mem: 416L
n100: Time: 0.181sec Mem: 416L

(UPDATED)
[I]– > : patan77 [/I] [I]– > : aaandres [/I]

[View Code]( http://www.patan77.com/fastest_attach/genBoxesMultiThreaded.txt) 

3dsMax 2015:
: (n15 / 3375boxes) [Time: 0.006 sec] [Mem: 440L]
: (n50 / 125000 boxes) [Time: 0.243 sec] [Mem: 432L]

3dsMax 2014:
: (n15 / 3375boxes) [Time: 0.005 sec] [Mem: 416L]
: (n50 / 125000 boxes) [Time: 0.068 sec] [Mem: 416L]
[I]– > : aaandres [/I] [I]– > : polytools3d [/I]

(
	fn compileCString =
	(
		SuperCubeClassName = "PathScripts.SuperCube"
		classStr = (
		"
			using System;
			using Autodesk.Max;
			using System.Collections.Generic;

			namespace PathScripts
			{
				class SuperCube
				{
					static public IGlobal global = GlobalInterface.Instance;
					static public IInterface14 ip = global.COREInterface14;

					static public void createSuperCube(int numCubes)
					{
						int[][] Faces = new int[12][] { new int[3] { 0, 2, 3 }, new int[3] { 3, 1, 0 }, new int[3] { 4, 5, 7 }, new int[3] { 7, 6, 4 },
														new int[3] { 0, 1, 5 }, new int[3] { 5, 4, 0 }, new int[3] { 1, 3, 7 }, new int[3] { 7, 5, 1 },
														new int[3] { 3, 2, 6 }, new int[3] { 6, 7, 3 }, new int[3] { 2, 0, 4 }, new int[3] { 4, 6, 2 }};
						float[][] Verts = new float[8][] { new float[3] { -0.5f, -0.5f, -0.5f }, new float[3] { 0.5f, -0.5f, -0.5f }, new float[3] { -0.5f, 0.5f, -0.5f }, new float[3] { 0.5f, 0.5f, -0.5f },
														   new float[3] { -0.5f, -0.5f, 0.5f }, new float[3] { 0.5f, -0.5f, 0.5f }, new float[3] { -0.5f, 0.5f, 0.5f }, new float[3] { 0.5f, 0.5f, 0.5f }};
						uint[] theElementSmooth = new uint[12] { 2, 2, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 };

						IClass_ID cid = global.Class_ID.Create( (uint) BuiltInClassIDA.EDITTRIOBJ_CLASS_ID , 0 );

						// Create a new TriObject.
						object objectEditMesh = ip.CreateInstance(SClass_ID.Geomobject, cid as IClass_ID);
						// Create a new node to hold it in the scene.
						IObject objBaseObject = (IObject)objectEditMesh;
						IINode node = global.COREInterface.CreateObjectNode( objBaseObject );
						// Name it unique.
						string newName = \"SuperCube\";
						//ip.MakeNameUnique(ref newName);
						node.Name = newName;
						// Cast to TriObject
						ITriObject triNew = objBaseObject as ITriObject;

						int nTotal = numCubes * numCubes * numCubes;
						Random r = new Random();
						int countVerts = 0;
						int actualVert = 0;
						int actualFace = 0;
						double range = 1.0 - 0.1;
						
						IMesh TMESH = triNew.Mesh;

						// Setup the new TriObject with number of faces and verts
						TMESH.SetNumFaces(12 * nTotal, false, false);
						TMESH.SetNumVerts(8 * nTotal, false, false);
						
						IList<IFace> MESH_FACES = TMESH.Faces;

						for (int z = 0; z < numCubes; z++)
						{
							for (int y = 0; y < numCubes; y++)
							{
								for (int x = 0; x < numCubes; x++)
								{
									actualVert = (8 * countVerts);
									actualFace = (12 * countVerts);
									float rng = (float)(r.NextDouble() * range + 0.1);
									for (int v = 0; v < 8; v++)
									{
										TMESH.SetVert(v + actualVert, Verts[v][0] * rng + x, Verts[v][1] * rng + y, Verts[v][2] * rng + z);
									}
									for (int f = 0; f < 12; f++)
									{
										IFace FACE = MESH_FACES[f + actualFace];
										FACE.SetVerts(Faces[f][0] + actualVert, Faces[f][1] + actualVert, Faces[f][2] + actualVert);
										FACE.SetEdgeVisFlags(EdgeVisibility.Vis, EdgeVisibility.Vis, EdgeVisibility.Invis);
										FACE.SmGroup = theElementSmooth[f];
									}
									countVerts++;
								}
							}
						}

						// Assign identity transform, position and center pivot.
						//IMatrix3 tm = global.Matrix3.Create(); tm.IdentityMatrix();
						//IPoint3 pt0 = global.Point3.Create(0, 0, 0);
						//node.SetNodeTM(0, tm);
						//node.ObjOffsetPos = pt0;
						//node.CenterPivot(0, false);
						// make it drawable.
						TMESH.InvalidateGeomCache();
						//ip.RedrawViews(0, RedrawFlags.Normal, null);
					}

				}
			}
		"
		)
	
		compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
		dotnet.setlifetimecontrol compilerParams #dotnet
		compilerParams.ReferencedAssemblies.Add("System.dll");
		compilerParams.ReferencedAssemblies.Add( getdir #maxroot + "Autodesk.Max.dll");
		compilerParams.GenerateInMemory = on
		csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
		compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(classStr)
		dotnet.setlifetimecontrol compilerResults #dotnet
		
		----	CHECK COMPILE
		if (compilerResults.Errors.Count > 0 ) then
		(
			local errs = stringstream ""
			for i = 0 to (compilerResults.Errors.Count-1) do
			(
				local err = compilerResults.Errors.Item[i]
				format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
			)
			format "%
" errs
			return undefined
		)			
		----	
		else
		(
			compilerResults.CompiledAssembly
		)
	)
	
	global assembly = compileCString()
	SuperCube = assembly.CreateInstance "PathScripts.SuperCube"

		
	/* TEST */
		
	delete objects
	gc()

	st=timestamp(); sh=heapfree

	SuperCube.createSuperCube 15
		
	format "time:% heap:%
" (timestamp()-st) (sh-heapfree)
		
)



(UPDATED 3)

3dsMax 2015:
: (n15 / 3375boxes) [Time: 0.045 sec] [Mem: 16208L] [/I]
: (n50 / 125000 boxes) [Time: 1.492 sec] [Mem: 16584L]

3dsMax 2014:
Not working at the moment
[I]– > : Patan77 [/I]

fn fn_createBoxSpeedTest  = (
	hf = heapfree
	local timeStart = timestamp()
	with redraw off(
		undo off(
			sliderTime = 0
			local n = 15
			local bScript = 
			("
				on ChannelsUsed pCont do
				(
					pCont.useScale = true
					pCont.usePosition = true
				)
				on Proceed pCont do 
				(
					n = ((pCont.NumParticles())^(1/3.0))
					i = [0,0]
					for z = 0 to (n - 1) do (
						for y = 0 to (n - 1) do (
							for x = 0 to (n - 1) do (
								rng = (random 0.1 1)
								rngUV = (random 0.0 1.0)
								i.x += 1
								pCont.particleIndex = i.x
								pCont.particleScale = rng
								pCont.particlePosition = [x,y,z] 
							)
						)
					)
				)
			")
			local pf = PF_Source Quantity_Viewport:100 Particle_Amount_Limit:1000000
			ParticleFlow.BeginEdit()
			pf.AppendAction (RenderParticles())
			local e1 = Event()
			e1.AppendAction (Birth Amount: (n^3) Emit_Start:0 Emit_Stop:0)
			e1.AppendAction (Script_Operator Proceed_Script: bScript)
			e1.AppendAction (ShapeLibrary '3D_Type':0 size:1)
			pf.appendInitialActionList e1
			ParticleFlow.EndEdit()
			mm = mesh name:"result" mesh:(snapshotasmesh (getnodebyname (pf.name + "->" + e1.name))) 
			particleFlow.BeginEdit()
			particleFlow.delete pf
			particleFlow.EndEdit() 	
		)
	)
	local timeStop = timestamp()
	print ("Time: " + (((timeStop - timeStart)/1000.0)as string) + " sec Mem: " + ((hf-heapfree) as string))
)
fn_createBoxSpeedTest()


3dsMax 2015:
: (n15 / 3375boxes) [Time: 0.033 sec] [Mem: 368L]
: (n50 / 125000 boxes) [Time: 2.37 sec] [Mem: 368L]

3dsMax 2014:
: (n15 / 3375boxes) [Time: 0.006 sec] [Mem: 360L]
: (n50 / 125000 boxes) [Time: 0.205 sec] [Mem: 368L]
[I]– > : aaandres [/I]

[View Code]( http://www.patan77.com/download/CODE_fn_createBoxSpeedTest_C01.txt) 

I[/I]

[I]– > : Serejah [/I]
3dsMax 2015:
: (n15 / 3375boxes) [Time: 0.04 sec] [Mem: 1432L]
: (n50 / 125000 boxes) [Time: 21.62 sec] [Mem: 1432L]

3dsMax 2014:
: (n15 / 3375boxes) [Time: 0.037 sec] [Mem: 1384L]
: (n50 / 125000 boxes) [Time: 21.555 sec] [Mem: 1384L]

fn fn_createBoxSpeedTest = (
	delete objects 
	(
		gc()
		with redraw off (
			with undo off (	
				t1=timestamp()
				hf = heapfree
				size = 15
				w = 10
				h = 10
				l = 10
				ps = (w/2.0)
				m = mesh numverts:(size^3) numfaces:(size^3)
				i = [0,0]
				for x=0 to size-1 do(
					for y=0 to size-1 do(
						for z=0 to size-1 do(
							setvert m (i.x += 1) [ x*w, y*l, z*h ]
						)							
					)
				)
				p = PArray()
				p.seed = (random 0 99999)
				p.Emitter_Stop = 0f
				p.quantityMethod = 1
				p.Total_Number = size^3
				p.formation = 2
				p.Growth_Time = 0f
				p.Fade_Time = 0f
				p.size = ps 
				p.standardParticle = 1
				p.viewPercent = 100
				p.viewType = 2
				p.Size_Variation = 100
				p.emitter = m
				mm = Mesher()
				mm.pick = p
				converttomesh mm
				delete p
				delete m
				format "Time: %sec. Mem: %
" ((timestamp()-t1)/1000 as float) (hf-heapfree)
			)
		)
	)
)
fn_createBoxSpeedTest()

I[/I]

3dsMax 2015:
: (n15 / 3375boxes) [Time: 0.150 sec] [Mem: 4969600L]
: (n50 / 125000 boxes) [Time: 11.98 sec] [Mem: 184982226L]

3dsMax 2014:
: (n15 / 3375boxes) [Time: 0.12 sec]
: (n50 / 125000 boxes) [Time: 12.338 ]
[I]– > : aaandres [/I]

fn fn_createBoxSpeedTest  = (
	timeStart = timestamp()
	-- Verts:
	theElementVerts = #([-0.5,-0.5,-0.5], [0.5,-0.5,-0.5], [-0.5,0.5,-0.5], [0.5,0.5,-0.5], [-0.5,-0.5,0.5], [0.5,-0.5,0.5], [-0.5,0.5,0.5], [0.5,0.5,0.5])
	-- Faces:
	theElementFaces = #([1,3,4], [4,2,1], [5,6,8], [8,7,5], [1,2,6], [6,5,1], [2,4,8], [8,6,2], [4,3,7], [7,8,4], [3,1,5], [5,7,3])
	-- Smooth
	theElementSmooth = #(2, 2, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64)

	colorb = (color (random 0 255) (random 0 255) (random 0 255))
	countFaces = 0
	vertsArray = #()
	facesArray = #()
	n = 15
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				rng =  (random 0.1 1)
				VertPos = for v in theElementVerts collect (posLocal = v*rng; [posLocal.x + x, posLocal.y + y, posLocal.z + z])
				join vertsArray VertPos 
				Faces = for f in theElementFaces collect (f + (8 * countFaces))
				join facesArray Faces
				countFaces += 1
			)
		)
	)

	oo = mesh vertices:vertsArray faces:facesArray
	oo.wirecolor = colorb
	oo.name =  "SuperCube"

	for i = 1 to facesArray.count by 12 do
	(
		for j = 0 to 11 do
		(
			setFaceSmoothGroup oo (i+j) theElementSmooth[j+1]
		)
	)
	update oo

	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()

Note: All codes are a collaboration between:
Patan77
aaandres
denisT
polytools3d
Serejah

70 Replies

Search for ‘Fast attach’ in this forum. Possibly you have a performance problem in the attach command.

1 Reply
(@denist)
Joined: 10 months ago

Posts: 0

absolutely true

also it would be faster to make a poly-box template, and make an instances of this template instead of making a new box object.

delete objects
gc()

(
	delete objects
	gc()
	t = timestamp()
	h = heapfree

	b = box width:2 length:2 height:2
	converttopoly b
	
	for k=1 to 1000 do
	(
		instance b
	)

	format "instance	 >> time:% heap:%
" (timestamp() - t) (h - heapfree)
)

(
	delete objects
	gc()
	t = timestamp()
	h = heapfree

	for k=1 to 1000 do
	(
		b = box width:2 length:2 height:2
		converttopoly b
	)

	format "predefined	 >> time:% heap:%
" (timestamp() - t) (h - heapfree)
)

(
	delete objects
	gc()
	t = timestamp()
	h = heapfree

	for k=1 to 1000 do
	(
		b = box()
		b.width = 2
		b.length = 2
		b.height = 2
		converttopoly b
	)

	format "make and set >> time:% heap:%
" (timestamp() - t) (h - heapfree)
)
 
3 Replies
(@patan77)
Joined: 10 months ago

Posts: 0

Thx,
Yeah, but for my real script every box need to be a different size so wont work with instances.

(@denist)
Joined: 10 months ago

Posts: 0

you can scale it with instancing (and position as well):

instance b scale:<scale> pos:<pos>

or do full transform if you need

(@patan77)
Joined: 10 months ago

Posts: 0

Didn’t think about that, but for me instance is slower then creating box(), instance: 0.592sec vs box() 0.444sec, but still of the 10sec 9.5 is the attach process

instance: (0.592sec)

fn fn_createBoxSpeedTest = (
	delete objects
	gc()
	local timeStart = timestamp()
	with undo false
	with redraw off
	local polyobj = editable_mesh name:"polyObj" 
	local n = 15
	convertTo polyobj  Editable_Poly
	local b = (box length:1 width:1 height:1)
	local bi
	local rng
	converttopoly b
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				rng =  (random 0.1 1)
				bi = (instance b scale:[rng,rng,rng]) 
				bi.center = [x,y,z]
				--polyop.attach polyobj bi
			)
		)
	)
	polyobj.wirecolor = [255,0,0]
	delete b
	gc()
	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()

box(): (0.444sec)

fn fn_createBoxSpeedTest = (
	delete objects
	gc()
	local timeStart = timestamp()
	with undo false
	with redraw off
	local polyobj = editable_mesh name:"polyObj" 
	local n = 15
	convertTo polyobj  Editable_Poly
	local b
	local rng
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				rng =  (random 0.1 1)
				b = (box length:rng width:rng height:rng)
				b.center = [x,y,z]
				-- polyop.attach polyobj b
			)
		)
	)
	polyobj.wirecolor = [255,0,0]
	gc()
	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()

your performance test is not correct… you have to add to ‘just create box’ method conversion to poly…

1 Reply
(@patan77)
Joined: 10 months ago

Posts: 0

sure if I add converttopoly after box() its 0.7sec so then its slower then instance, but if I have polyop.attach enabled and do just box() then attach and skip converttopoly its faster then instance and attach:
instance + attach: (“Time: 9.709 )
box() + attach: (“Time: 9.381 sec”)

find ‘fast attach’ on this forum first

Ok, this is what I came up with (recursive attach script) :

3375 objects 0.45sec instead of 9.5sec so that’s much faster

fn quickAttachRec inArr = (
	if inArr.count == 1 do (
		return inArr[1]
	)
	for i = 1 to (inArr.count - 1) by 2 do (
		polyop.attach inArr[ i ] inArr[i+1]
	)
	quickAttachRec (objects as array)
)

fn fn_Timer = (
	gc()
	local timeStart = timestamp()
	quickAttachRec (objects as array)
	local timeStop = timestamp()
	print ("Time: " + (((timeStop - timeStart)/1000.0)as string) + " sec")
)
fn_Timer()

And “complete” script: n at 15 (~2sec) (would like it to be way faster still[/I])

fn quickAttachRec inArr = (
	if inArr.count == 1 do (
		return inArr[1]
	)
	for i = 1 to (inArr.count - 1) by 2 do (
		meshop.attach inArr[ i ] inArr[i+1]
	)
	quickAttachRec (objects as array)
)

fn fn_createBoxSpeedTest = (
	delete objects
	gc()
	local timeStart = timestamp()
	with undo false
	with redraw off
	local n = 15
	local b = (box length:1 width:1 height:1)
	local bi
	local rng
	converttomesh b
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				rng =  (random 0.1 1)
				bi = (instance b scale:[rng,rng,rng]) 
				bi.center = [x,y,z]
			)
		)
	)
	delete b
	InstanceMgr.MakeObjectsUnique (objects as array)  #individual 
	quickAttachRec (objects as array)
	gc()
	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()

this is not the ‘canonical’ FastAttach method. I’m not sure that yours is better.

3 Replies
(@aaandres)
Joined: 10 months ago

Posts: 0

I’ve tryed the ‘canonical’ and the result is the same, possibly because all meshes are boxes with the same number of verts.
The only improvements I’ve found are:

  • Go back to copy instead of instances (InstanceMgr takes half a second or more)
  • delete the end gc() (that is another half second)
  • scale after the creation (it’s 0,1 seconds better)
    So, I get a total of 1,23 seconds.

fn quickAttachRec inArr = (
	if inArr.count == 1 do (
		return inArr[1]
	)
	for i = 1 to (inArr.count - 1) by 2 do (
		meshop.attach inArr[i] inArr[i+1]
	)
	quickAttachRec (objects as array)
)

fn fn_createBoxSpeedTest = (
	delete objects
	gc()
	local timeStart = timestamp()
	with undo false
	with redraw off
	local n = 15
	local b = (box length:1 width:1 height:1)
	local bi
	local rng
	converttomesh b
	for z = 0 to (n-1) do (
		for y = 0 to (n-1) do (
			for x = 0 to (n-1) do (
				rng =  (random 0.1 1)
				bi = copy b  
				bi.center = [x,y,z]
				bi.scale = [rng,rng,rng]
			)
		)
	)
	delete b
	quickAttachRec (objects as array)
	
	print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
)
fn_createBoxSpeedTest()


(@denist)
Joined: 10 months ago

Posts: 0

recursive method needs better way to work with list of original nodes. (it uses now (objects as array) which not correct in general).
‘canonical’ version makes array operations (deleteitem) what takes a time.

(@patan77)
Joined: 10 months ago

Posts: 0

Well I didn’t spend much time writing that script, its just a test not final code, here is another version without the (objects as array, )its still a bit flawed tho, need to use object count of power of 2 like 4096objects etc. or run it multiple times

n 16 (4096)objects 0.464sec (n15 3375objects est: 0.365sec)

fn quickAttachRec inArr = (
	tmpAry = #()
	if inArr.count == 1 do (
		return inArr[1]
	)
	for i = 1 to (inArr.count - 1) by 2 do (
		meshop.attach inArr[i] inArr[i+1]
		append tmpAry inArr[i]
	)
	quickAttachRec tmpAry
) 

my thought is that recursive version has to be slower and has to use much more memory.

try it for bigger numbers.

If Patrik is interested, here’s the function I’ve used to compare:

fn customAttach nodes = 		
	(
		fn qsfn v1 v2 = v1.numVerts - v2.numVerts		
		qSort nodes qsFn
		local k = 1
		local att = meshop.attach		
		while nodes.count > 1 do
		(
			local nk = nodes[k]
			att nk nodes[k+1]
			deleteItem nodes (k+1)
			if nodes[k+2]!=undefined and nk.numVerts >= nodes[k+2].numVerts do k += 1
			if k >= nodes.count do k = 1			
		)
		nodes[1]
	)

that can be simplified for this special case to: (no need to sort, no need to check later nodes with greater number of verts)

fn customAttach nodes = 		
	(
		--fn qsfn v1 v2 = v1.numVerts - v2.numVerts		
		--qSort nodes qsFn
		local k = 1
		local att = meshop.attach		
		while nodes.count > 1 do
		(
			local nk = nodes[k]
			att nk nodes[k+1]
			deleteItem nodes (k+1)
			--if nodes[k+2]!=undefined and nk.numVerts >= nodes[k+2].numVerts do k += 1
			if nodes[k+2]!=undefined do k += 1
			if k >= nodes.count do k = 1			
		)
		nodes[1]
	)


1 Reply
(@patan77)
Joined: 10 months ago

Posts: 0

thx definitely useful info

Trying going about it from another angle by using pflow scripting instead with n 15 3375boxes random size I got it down to (0.062 sec) Time: 0.056 sec generate boxes then 0.004sec for snapshot

Code is just temporary prof of concept to test the speed, need clean it up alot, but yeah this is for sure they way to do it:

on ChannelsUsed pCont do
(
	pCont.useScale = true
)

on Init pCont do 
(

)


on Proceed pCont do 
(
	--if pflowRun == false then (
		pflowSource = $ --select Pflow obj before ctrl+e
		gc()
		timeStart = timeStamp()
		n = 15
		i = 1
		rng
		for z = 0 to (n - 1) do (
			for y = 0 to (n - 1) do (
				for x = 0 to (n - 1) do (
					rng = (random 0.1 1)
					pCont.AddParticle()
					pCont.particleIndex = i
					pCont.particleScale = rng
					pCont.particlePosition = [x,y,z] 
					i += 1
				)
			)
		)
		--m = Mesher()
		--m.pick = pflowSource
		--snapshot m
		--flowSource.Enable_Particles = false
		--delete m 
		--pflowRun = false
		timeStop = timeStamp()
		print ("Time: " + (((timestamp() - timeStart)/1000.0)as string) + " sec")
	--)
)

on Release pCont do 
(


)
Page 1 / 5