Notifications
Clear all

[Closed] How to optimize this code

It would certainly speed up the whole process.

This would be a continuation of optimization.
First, to select only the hard edges>>>

	fn edgeFacesAngle dir1 dir2 = (acos (dot (normalize dir2) (normalize dir1)))
 	fn findHardEdges obj minAngle maxAngle =
 	(
 		edgelist = #{}
 		getedgefaces = polyOp.getEdgeFaces
 		facenormal = polyop.getFaceNormal
 		setedgesel = polyOp.setEdgeSelection
 		getnumedges = polyop.getNumEdges obj
 		for edge in 1 to getnumedges where (getedgefaces obj edge).count == 2 do
 		(
 			facesArr = (getedgefaces obj edge)
 			dir1 = (facenormal obj facesArr[1])
 			dir2 = (facenormal obj facesArr[2])
 			theAngle = edgeFacesAngle dir1 dir2
 			if theAngle >= minAngle and theAngle <= maxAngle do append edgelist edge
 		) ; edgelist
 		if edgelist.numberSet != 0 do
 		(
 			setedgesel obj edgelist
 			if getCommandPanelTaskMode() != #modify do (max modify mode)
 			modPanel.setCurrentObject obj	; subobjectLevel = 2
 		)
 	)
 	if selection.count == 1 and classof selection[1].baseobject == Editable_Poly do
 	(
 		findHardEdges selection[1].baseobject 40 120 --angle range minimun 40, maximum 120
 	)

and then the main function>>>

(
 	  fn wrinkleEdges obj edges: chamferAmount:1 connectSeg:2 rand:[0.1,0.1,0.1] seedValue: subD:on = if iskindof obj editable_poly do
 	  (
 		  if edges == unsupplied then edges = obj.selectededges as bitarray else edges = edges as bitarray
 		  if edges.numberSet > 0 do
 		  (
 			  if seedValue != unsupplied do seed seedValue
 			   chamferedges = polyOp.chamferEdges
 			  connectedges = obj.ConnectEdges
 			  getedgeverts = polyOp.getEdgeVerts 
 			  movevert = polyOp.moveVert 
 ------------------------------------------------------------------------- [b]NEW #1[/b]
 			fn calcEdgeLength obj idx =
 			(
 				getvertpos = polyOp.getVert
 				v1Pos = getvertpos obj (polyOp.getEdgeVerts obj idx)[1]
 				v2Pos = getvertpos obj (polyOp.getEdgeVerts obj idx)[2]
 				length (v2Pos - v1Pos)
 			)		
 			maxEdgesLength = amax (for edge in edges collect (calcEdgeLength obj edge))
 			s = connectSeg
 ------------------------------------------------------------------------- [b]END NEW #1[/b][b]	[/b]	
 			  for edge in edges do
 			  (
 ------------------------------------------------------------------------- [b]NEW #2[/b]	  
 				edgeLength = calcEdgeLength obj edge
 				connectSeg = case of ( --"connectSeg" value in range 1-5  
 					(s == 1): ( if edgeLength <= maxEdgesLength/2 then 0 else 1)
 					(s == 2): (
 						if (edgeLength > maxEdgesLength/3) and (edgeLength <= 2*maxEdgesLength/3) then 1
 						else if (edgeLength > 2*maxEdgesLength/3) then 2 else 0
 					)
 					(s == 3): (
 						if (edgeLength > maxEdgesLength/4) and (edgeLength <= maxEdgesLength/2) then 1
 						else if (edgeLength > maxEdgesLength/2) and (edgeLength <= 3*maxEdgesLength/4) then 2
 						else if (edgeLength > 3*maxEdgesLength/4) then 3 else 0
 					)
 					(s == 4): (
 						if (edgeLength > maxEdgesLength/5) and (edgeLength <= 2*maxEdgesLength/5) then 1
 						else if (edgeLength > 2*maxEdgesLength/5) and (edgeLength <= 3*maxEdgesLength/5) then 2
 						else if (edgeLength > 3*maxEdgesLength/5) and (edgeLength <= 4*maxEdgesLength/5) then 3
 						else if (edgeLength > 4*maxEdgesLength/5) then 4 else 0
 					)
 					(s == 5): (
 						if (edgeLength > maxEdgesLength/6) and (edgeLength <= maxEdgesLength/3) then 1
 						else if (edgeLength > maxEdgesLength/3) and (edgeLength <= maxEdgesLength/2) then 2
 						else if (edgeLength > maxEdgesLength/2) and (edgeLength <= 2*maxEdgesLength/3) then 3
 						else if (edgeLength > 2*maxEdgesLength/3) and (edgeLength <= 5*maxEdgesLength/6) then 4
 						else if (edgeLength > 5*maxEdgesLength/6) then 5 else 0
 					)		
 				)
 ------------------------------------------------------------------------- [b]END NEW #2[/b]
 				
 				  obj.selectededges = #{edge} -- set selection for each edge separately
 				  chamferedges obj edge chamferAmount -- chamfer edge with given a value
 ------------------------------------------------------------------------- [b]NEW #3[/b] 				
 				if connectSeg != 0 do 
 				(
 					obj.connectEdgeSegments = connectSeg --adjust segments
 					connectedges() -- connect edges
 				)
 ------------------------------------------------------------------------- [b]END NEW #3[/b]	  
 				
 				  for e in obj.selectededges as bitarray do
 				  (
 					  vv = getedgeverts obj e -- collect edge vertex
 					  movevert obj vv #(random -rand rand, random -rand rand) --set position for first vert
 				  )
 			  )
 			  faces = obj.faces as bitarray -- collect all faces
 			  polyop.retriangulate obj faces -- retriangulate faces
 			  polyop.setFaceSmoothGroup obj faces 0 -- clear SmoothGroup
 			  if (obj.surfSubdivide = subD) do obj.iterations = 2
 		  )
 	  )
 
 	  undo "WrinkledEdges" on 
 	  (
 		  if (mode = getCommandPanelTaskMode()) != #create do setCommandPanelTaskMode mode:#create
 		  t1 = timestamp()
 		  m1 = heapfree
 		  wrinkleEdges selection[1] seed:0
 		  format "time:% memory:%
" (timestamp() - t1) (m1 - heapfree)
 		  if (getCommandPanelTaskMode()) != mode do setCommandPanelTaskMode mode:mode
 	  )
 )

