Notifications
Clear all

[Closed] UVW Seem with GW

it’s VERY smart!

good results… i’m using as a test object the all parts Teapot with 32 segments (32898 verts, 4096 open edges).

your code gives me:
time:175 memory:5705960L

my code (which is almost identical to yours but better optimized) gives:
time:111 memory:5046656L

I noticed display statistics (shortcut 7) plays a BIG role in performance in max 2014. I tested with a teapot with 64segs + TS (~1 million polys), as expected viewport speed goes to a crawl, but as soon as I turn display statistics on I get ~60fps!

The same in max 2012 doesn’t work, performance is very poor but better than max 2014 with no statistics.

Is there a way to make the gw lines not appear on the backside of geo?

Denis its surprising to see you pleased with results after you quickly shot down my post idea from day one. :applause:

4 Replies
(@denist)
Joined: 10 months ago

Posts: 0

i have this preview mode made for about 4 years. but of course i don’t use gw

(@miauu)
Joined: 10 months ago

Posts: 0

I made a script that uses gw, but the performance was…
My way to acheive this was to check if the edges are visible in the viewport and if they are not, then the redrawCallbacks fn did not draw gw lines for those edges.

(@polytools3d)
Joined: 10 months ago

Posts: 0

Also, did anyone succeed using gw.Polygon?
I cannot get it working in any Max version, not even the examples provided in the help.
If there is a way to get gw.Polygon working, then I think backface culling could work.

(@polytools3d)
Joined: 10 months ago

Posts: 0

Solved!
gw.polygon is brocken, but gw.triangle and gw.tristrip works well.

I am using a custom model, which has 6000 uv open edges, 5000 shared and 1000 mesh open edges. Then I just turbosmooth it to get an average of low and high polygons.

For that teapot, I get 80ms, which means using your optimizations I should get around 51ms.
I get 48ms just before entering the loops. Even if I completely remove the first loop, I get 54ms, which is still slower than your code, so I suspect the optimization should be before the loops, but I really can see where or how.

In the latest code, the lines “append foundEdges
” in the second loop shouldn’t be there, but taking them away don’t make any big difference in the teapot test.

2 Replies
(@denist)
Joined: 10 months ago

Posts: 0

could you attach the model? (max 2010-2012 please)

(@polytools3d)
Joined: 10 months ago

Posts: 0

Denis,

I can’t share the models I am using because they are copyrighted and I am not the owner, althought I created them, but I have created a similar object for you to test.

It is obviously not the same as the one I am testing, but it has barely the same amount of uv edges and mesh open edges, so the results should be similar.

I test it as it is, the with 1, 2 and 3 turbosmooth iterations.

It’s an .obj, so others can open it too.

These are the results I got using the model I’ve uploaded.

Previous version

Base Model
Found 3920 UV Open Edges in 92ms
Used Memory 3048248L

TurboSmooth 1 iteration
Found 7840 UV Open Edges in 291ms
Used Memory 7275320L

TurboSmooth 2 iterations
Found 15680 UV Open Edges in 990ms
Used Memory 19341568L

Latest version

Base Model
Found 3920 UV Open Edges in 49ms
Used Memory 2769144L

TurboSmooth 1 iteration
Found 7840 UV Open Edges in 107ms
Used Memory 6082848L

TurboSmooth 2 iterations
Found 15680 UV Open Edges in 246ms
Used Memory 14535560L

2 Replies
(@denist)
Joined: 10 months ago

Posts: 0

what max version do you use?

(@polytools3d)
Joined: 10 months ago

Posts: 0

Max 2011 x64 Win7

Edit: Same results in Max 2012+

i have absolutelly different numbers for your code…
that’s what i actually use:


