[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.
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.