Testing object

test on my PC
older code
time:1634 memory:-574216L
this code
time:1257 memory:-260936L

what is the main idea of the tool? does it have to bevel and smooth hard edges?

This tool need to chew up the edges of Editable Poly objects like wooden or concrete pillars or walls.

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

ok. i’ve got the point. but i see the regular pattern of distorsion

(@denist)
Joined: 11 months ago

Posts: 0

ok. i’ve got the point. but i see the regular pattern of edge distortion. it looks too artificial.

Denis could you tell me something about seed value that you place in this code.
I plan to add spinner control fot the SEED. What kind of value i should use: 012345 or just single digit?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

it might be any digit. help says that seed value has to be a number… but as i know it uses only a bit combination. it a good thing to have exactly same values for random. using the same seed is much easier to debug (tweak) the code.

could you attach this mesh to the post to give me a sample to play with?

originally posted by DenisT
but i see the regular pattern of distorsion

It bothers me to. How could I fix it. Do you have an idea?
I tried to manage attachments but it always shows me an error.
Look here
http://www.mediafire.com/?dd5up7qmeub6dr6

And this is done manually with modifiers.
http://www.mediafire.com/?i6ocx9nwbr55ppf

I accelerated the whole process (almost 3 time faster solution) with this new approach.


   (
   	  fn wrinkleEdges obj edges: chamferAmount:0.5 divides:2 rand:[0.5,0.3,0.5] seedValue: subD:on = if iskindof obj editable_poly do
   	  (
   		  if edges == unsupplied then edges = obj.selectededges as bitarray else edges = edges as bitarray
   		  if edges.numberSet > 0 do
   		  (
   			  if seedValue != unsupplied do seed seedValue
   			   chamferedges = polyOp.chamferEdges
   			  getedgeverts = polyOp.getEdgeVerts 
   			  movevert = polyOp.moveVert 
   			divideedge = polyOp.divideEdge
   			getnumedges = polyOp.getNumEdges
   
   			fn calcEdgeLength obj idx =
   			(
   				getvertpos = polyOp.getVert
   				v1Pos = getvertpos obj (polyOp.getEdgeVerts obj idx)[1]
   				v2Pos = getvertpos obj (polyOp.getEdgeVerts obj idx)[2]
   				length (v2Pos - v1Pos)
   			)		
   			maxEdgesLength = amax (for edge in edges collect (calcEdgeLength obj edge))
   			  for edge in edges do
   			  (
   				edgeLength = calcEdgeLength obj edge
   				case divides of ( --"divides" value in range 1-3
   					(1): (if edgeLength > maxEdgesLength/2 do divideedge obj edge 0.5)
   					(2): (
   						if (edgeLength > maxEdgesLength/3) and (edgeLength <= 2*maxEdgesLength/3) then divideedge obj edge 0.5
   						else if (edgeLength > 2*maxEdgesLength/3) do
   						(
   							divideedge obj edge 0.3333
   							divideedge obj (getnumedges obj) 0.5
   						)
   					)
   					(3): (
   						if (edgeLength > maxEdgesLength/4) and (edgeLength <= maxEdgesLength/2) then divideedge obj edge 0.5
   						else if (edgeLength > maxEdgesLength/2) and (edgeLength <= 3*maxEdgesLength/4) then 
   						(
   							divideedge obj edge 0.3333
   							divideedge obj (getnumedges obj) 0.5							
   						)
   						else if (edgeLength > 3*maxEdgesLength/4) do
   						(
   							divideedge obj edge 0.5
   							divideedge obj (getnumedges obj) 0.5
   							divideedge obj edge 0.5						
   						)
   					)
   				)
   			)	
   			  chamferedges obj obj.selectededges chamferAmount -- chamfer edge with given a value
   			for e in obj.selectededges as bitarray do
   			(
   				edgeverts = getedgeverts obj e -- collect edge vertex
   				movevert obj edgeverts #(random -rand rand, random -rand rand) --set position for first vert
   			)
   			  faces = obj.faces as bitarray -- collect all faces
   			  polyop.retriangulate obj faces -- retriangulate faces
   			  polyop.setFaceSmoothGroup obj faces 0 -- clear SmoothGroup
   			  if (obj.surfSubdivide = subD) do obj.iterations = 2
   		  )
   	  )
   
   	  undo "WrinkledEdges" on 
   	  (
   		  if (mode = getCommandPanelTaskMode()) != #create do setCommandPanelTaskMode mode:#create
   		  t1 = timestamp()
   		  m1 = heapfree
   		  wrinkleEdges selection[1] seed:0
   		  format "time:% memory:%
" (timestamp() - t1) (m1 - heapfree)
   		  if (getCommandPanelTaskMode()) != mode do setCommandPanelTaskMode mode:mode
   	  )
   )

