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.
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?
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:
- Select all hard edges
- Divide edges (range 1-3)
- Chamfer all edges at once.
- 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
)
)