(
  
	  unRegisterRedrawViewsCallback cbDrawOpenEdges
	  
	  global RO_DISPLAY_UV_OE
	  global cbDrawOpenEdges
	  global cbSelectionChanged
	  
	  local vertexPos   = #()
	  local uvChannel   = 1
	  local edgesColor  = [0,255,0]
	  local edgeOffset  = 0.03
	  local forceRedraw = false
	  local polyLine	= gw.polyLine
	  
	  fn cbDrawOpenEdges = (
		  
		  gw.setTransform (Matrix3 1)
		  gw.setColor #line edgesColor
		  
		  for j in vertexPos do polyLine j true
  
		  -- Needed in some Max versions or used dirvers
		  if forceRedraw do (
			  gw.enlargeUpdateRect #whole
			  gw.updateScreen()
		  )
	  )
  
	  fn cbSelectionChanged mForce:false = (
  
		  unRegisterRedrawViewsCallback cbDrawOpenEdges
		  
		  if ($ != undefined) do (
			  
			  setwaitcursor()
  
			  t1 = timeStamp()
			m1 = heapfree
				  
			  cGetMapFace = meshop.getMapFace
  
			  obj = snapshotasmesh selection[1]
  
			  allChannels = for j = 1 to meshop.getNumMaps obj where (meshop.getMapSupport obj j) collect j
			  
			  RO_DISPLAY_UV_OE.ddl_channel.items = for j in allChannels collect j as string
			  
			  if (mForce == false) do (
				  uvChannel = allChannels[1]
				  RO_DISPLAY_UV_OE.ddl_channel.selection = 1
			  )
  
			  numTFaces = meshop.getNumMapFaces obj uvChannel
			  numTVerts = meshop.getNumMapVerts obj uvChannel
			  
			  emesh = trimesh()
			  setMesh emesh numverts:numTVerts numfaces:numTFaces
			  setMesh emesh faces:(for j = 1 to numTFaces collect (cGetMapFace obj uvChannel j))
			  
			  objOpenEdges  = meshop.getOpenEdges obj
			  meshOpenEdges = meshop.getOpenEdges emesh
			  delete emesh
						  
			  sharedFaces = meshop.getFacesUsingEdge obj meshOpenEdges
			  foundEdges = #()
			  vertexPos  = #()
			  
			  for j in sharedFaces do (
				  
				  objFaceVerts = getFace obj j
				  
				  edge1 = j*3 - 2
				  edge2 = j*3 - 1
				  edge3 = j*3
				  
				  v1Idx = objFaceVerts.x
				  v2Idx = objFaceVerts.y
				  v3Idx = objFaceVerts.z
				  
				  v1 = getVert obj v1Idx
				  v2 = getVert obj v2Idx
				  v3 = getVert obj v3Idx
  
				  if meshOpenEdges[edge1] do (
					  found = findItem foundEdges [v1Idx, v2Idx]
					  if (found == 0) then (
						  append vertexPos #(v1,v2)
						  append foundEdges [v2Idx, v1Idx]
					  )else(
						  deleteitem foundEdges found
					  )
				  )
				  if meshOpenEdges[edge2] do (
					  found = findItem foundEdges [v2Idx, v3Idx]
					  if (found == 0) then (
						  append vertexPos #(v2,v3)
						  append foundEdges [v3Idx, v2Idx]
					  )else(
						  deleteitem foundEdges found
					  )
				  )
				  if meshOpenEdges[edge3] do (
					  found = findItem foundEdges [v3Idx, v1Idx]
					  if (found == 0) then (
						  append vertexPos #(v3,v1)
						  append foundEdges [v1Idx, v3Idx]
					  )else(
						  deleteitem foundEdges found
					  )
				  )
					  
			  )
	
			  format "mesh >> open edges:% time:% memory:%
" vertexPos.count (timestamp() - t1) (m1 - heapfree) 
  
			  registerRedrawViewsCallback cbDrawOpenEdges
  
			  delete obj
			  
			  gc light:true
			  
			  setArrowCursor()
			  
		  )
		  
		  forceCompleteRedraw()
		  
	  )
  
	  
	  try(destroyDialog RO_DISPLAY_UV_OE) catch()
	  rollout RO_DISPLAY_UV_OE "UV Open Edges" width:160 height:198
	  (
		  checkbutton bt_enable "Display UV Open Edges" pos:[8,8] width:144 height:32
		  dropdownList ddl_channel "UV Channel:" pos:[8,72] width:120 height:40 enabled:false
		  colorPicker cp1 "" pos:[131,90] width:21 height:21 enabled:true color:edgesColor modal:false
		  checkbox chk_redraw "Force Redraw" pos:[8,46] width:100 height:16 enabled:false
		  spinner spn_width "Edge Width:" pos:[8,120] width:120 height:16 range:[1,100,4] type:#integer fieldwidth:50
		  button bt_update "Update" pos:[8,160] width:144 height:28 enabled:false
  
		  fn destroy = (
			  callbacks.removeScripts #selectionSetChanged
			  unRegisterRedrawViewsCallback cbDrawOpenEdges
			  forceCompleteRedraw()
		  )
		  
		  on RO_DISPLAY_UV_OE close do destroy()
		  
		  on bt_enable changed arg do
		  (
			  bt_update.enabled = arg
			  ddl_channel.enabled = arg
			  chk_redraw.enabled = arg
			  destroy()
			  
			  if (arg == true) do (
				  callbacks.addscript #selectionSetChanged "cbSelectionChanged()"
				  cbSelectionChanged()
			  )
		  )
		  
		  on bt_update pressed do cbSelectionChanged()
		  
		  on ddl_channel selected arg do (
			  uvChannel = (ddl_channel.selected as integer)
			  cbSelectionChanged mForce:true
		  )
		  
		  on cp1 changed arg do edgesColor = arg
			  
		  on spn_width changed arg do edgeOffset = (arg-1)/100.0
		  
		  on chk_redraw changed arg do forceRedraw = arg
  
	  )
  
	  createDialog RO_DISPLAY_UV_OE
	  
  )