The execution process:

  1. Select all hard edges
  2. Divide edges (range 1-3)
  3. Chamfer all edges at once.
  4. Randomize selected verts position (one by one):
    “Pattern of distorsion” problem (FIXED)

    This is result
    older code
    time:1441 memory:25360L
    this code
    time:582 memory:-10128L
    The only thing that I don’t like in the code is the limit of Divide Edges Value (max 3)
    Denis, i’ll wait to see what you are prepared.
    Probably ten times faster version.
    Cheers!

i couldn’t make it faster but my optimized version takes 10 times less memory:


(
	fn wrinkleEdges obj edges: chamferAmount:0.5 divides:2 rand:[0.5,0.3,0.5] seedValue: subD:on = if iskindof obj editable_poly do
	(
		if edges == unsupplied then edges = obj.selectededges as bitarray else edges = edges as bitarray
		if edges.numberSet > 0 do
		(
			if seedValue != unsupplied do seed seedValue
			
			chamferedges = polyOp.chamferEdges
			getedgeverts = polyOp.getEdgeVerts 
			movevert = polyOp.moveVert 
			   divideedge = polyOp.divideEdge
			   getnumedges = polyOp.getNumEdges
			getvertpos = polyOp.getVert
   
			edgeLenghts = for edge in edges collect
			(
				vv = getedgeverts obj edge
				distance (getvertpos obj vv[1]) (getvertpos obj vv[2])
			)
			maxEdgesLength = amax edgeLenghts
			
			id = 0
			for edge in edges do
			(
				   p = edgeLenghts[id += 1]/maxEdgesLength
				
				case divides of 
				( 
					   (1): if  p > 0.5 do divideedge obj edge 0.5
					   (2): 
					(
						   if (p > 0.6666) then
						   (
							   divideedge obj edge 0.6666
							   divideedge obj edge 0.5
						   )
						else if (p > 0.3333) do divideedge obj edge 0.5
					   )
					   (3): 
					(
						   if (p > 0.75) then
						   (
							   divideedge obj edge 0.75
							   divideedge obj edge 0.6666
							   divideedge obj edge 0.5						
						   )
						else if (p > 0.5) then 
						   (
							   divideedge obj edge 0.6666
							   divideedge obj edge 0.5							
						   )
						else if (p > 0.25) do divideedge obj edge 0.5
					   )
				   )
			   )	
			
			chamferedges obj obj.selectededges chamferAmount -- chamfer edge with given a value
			verts = polyop.getvertsusingedge obj obj.selectededges
			   for v in verts do movevert obj v (random -rand rand)
			
			polyop.retriangulate obj obj.faces -- retriangulate faces
			polyop.setFaceSmoothGroup obj obj.faces 0 -- clear SmoothGroup
			if (obj.surfSubdivide = subD) do obj.iterations = 2
		)
	)
   
	undo "WrinkledEdges" on 
	(
		if (mode = getCommandPanelTaskMode()) != #create do setCommandPanelTaskMode mode:#create
		t1 = timestamp()
		m1 = heapfree
		wrinkleEdges selection[1] seed:0
		format "time:% memory:%
" (timestamp() - t1) (m1 - heapfree)
		if (getCommandPanelTaskMode()) != mode do setCommandPanelTaskMode mode:mode
	)
)


Page 2 / 8