Bao2
07-05-2005, 06:53 PM
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.
Updated: Version 1.1
Note: The object stack must be collapsed. This script don't works well or fails
(script error messages) if there are modifiers in stack.
/*
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
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.
Updated: Version 1.1
Note: The object stack must be collapsed. This script don't works well or fails
(script error messages) if there are modifiers in stack.
/*
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
