[Closed] BaoAutoChamfer a script to smooth edges using threshold angle
I want give you a script I have done to smooth (chamfer) edges in a Poly Object. The
edges are selected using a Threshold angle. You can manually add or deselect edges
before chamfer them too.
Copy the code to a text file and rename it to BaoAutoChamfer.ms and then follow
the Installation and Usage that are explained in the comment header of the code.
[b]Updated: Version 1.1
[color=DarkOrange]Note: The object stack must be collapsed. This script don’t works well or fails
(script error messages) if there are modifiers in stack.
[/color][/b]
/*
BaoAutoChamfer 1.1:
Autodetects edges with a threshold angle between face normals and chamfers them,
welding vertices if necessary.
Installation:
Place it in Max/scripts/startup
Usage:
In Utilities panel open MaxScript and open the dropdown list and select BaoAutoChamfer
and now scroll down the utilities panel because BaoAutoChamfer is opened down.
Important: The object stack must be collapsed. BaoAutoChamfer runs badly if there
are modifiers above the Editable Poly Object.
Angle threshold: An edge have two faces. The faces have normals. The angle between the
two normals is compared for each edge with this angle threshold.
If normals angle >= angle threshold, then chamfer the edge.
Chamfer amount: Amount for the first chamfer iteration
Chamfer iterations: Number of chamfers to do.
Select an object and press Detect & Chamfer Edges button. Or press Detect Edges, now
you can change the edge selection adding or deselecting edges, and then press the
Chamfer them button.
Revisions:
1.1 - Better detection of edges to chamfer. Now edges created in first iteration that have
faces planar (zero degrees between its face normals) are not included in next iteration
- Less code using function calls
TO DO: Iterations > 3
I have observed with iterations > 3 I have overlaping faces because no welded
vertices, so I decided limit the iterations to 3 by now.
*/
fn fnDetectEdges anglethreshold=
( polyOp.CollapseDeadStructs $
facesDuplo=#()
edgesSel=#()
numedges=polyOp.getNumEdges $
for i=1 to numedges do
( facesDuplo=polyOp.getEdgeFaces $ i
if(facesDuplo.count==2) do
( facenormal1=polyOp.getFaceNormal $ facesDuplo[1]
facenormal2=polyOp.getFaceNormal $ facesDuplo[2]
normalsangle=acos(dot (normalize facenormal1) (normalize facenormal2))
if(normalsangle>=anglethreshold) do append edgesSel i
) )
polyOp.setEdgeSelection $ edgesSel
)
fn fnChamferThem edgesSel amount iterations smooth=
( $.edgeChamfer = amount
for i=1 to iterations do
( if(i==2) do $.edgeChamfer /= 2.75
if(i==3) do $.edgeChamfer /= 2.1
-- TO DO: iterations > 3 (change also range in spinner baciterations below)
--if(i==4) do $.edgeChamfer /= 1.45
--if(i==5) do $.edgeChamfer /= 0.85
numedges=polyOp.getNumEdges $
$.EditablePoly.buttonOp #Chamfer
--append the new edges created by chamfer to edges selection array
numnewedges=polyOp.getNumEdges $
for j=(numedges+1) to numnewedges do
( facesDuplo=polyOp.getEdgeFaces $ j
if(facesDuplo.count==2) do
( facenormal1=polyOp.getFaceNormal $ facesDuplo[1]
facenormal2=polyOp.getFaceNormal $ facesDuplo[2]
normalsangle=acos(dot (normalize facenormal1) (normalize facenormal2))
if(normalsangle>=1) do append edgesSel j
) )
polyOp.setEdgeSelection $ edgesSel
--select vertices from edgeselection and weld vertices in threshold=edgeChamfer
$.EditablePoly.ConvertSelection #Edge #Vertex
vertsSel=polyOp.getVertSelection $
$.weldThreshold = $.edgeChamfer*0.7
polyOp.weldVertsByThreshold $ vertsSel
--deletes dead edges and load again the edgesSel array with the new selection
polyOp.CollapseDeadStructs $
edgesSel=polyOp.getEdgeSelection $
)--for
if(smooth==true) do
( subobjectlevel=4
polyOp.setFaceSelection $ #all
$.EditablePoly.buttonOp #Autosmooth
polyOp.setFaceSelection $ #none
subobjectlevel=0
)
max utility mode
)
fn fnMessageError error:0 =
( if(error==1) then messagebox "Press Detect Edges first (then change selection if you want) and after Press this button."
else
( if(selection.count != 1) then
( if(selection.count == 0) then messagebox "Select 1 object before!"
else messagebox "Select only 1 object, please."
)
else if(classOf $.baseObject != editable_poly) do messagebox "This script works on Poly Objects only."
)
)
utility BaoAutoChamfer "BaoAutoChamfer 1.1"
( local bacpressedfirstbut
label baclabel1 "Jose Manuel Baleato Bao, 2005"
group ""
( spinner bacangle "Threshold Angle:" fieldwidth:50 align:#left range:[0,359,30]
spinner bacamount "Amount:" fieldwidth:50 align:#left range:[0,10000,0] scale:0.001
spinner baciterations "Iterations:" fieldwidth:30 align:#left range:[1,3,2] type:#integer
checkbox bacsmooth "Auto Smooth" checked:true
)
group "Automatic"
( button bacbutautomat "Detect & Chamfer"
)
group "Manual (you can change Sel.)"
( button bacbutdetect "Detect Edges"
button bacbutchamfer "Chamfer them"
)
on BaoAutoChamfer open do
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) do
( bacamount.value=0.7 --bacamount.value=$.edgeChamfer -- TO DO: Fix this
bacpressedfirstbut=false
) )
on bacbutdetect pressed do
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) then
( fnDetectEdges(bacangle.value)
max modify mode
subobjectlevel= 2
bacpressedfirstbut=true
)
else fnMessageError()
)
on bacbutchamfer pressed do
( if(bacpressedfirstbut==false) then fnMessageError error:1
else
( undo "BaoAutoChamfer Manual" on
( max modify mode
subobjectlevel= 2
edgesSel=polyOp.getEdgeSelection $
if(edgesSel.count>0) do fnChamferThem edgesSel bacamount.value baciterations.value bacsmooth.checked
bacpressedfirstbut=false
) )
)
on bacbutautomat pressed do
( undo "BaoAutoChamfer Automatic" on
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) then
( fnDetectEdges(bacangle.value)
edgesSel=polyOp.getEdgeSelection $
if(edgesSel.count>0) do
( max modify mode
subobjectlevel= 2
fnChamferThem edgesSel bacamount.value baciterations.value bacsmooth.checked
) )
else fnMessageError()
)
bacpressedfirstbut=false
)
) -- end of utility definition
Thanks. It is a very cool script I also like how you made a “Edge Detect” button that shows what edges is selected. I have not studied your script in detail yet, but noticed that the script seen to chamfer edges “individually” resulting in some extra edges in places where it is just a continious line of edges. Assuming p is the object in question with the selected eges then doing the following for example, chamfers the entire edge selection in one go:
p.EditablePoly.chamferEdges 3.0
p.EditablePoly.chamferEdges 1.0
I assume that the way you do it that due to the fact that you get better control on what happens in the corners etc.?
Lars
Hi Lars.
I have edited the first post and updated to 1.1 the script.
Now I think the extra vertices in long edges are no more created
so a cleaner mesh is obtained.
A work around for the stack having to be colapsed and losing your UV maps is to copy the object, colapse it, run the script and leave it to just select the edges, copy paste the uv maps onto the copy, then apply and edit poly, go to edge selection and you should have the correct edges already selected so can go ahead and bevel them, only downside you dont get as nice edges but helps overcome this fantastic scripts major downside
Cool script Bao, but you should perhaps put it in a floating dialog instead of the utility panel, it will make the interface a hell of a lot friendlier.
I changed it here, I changed the utility to a rollout and I killed all command panel switching.
fn fnDetectEdges anglethreshold=
( polyOp.CollapseDeadStructs $
facesDuplo=#()
edgesSel=#()
numedges=polyOp.getNumEdges $
for i=1 to numedges do
( facesDuplo=polyOp.getEdgeFaces $ i
if(facesDuplo.count==2) do
( facenormal1=polyOp.getFaceNormal $ facesDuplo[1]
facenormal2=polyOp.getFaceNormal $ facesDuplo[2]
normalsangle=acos(dot (normalize facenormal1) (normalize facenormal2))
if(normalsangle>=anglethreshold) do append edgesSel i
) )
polyOp.setEdgeSelection $ edgesSel
)
fn fnChamferThem edgesSel amount iterations smooth=
( $.edgeChamfer = amount
for i=1 to iterations do
( if(i==2) do $.edgeChamfer /= 2.75
if(i==3) do $.edgeChamfer /= 2.1
-- TO DO: iterations > 3 (change also range in spinner baciterations below)
--if(i==4) do $.edgeChamfer /= 1.45
--if(i==5) do $.edgeChamfer /= 0.85
numedges=polyOp.getNumEdges $
$.EditablePoly.buttonOp #Chamfer
--append the new edges created by chamfer to edges selection array
numnewedges=polyOp.getNumEdges $
for j=(numedges+1) to numnewedges do
( facesDuplo=polyOp.getEdgeFaces $ j
if(facesDuplo.count==2) do
( facenormal1=polyOp.getFaceNormal $ facesDuplo[1]
facenormal2=polyOp.getFaceNormal $ facesDuplo[2]
normalsangle=acos(dot (normalize facenormal1) (normalize facenormal2))
if(normalsangle>=1) do append edgesSel j
) )
polyOp.setEdgeSelection $ edgesSel
--select vertices from edgeselection and weld vertices in threshold=edgeChamfer
$.EditablePoly.ConvertSelection #Edge #Vertex
vertsSel=polyOp.getVertSelection $
$.weldThreshold = $.edgeChamfer*0.7
polyOp.weldVertsByThreshold $ vertsSel
--deletes dead edges and load again the edgesSel array with the new selection
polyOp.CollapseDeadStructs $
edgesSel=polyOp.getEdgeSelection $
)--for
if(smooth==true) do
( subobjectlevel=4
polyOp.setFaceSelection $ #all
$.EditablePoly.buttonOp #Autosmooth
polyOp.setFaceSelection $ #none
subobjectlevel=0
)
)
fn fnMessageError error:0 =
( if(error==1) then messagebox "Press Detect Edges first (then change selection if you want) and after Press this button."
else
( if(selection.count != 1) then
( if(selection.count == 0) then messagebox "Select 1 object before!"
else messagebox "Select only 1 object, please."
)
else if(classOf $.baseObject != editable_poly) do messagebox "This script works on Poly Objects only."
)
)
rollout BaoAutoChamfer "BaoAutoChamfer 1.1"
( local bacpressedfirstbut
label baclabel1 "Jose Manuel Baleato Bao, 2005"
group ""
( spinner bacangle "Threshold Angle:" fieldwidth:50 align:#left range:[0,359,30]
spinner bacamount "Amount:" fieldwidth:50 align:#left range:[0,10000,0] scale:0.001
spinner baciterations "Iterations:" fieldwidth:30 align:#left range:[1,3,2] type:#integer
checkbox bacsmooth "Auto Smooth" checked:true
)
group "Automatic"
( button bacbutautomat "Detect & Chamfer"
)
group "Manual (you can change Sel.)"
( button bacbutdetect "Detect Edges"
button bacbutchamfer "Chamfer them"
)
on BaoAutoChamfer open do
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) do
( bacamount.value=0.7 --bacamount.value=$.edgeChamfer -- TO DO: Fix this
bacpressedfirstbut=false
) )
on bacbutdetect pressed do
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) then
( fnDetectEdges(bacangle.value)
subobjectlevel= 2
bacpressedfirstbut=true
)
else fnMessageError()
)
on bacbutchamfer pressed do
( if(bacpressedfirstbut==false) then fnMessageError error:1
else
( undo "BaoAutoChamfer Manual" on
( subobjectlevel= 2
edgesSel=polyOp.getEdgeSelection $
if(edgesSel.count>0) do fnChamferThem edgesSel bacamount.value baciterations.value bacsmooth.checked
bacpressedfirstbut=false
) )
)
on bacbutautomat pressed do
( undo "BaoAutoChamfer Automatic" on
( if((selection.count == 1) and (classOf $.baseObject == editable_poly)) then
( fnDetectEdges(bacangle.value)
edgesSel=polyOp.getEdgeSelection $
if(edgesSel.count>0) do
(
subobjectlevel= 2
fnChamferThem edgesSel bacamount.value baciterations.value bacsmooth.checked
) )
else fnMessageError()
)
bacpressedfirstbut=false
)
) -- end of utility definition
createDialog BaoAutoChamfer
I agree with your suggestion Wahooney, this makes it more easy to access and therefore even more usefull. What do you think Bao2?
Btw. I can not get the chamfering part of the script working in Max 8 SP3 … it seems to select the edges all right but never chamfers them (seems to do some autosmooth though). Do you see the same problem in Max 8 – any ideas ?
thank you very much Bao2, it is really useful, this script is awesome, it will save me a lot of time, and thanks to wahooney too.
Xlars i think you should see if you have some amount, by deafult it´s set to 0, increase it, i hope it helps, i´m running 3ds max 8 SP3 without problem.
This is an awesome script man Great job! I noticed that it adds some extra edges though when you apply smoot chamfers to edges? Is there a checkbox somewhere that I’m missing?
Thanks for the great work!
TK
This is an awesome script man Great job! I noticed that it adds some extra edges though when you apply smoot chamfers to edges? Is there a checkbox somewhere that I’m missing?
Thanks for the great work!
TK