Notifications
Clear all

[Closed] accelerating geometry export with Dotnet and c++

Hello There,

I have written a geometry exporter for max, for not so well known renderer: redqeen.
I made it work multithreaded. The base idea of the script was the example in the maxscript help file. I was wondering if it is possible to increase the speed of export, if I would would make a c# libarary or something.
Now it works as :
snapshot, and then cycle through the vertices, polygons, and texture vertices. And then stream it out.

On bigger scenes/objects it is still a bottleneck.

Anyone, please would advise me, any method would work faster?

Thank you very much.

6 Replies

Native code tends to make it go faster (i.e. using the C++ SDK), presumably since you don’t incur overhead from the maxscript interpreter. Other than that, you may still be able to speed up your maxscript a bit too – hard to say without seeing it though.

I’d probably do the export via the C++ SDK though.

I have been thinking about this, is it that I have to make 2008 x32/x64 and 2009 x32/x64 versions then, or lets say, the 2008 x32 would run smoothly on all versions, with maybe a slightly less speed?

I can include the most important part of the code.
THanks very much to look into it.

takencount is a variable wich shows that the current object is already being exported or not by an other thread…

The treads are started by automatically based on the number of cores, and it is dotnet.


takencount is a variable wich shows that the current object is already being exported or not by an other thread...


function geom1 = (

  print "start export geomerty 1"

  out_path = xscenefolder as string
  out_name_g =  out_path + "geometry.rrt"
  out_file_g = createfile out_name_g
  
		vpr1b = selarr_g.count as float -- PROGRESS BAR VARIABLE
		for l=1 to selarr_g.count do  (
		if cancelpress == true then exit -- Cancel pressed
		if takencount == l or takencount > l do continue
		takencount = l
	
                      vpr1a = l as float -- PROGRESS BAR
		xpr1 = ((vpr1a/vpr1b)*100.0) as float-- PROGRESS BAR
		mainroll.geomexp1pr.value = xpr1 -- PROGRESS BAR

--  START EXPORT 

		obj = selarr_g[l]
		if obj.material != undefined then 
	(
		matname = obj.material.name
		tmesh = snapshotAsMesh obj	
		num_verts = tmesh.numverts 
		if tmesh.numverts < 3 do continue
		num_tverts = tmesh.numtverts 
		num_faces = tmesh.numfaces
		format "mesh 
" to:out_file_g
		format "name \"%\"  
" obj.name to:out_file_g
		format "smooth %
" glsmoothst to:out_file_g
		format "material \"%\"
" matname to:out_file_g
	) 
		else -- if the material doesnt exists we use redqueen default
	( 
	
		tmesh = snapshotAsMesh obj		
		num_verts = tmesh.numverts
		num_tverts = tmesh.numtverts 
		if num_verts < 3 do continue
		num_faces = tmesh.numfaces
		format "mesh 
" to:out_file_g
		format "name \"%\"  
" obj.name to:out_file_g
		format "smooth 30
" to:out_file_g
		format "material \"rqdefault\"
" to:out_file_g
		
	)	
	
	-- vertex export
	
		for v = 1 to num_verts do
	(
		vert = getVert tmesh v
		format "  vertex % % %
" vert[1] vert[2] vert[3] to:out_file_g
	)
	
	-- uvw export
			
		if tmesh.numtverts != 0 then (
		
		meshuvw = True
		
		for t = 1 to num_tverts do
	(
		tvert = getTvert tmesh t
		
		tx = tvert[1] -- as integer 
		ty = tvert[2] -- as integer
 		tz = tvert[3] -- as integer
		
		format "  texel % % %
" tx (1-ty) tz to:out_file_g
	)	
	)
		
	-- polygon export	
		
		if meshuvw == True then 
	(
		for f = 1 to num_faces do
	(
		mface = meshop.getmapface tmesh 1 f
		mx = mface[1] as integer -1
		my = mface[2] as integer -1
		mz = mface[3] as integer -1
		face = getFace tmesh f
		fx = face[1] as integer -1
		fy = face[2] as integer -1
		fz = face[3] as integer -1
		format "  polygon %/% %/% %/%
" fx mx fy my fz mz to:out_file_g
	)
	) else 
	(
			for f = 1 to num_faces do (
			
		face = getFace tmesh f
	    fx = face[1] as integer -1
	    fy = face[2] as integer -1
		fz = face[3] as integer -1
		format "  polygon % % %
" fx fy fz to:out_file_g
	)	
	)
		format "end 

" to:out_file_g
	)

print "FINISHED export geomerty 1"
close out_file_g
geom1export = true -- SUCESSS..
ingnorediffuse = False

)


I’ve found that you can significantly increase performance by buffering your writes to a stringstream, then writing to the file once (or fewer times).

On top of that, writing this geometry export routine in C++, using that technique should speed things up even more.

Regarding SDK -> Max version compat: I don’t remember off-hand, but the SDK docs should mention which versions of the SDK work with which versions of max.

Thanks a lot, I experimented a little with stringstream, it works much faster on only one object. I am puzzled, when there is more object the whole thing becomes slow, the processor usage drops to 20-50%. On one objects, it is amazing fast.
Hmmm…

Perhaps because when you have many objects you run out of physical memory (since string-streams are memory buffers) and so the system starts paging. Perhaps it would be wiser to use a stringstream buffer per object, do a disk-write, then reuse the same stringstream for the next object – instead of attempting to hold your entire scene’s geometry in a string stream, then doing one write at the end.

yes, but then there is no speed improvement, actually for many objects it worked better the original way. Only for one object it worked fine.
Unfourtunately I dont know how to improve further, Dotnet is not documented well in maxscript and c++ thing is a different story. When I am finished it, I will try c++ with the sdk. But I will ask somebody that what are the possibilities…
In the other hand the file format is also sort of responsible. Its not so very effective, maybe some binary format would perform better, now its some sort of xml format.