for your sample object i have:

with no turbosmooth it’s
mesh >> open edges:3920 time:165 memory:1275784L

with 1 turbosmooth iteration it’s
mesh >> open edges:7840 time:600 memory:3171480L

i’ve tested in with max 2012/64

 With your code I get these results:
  
  [b]Base Model[/b]
  mesh >> open edges:3920 time:69 memory:1291032L
  
  [b]Turbosmooth 1 iteration[/b]
  mesh >> open edges:7840 time:243 memory:3211120L
  
  [b]Turbosmooth 2 iterations[/b]
  mesh >> open edges:15680 time:878 memory:8814776L

With my latest code I get these:

Base Model
mesh >> open edges:3920 time:50 memory:2754200L

Turbosmooth 1 iteration
mesh >> open edges:7840 time:108 memory:6075416L

Turbosmooth 2 iterations
mesh >> open edges:15680 time:245 memory:14534304L

From these results yours uses about half the memory and mine runs about 2.5 times faster.

ok. here is my code:


 try(unregisterRedrawViewsCallback showOpenMapEdgesDialog.drawEdges; completeredraw()) catch() 
try(destroydialog showOpenMapEdgesDialog) catch()

rollout showOpenMapEdgesDialog "Open Map Edges" width:200
(
	fn getOpenMapEdges node channel:1 debug:on = if iskindof node GeometryClass and canconvertto node editable_mesh do
	(
		t1 = timestamp()
		m1 = heapfree
		local mesh = snapshotasmesh node
		local edges = #()

		if meshop.getmapsupport mesh channel do
		(
			numtverts = meshop.getnummapverts mesh channel
			getmapface = meshop.getmapface
			
			tfaces = for f=1 to mesh.numfaces collect (getmapface mesh channel f)
			
			local emesh = TriMesh()
			setmesh emesh numverts:numtverts numfaces:mesh.numfaces 
			setmesh emesh faces:tfaces

			seamed = meshop.getopenedges emesh 
			opened = meshop.getopenedges mesh * seamed
			faces = meshop.getfacesusingedge mesh seamed 
				
			for f in faces do
			(
				vv = getface mesh f
				e = f*3 - 3

				if seamed[e += 1] and (vv[1] < vv[2] or opened[e]) do append edges #(getvert mesh vv.x, getvert mesh vv.y)
				if seamed[e += 1] and (vv[2] < vv[3] or opened[e]) do append edges #(getvert mesh vv.y, getvert mesh vv.z)
				if seamed[e += 1] and (vv[3] < vv[1] or opened[e]) do append edges #(getvert mesh vv.x, getvert mesh vv.z)
			)
			if debug do format "mesh >> open edges:% time:% memory:%
" edges.count (timestamp() - t1) (m1 - heapfree) 
			free mesh
			free emesh
		)
		edges
	)

	local edges
	fn drawEdges = if edges != undefined do
	(
		polyLine = gw.polyLine
		gw.setTransform (matrix3 1)
		gw.setColor #line green
		for e in edges do polyLine e off
		gw.enlargeUpdateRect #whole
		gw.updateScreen()
	)

	checkbutton draw_bt "Show" width:190
	on draw_bt changed state do
	(
		unregisterRedrawViewsCallback drawEdges 
		if state do if (edges = getOpenMapEdges selection[1] debug:on) != undefined do registerRedrawViewsCallback drawEdges 
		gc light:on delayed:on
		completeredraw()	
	)
)
createdialog showOpenMapEdgesDialog
 

what numbers does it make for your sample on your machine?

1 Reply
(@polytools3d)
Joined: 10 months ago

Posts: 0

This approach runs faster and uses less memory than mine.

Base Model
mesh >> open edges:3920 time:20 memory:1137208L

Turbosmooth 1 iteration
mesh >> open edges:7840 time:51 memory:2799352L

Turbosmooth 2 iterations
mesh >> open edges:15680 time:137 memory:7984208L

If I remove the Edge Width from my code, yours still runs faster and uses a bit less memory

These are the numbers I get removing the Edge Width feature

Base Model
mesh >> open edges:3920 time:32 memory:1267368L

Turbosmooth 1 iteration
mesh >> open edges:7840 time:74 memory:3061984L

Turbosmooth 2 iterations
mesh >> open edges:15680 time:182 memory:8510272L

Page 2 / 3