[Closed] Maxscript auto-select convex edges
Having searched around I can’t find a way to start writing maxscript to select convex edges.
To increase the realism of a building render, I add a slight chamfer to the edges that are convex, leaving concave edges alone. The selection of such edges would be simple if all buildings were cubes (all edges being convex).
To save progressively adding to the manual selection of convex edges (once in edge sub-object mode of the building mesh), I was wondering if anyone has any sites (searched maxscript dot com and here) or ideas on putting together a script to run that would select all convex edges so chamfering could be assigned to only those edges?
The workflow would be: enter edge sub-object mode for the building object, run convex edge selection maxscript, click Chamfer.
Thanks for any help.
to start, you should probably grab data on which faces are connected to which other faces, get the faces’ normal data, and use that normal data to see if the two normals are 1. convex and 2. ‘convex enough’ (a sphere is all convex faces, but you wouldn’t usually bevel that), then select the shared edge(s).
Hi Steve,
here it is. Evaluate it and you’ll get a rollout with a button to select convex edges in Editable Poly objects. It works on face selections too. If there aren’t selected faces it processes the whole object. It’s not super optimized, but should work well enough.
rollout rolTest "Convex Edges"
(
button btRun "Select!" width:90 align:#center offset:[0, -2]
function selectConvexEdges oPoly =
(
polyOp.setEdgeSelection oPoly #{}
local baFaceSel = polyOp.getFaceSelection oPoly
if ( (baFaceSel.isEmpty == true) or (subObjectLevel == 0) or (subObjectLevel == undefined) ) do
baFaceSel = #{1..(polyOp.getNumFaces oPoly)}
local baVertSet = polyOp.getVertsUsedOnlyByFaces oPoly baFaceSel
local baEdgeTest = (polyOp.getEdgesUsingVert oPoly baVertSet) - (polyOp.getOpenEdges oPoly)
local mGetFaceNormal = polyOp.getFaceNormal
local mGetVert = polyOp.getVert
local iNumFaces = polyOp.getNumFaces oPoly
local ap3FaceNormals = for i = 1 to iNumFaces collect (mGetFaceNormal oPoly i)
local iNumVerts = polyOp.getNumVerts oPoly
local ap3VertPos = for i = 1 to iNumVerts collect (mGetVert oPoly i)
local baConvexEdges = #{}
local aiVerts = #()
local aiFaces = #()
local p3EdgeNorm = [0,0,0]
local p3Cross = [0,0,0]
for iEdge in baEdgeTest do
(
aiVerts = polyOp.getEdgeVerts oPoly iEdge
aiFaces = polyOp.getEdgeFaces oPoly iEdge
p3EdgeNorm = normalize(ap3VertPos[aiVerts[2]] - ap3VertPos[aiVerts[1]])
p3Cross = cross ap3FaceNormals[aiFaces[1]] p3EdgeNorm
if (dot p3Cross (ap3FaceNormals[aiFaces[2]]) < 0) do
baConvexEdges[iEdge] = true
)
setCommandPanelTaskMode #modify
subObjectLevel = 2
polyOp.setEdgeSelection oPoly baConvexEdges
forceCompleteRedraw()
)
on btRun pressed do
(
if ( (selection.count == 1) and ( (classOf selection[1]) == Editable_Poly) ) do
selectConvexEdges selection[1]
)
) -- End Rollout
createDialog rolTest 96 27 style:#(#style_toolwindow, #style_border, #style_sysmenu)
- Enrico
Hi Enrico,
So sorry it’s been so long since your post for me to be replying – I had memory problems on my PC and had to quit my involvement in the Evermotion Rendering Comp (the reason why I had posted).
Had forgotten to check back until today when I started searching again for the same thing.
Awesome script. Many thanks friend. :bowdown:
Hi Steve,
I just edited previous code. It is a little improved version (avoids memory leaks, thanks to Denis Trofimov).
- Enrico
here is my version:
fn getConvexEdges node:selection[1] show:on threshold:45 ignoreHardEdges:off ignoreOpenEdges:on = if iskindof node Editable_Poly do
(
local edgeFaces = polyop.getedgefaces
local faceNormal = polyop.getfacenormal
local faceCenter = polyop.getfacecenter
local faceSmooth = polyop.getfacesmoothgroup
edges = #{}
for e in (node.edges as bitarray) do
(
ff = edgeFaces node e
if (not ignoreOpenEdges and ff.count != 2) or
(
(ff.count == 2) and
(
n1 = faceNormal node ff[1]
n2 = faceNormal node ff[2]
vc = faceCenter node ff[2] - faceCenter node ff[1]
(dot n1 vc <= 0) and (acos (dot n1 n2) > threshold) and
(
not ignoreHardEdges or (bit.and (faceSmooth node ff[1]) (faceSmooth node ff[2]) > 0)
)
)
)
do append edges e
)
if show do node.selectededges = edges
edges
)
getConvexEdges()