[Closed] Need help finishing / debugging script
Hi. I just started to work with mxs. This forum and a couple of others helped me a lot so I wanted to thank you all and ask for some more help if I may.
I made a script to remove zero area faces from the mesh(es) but I have some difficulties finishing it. It worked just fine the other day while I was still testing it in the editor. Then I dragged it onto a toolbar to make a macros and after that it stopped updating the Listener while in a loop. The script itself seems to be working but I need those progress / performance numbers at runtime to further polish / debug the code as it seems to have some issues in certain situations. I went back to launching it from editor but it’s still not working. I checked the code and didn’t find any reasons for that to be happening.
Any help is appreciated.
Thanks in advance.
global _user32
fn CreateUser32Assembly =
(
source = "using System;
"
source += "using System.Runtime.InteropServices;
"
source += "class User32
"
source += "{
"
source += " [DllImport(\"user32.dll\")]
"
source += " static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, uint flags);
"
source += " static uint FULL_REDRAW = 0x0185;
"
source += " public bool RedrawAllWindow(Int32 hWnd) { return RedrawWindow((IntPtr)hWnd, IntPtr.Zero, IntPtr.Zero, FULL_REDRAW); }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.AddRange #("System.dll")
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
_user32 = compilerResults.CompiledAssembly.CreateInstance "User32"
)
CreateUser32Assembly()
try(destroydialog Myroll) catch()
total_f = 0
processed_f = 0
lp_count = 0
lp_thresh = 5000
df_count = 0
df_thresh = 5000
df_total = 0
lp_fdelta = 0
lp_flast = 0
for o in (selection as array) do total_f += o.numfaces
--format "%
" total_f as string
format "Total faces selected: %
" (formattedPrint total_f format:"8.0u")
rollout Myroll "Del 0 area faces"
(
button bt_start "Start" width:100
on bt_start pressed do
(
st = lp_tlast = lp_tdelta = timestamp()
disableSceneRedraw()
undo off
exit_bool = 0
_user32.RedrawAllWindow (windows.getchildhwnd 0 Myroll.title)[1]
for o in (selection as array) while exit_bool != 1 do
(
faceSel = #()
select o
setFaceSelection o faceSel
obj_tot_f = o.numfaces
--progressStart "progress"
for f = 1 to o.numfaces while exit_bool != 1 do
(
if keyboard.escpressed then exit_bool = 1
if meshop.getFaceArea o #{f} == 0.0 then
(
--df_count += 1
df_total += 1
append faceSel f
)
--if (progressUpdate(100.0*f/o.numfaces)) == false then exit_bool = 1
if lp_count == lp_thresh then
(
lp_tdelta = timestamp() - lp_tlast
lp_tlast = timestamp()
lp_fdelta = processed_f - lp_flast
lp_flast = processed_f
clearlistener()
eta1 = (lp_tdelta ) * (total_f - processed_f) / (lp_thresh * 1000) --seconds
fps_o = (1000.0*processed_f/(lp_tlast - st))
fps_l = (1000.0*lp_fdelta/lp_tdelta)
format "
"
format "Obj Total F: [ % ] Name: [ % ]
" (formattedPrint obj_tot_f format:"8.0u") o.name
format "
"
format "F Sel buffr: [ % ] Last loop: [ % ] FPS loop: [ % ] FPS overall: [ % ]
" (formattedPrint faceSel.count format:"8.0u") (formattedPrint lp_tdelta format:"6.0u") (formattedPrint fps_l format:"10.0f") (formattedPrint fps_o format:"10.0f")
format "
"
format " [ % ] [ % ] / [ % ] Removed: [ % ] Percent: [ % ]
" (formattedPrint (100.0*processed_f/total_f) format:"6.2f") (formattedPrint processed_f format:"8.0u") (formattedPrint total_f format:"8.0u") (formattedPrint df_total format:"8.0u") (formattedPrint (100.0*df_total/processed_f) format:"6.2f")
format "
"
format "ETA 1: % secs / % mins Elapsed: % secs / % mins
" (formattedPrint eta1 format:"7.0f") (formattedPrint (eta1/60) format:"7.2f") (formattedPrint ((lp_tlast - st)/1000) format:"7.0u") (formattedPrint (1.0*(lp_tlast - st)/60000) format:"7.2f")
lp_count = 1
)
else lp_count += 1
processed_f += 1
)
--progressEnd()
setFaceSelection o faceSel --set the face selection in the EMesh
max modify mode --go to modify mode
select o --select the mesh
subObjectLevel = 3 --go to Face SO level
modPanel.addModToSelection (deleteMesh())
maxOps.CollapseNode o true
subObjectLevel = 0
)
lp_tlast = timestamp()
fps_o = (1000.0*processed_f/(lp_tlast - st))
format "
"
format "----------------------------------------------------------------------------------------------
"
format " [ % ] [ % ] / [ % ] Removed: [ % ] Percent: [ % ]
" (formattedPrint (100.0*processed_f/total_f) format:"6.2f") (formattedPrint processed_f format:"8.0u") (formattedPrint total_f format:"8.0u") (formattedPrint df_total format:"8.0u") (formattedPrint (100.0*df_total/processed_f) format:"6.2f")
format "Elapsed: % secs / % mins FPS: [ % ]
" (formattedPrint ((lp_tlast - st)/1000) format:"7.0u") (formattedPrint ((1.0*lp_tlast - st)/60000) format:"7.2f") (formattedPrint fps_o format:"10.0f")
clearSelection()
undo on
enableSceneRedraw()
)
)
createDialog Myroll width:300 height:200
Hey, dunno what you were trying to do with all that C#, but I’ve tweaked some stuff in your script and it seems to be working (updating in realtime in the listener).
Let me know if this works out for you.
(
global myRoll
try(destroydialog myRoll) catch()
total_f = 0
processed_f = 0
lp_count = 0
lp_thresh = 5000
df_count = 0
df_thresh = 5000
df_total = 0
lp_fdelta = 0
lp_flast = 0
for o in (selection as array) do total_f += o.numfaces
--format "%
" total_f as string
format "Total faces selected: %
" (formattedPrint total_f format:"8.0u")
rollout myRoll "Del 0 area faces"
(
button bt_start "Start" width:100
on bt_start pressed do
(
st = lp_tlast = lp_tdelta = timestamp()
with redraw off with undo off (
exit_bool = 0
_user32.RedrawAllWindow (windows.getchildhwnd 0 myRoll.title)[1]
for o in (selection as array) while exit_bool != 1 do
(
faceSel = #()
select o
setFaceSelection o faceSel
obj_tot_f = o.numfaces
--progressStart "progress"
for f = 1 to o.numfaces while exit_bool != 1 do
(
if keyboard.escpressed then exit_bool = 1
if meshop.getFaceArea o #{f} == 0.0 then
(
--df_count += 1
df_total += 1
append faceSel f
)
--if (progressUpdate(100.0*f/o.numfaces)) == false then exit_bool = 1
if lp_count == lp_thresh then
(
lp_tdelta = timestamp() - lp_tlast
lp_tlast = timestamp()
lp_fdelta = processed_f - lp_flast
lp_flast = processed_f
clearlistener()
eta1 = (lp_tdelta ) * (total_f - processed_f) / (lp_thresh * 1000) --seconds
fps_o = (1000.0*processed_f/(lp_tlast - st))
fps_l = (1000.0*lp_fdelta/lp_tdelta)
format "
"
format "Obj Total F: [ % ] Name: [ % ]
" (formattedPrint obj_tot_f format:"8.0u") o.name
format "
"
format "F Sel buffr: [ % ] Last loop: [ % ] FPS loop: [ % ] FPS overall: [ % ]
" (formattedPrint faceSel.count format:"8.0u") (formattedPrint lp_tdelta format:"6.0u") (formattedPrint fps_l format:"10.0f") (formattedPrint fps_o format:"10.0f")
format "
"
format " [ % ] [ % ] / [ % ] Removed: [ % ] Percent: [ % ]
" (formattedPrint (100.0*processed_f/total_f) format:"6.2f") (formattedPrint processed_f format:"8.0u") (formattedPrint total_f format:"8.0u") (formattedPrint df_total format:"8.0u") (formattedPrint (100.0*df_total/processed_f) format:"6.2f")
format "
"
format "ETA 1: % secs / % mins Elapsed: % secs / % mins
" (formattedPrint eta1 format:"7.0f") (formattedPrint (eta1/60) format:"7.2f") (formattedPrint ((lp_tlast - st)/1000) format:"7.0u") (formattedPrint (1.0*(lp_tlast - st)/60000) format:"7.2f")
lp_count = 1
)
else lp_count += 1
processed_f += 1
)
--progressEnd()
setFaceSelection o faceSel --set the face selection in the EMesh
max modify mode --go to modify mode
select o --select the mesh
subObjectLevel = 3 --go to Face SO level
modPanel.addModToSelection (deleteMesh())
maxOps.CollapseNode o true
subObjectLevel = 0
)
lp_tlast = timestamp()
fps_o = (1000.0*processed_f/(lp_tlast - st))
format "
"
format "----------------------------------------------------------------------------------------------
"
format " [ % ] [ % ] / [ % ] Removed: [ % ] Percent: [ % ]
" (formattedPrint (100.0*processed_f/total_f) format:"6.2f") (formattedPrint processed_f format:"8.0u") (formattedPrint total_f format:"8.0u") (formattedPrint df_total format:"8.0u") (formattedPrint (100.0*df_total/processed_f) format:"6.2f")
format "Elapsed: % secs / % mins FPS: [ % ]
" (formattedPrint ((lp_tlast - st)/1000) format:"7.0u") (formattedPrint ((1.0*lp_tlast - st)/60000) format:"7.2f") (formattedPrint fps_o format:"10.0f")
clearSelection()
)
)
)
createDialog myRoll
)
hmm… an interesting story.
in you your code the only right function is CreateUser32Assembly, and only because this is my function.
but you care about ‘something wrong’ in a redraw. what does work ‘just fine’?
Kameleon, thank you, it’s working now.
I had to comment the _user32.RedrawAllWindow line, obviously…
denisT
I’ve been working with mxs for a week only, so I don’t have a very good understanding of it.
By working just fine I meant it was deleting what it was supposed to delete from the very beginning. And later, when I implemented the counters output they were also working – updating while inside a loop, that is.
What I did after that to break the updating is mystery to me…
Now that I see it’s working even without the User32 I wonder if I got it (User32) to work properly at all, or was it just me breaking and fixing other code that made the update (not/)work.
So this User32 business, if done properly, will make the actual rollout update while in a loop?
…Now, if u don’t mind, i’d like to ask you guys another Q.
Consider these two outputs of the script working.
The first one is a case of 180 objects, 1 145 327 faces in total. Processing time 102 secs.
----------------------------------------------------------------------------------------------
[ 100.00 ] [ 1145327 ] / [ 1145327 ] Removed: [ 661760 ] Percent: [ 57.78 ]
Elapsed: 102 secs / 1.70 mins FPS: [ 11201 ]
The second one is for a single object, 1 173 218 faces. In 100 secs only 42 169 faces were processed. Complete processing of this object took 80+ mins. Also mem usage was pretty high, almost 15GB.
----------------------------------------------------------------------------------------------
[ 3.59 ] [ 42169 ] / [ 1173218 ] Removed: [ 26660 ] Percent: [ 63.22 ]
Elapsed: 100 secs / 1.68 mins FPS: [ 418 ]
Is it the append messing it up?
What are more efficient alternatives?
Maybe something like this?
myObjects = for i in $Obj* where classof i == Box collect i
faceSel = for f in o.faces where meshop.getFaceArea o #{f} == 0.0 collect f
Kameleon
It works now, thank you. I had to comment the line with _user32.RedrawAllWindow, ofc.
I have another question though.
When I run this script on 180 objects, 1 100 000 faces in total it takes 100 secs.
When I run it on a single object, same number of faces, it takes 80+ mins.
Any ideas on what’s causing it?
I already tried collect instead of append but it doesn’t seem to make any difference.
denisT
As I said earlier, I’m only doing this for a week now, so my understanding isn’t that good.
But the script did work from the very beginning. It was deleting the faces. And when added the info output it updated while in a loop. But then I made smth that broke it.
here is a global mistake in your pipeline. if you would find any zero-area face why to you delete this face?
Here is a simple code to delete the 0 area faces that should run pretty fast.
Additionally you might want to weld the vertices of the faces you just deleted; otherwise you would have a hole there.
Although I dont know what you need, so perhaps you dont have to weld them.
(
st = timestamp(); sh = heapfree
_getFaceArea = meshop.getFaceArea
_deleteFaces = meshop.deleteFaces
for node in selection do
(
faces = #{}
for f = 1 to node.numfaces do
(
if (_getFaceArea node f) == 0 do append faces f
)
_deleteFaces node faces
)
format "time:% ram:%
" (timestamp()-st) (sh-heapfree)
)
If I had to guess, the obvious answer would be yes, they should be welded.
But it is by no means a restrictive condition and I am not in a position to assure it has to be that way, as I am not the OP.
I get your point; it is just that it has not been specified yet.
Here is a little modified version, which welds the vertices instead of deleting the faces.
Briefly tested, speed and memory usage are fine, no big difference.
Should require some more testing to be sure it is working well.
(
st = timestamp(); sh = heapfree
_getFaceArea = meshop.getFaceArea
_getVertsUsingFace = meshop.getVertsUsingFace
_weldVertsByThreshold = meshop.weldVertsByThreshold
for node in selection do
(
faces = #{}
for f = 1 to node.numfaces do
(
if (_getFaceArea node f) == 0 do append faces f
)
verts = _getVertsUsingFace node faces
_weldVertsByThreshold node verts 0.0001
)
format "time:% ram:%
" (timestamp()-st) (sh-heapfree)
)