[Closed] How to use maxscript select all top faces from a building
Hello everyone,
i have a lot of boxes group as a building(every single box like a brick), the problem i am trying to figure out is i want to select all top faces of this building. Becasue there must be some box overlap on another, and the top of the building actual not flat, so how can i know which box is the topmost?
anyone can help to give me some script examples or is there any existing tools can do it ?
because the building top is not flat, so it cannot be achieved by simply calculate the shortest distance between face center and bounding box
You can use copy of building mesh to select faces using Vol Select modifier.
Otherwise modify this script to your needs.
It selects top faces that were intersected at least twice.
(
fn IsMeshObject node = isKindOf node Editable_mesh
shp = pickObject filter:IsShapeObject
tri = pickObject filter:IsMeshObject
if isValidNode shp and isValidNode tri do
(
convertToSplineShape shp
selected_before = #{}
fsel = #{}
steps = 300 -- total amount of intersections to be made along spline shape
step = 1.0 / steps
r = ray [0,0,0] -z_axis
for i = 0.0 to 1.0 by step do
(
r.pos = interpCurve3D shp 1 i
sect = intersectRayEx tri r
if sect != undefined do
(
if selected_before[ sect[2] ] do fsel[ sect[2] ] = true
selected_before[ sect[2] ] = true
)
)
setFaceSelection tri fsel
select tri
addModifier tri (Edit_Poly())
max modify mode
subObjectLevel = 4
)
)
hi Serejah, what is in your demo is really suit my problem, but after tried, i cannot got the same result with yours, my run your script as below:
1.create some boxes (convert to editable mesh)and group them like a wall,then open the group
2.create a splines-rectangle over the “wall” i just created
3.run the script
4.select the splines-rectangle and “wall” in the scene
after this, i did’t see any faces have been selected, but i can find the edit-poly that has been add to the modifier stack, can you please help me again to take a look on my steps above? thanks a million!
another question is i saw in your demo, when you select the wall, in modifier stack, it shows editble-mesh, why it could be? I mean if you select a group, it shows nothing in my modifier stack.
thanks!
what’s the point to have a wall of bricks as a group of separate objects?
in my example wall is one editable mesh object
for separate objects
(
shp = pickObject filter:IsShapeObject
if isValidNode shp do
(
convertToSplineShape shp
fn sortByZ a b =
(
if a[2].pos.z > b[2].pos.z then -1 else if a[2].pos.z < b[2].pos.z then 1 else 0
)
intersections = #()
selected_before = #{}
steps = 300 -- total amount of intersections to be made along spline shape
step = 1.0 / steps
r = ray [0,0,0] -z_axis
for i = 0.0 to 1.0 by step do
(
r.pos = interpCurve3D shp 1 i
sects = intersectRayScene r
if sects.count > 0 do
(
qsort sects sortByZ
topmost = sects[1][1]
handle = 1 + topmost.inode.handle
if selected_before[ handle ] do
(
appendIfUnique intersections topmost
)
selected_before[ handle ] = true
)
)
select intersections
)
)
hi Sersjah,
I am still got one more question, is that possible to change the spline to a plane? Is there some functions for plane that have the same functionalities with “interpCUrve3D” .Becasue now the script seems can only detective the object along with the line, but the middle part of the building may not empty. How to deal with this situation?
Used to determine if face/node was hit before.
convert your object to poly, select it and try this
(
max create mode
obj = selection[1]
up_faces = for f = 1 to polyop.getNumFaces obj where dot (polyop.getFaceNormal obj f) z_axis > 0.999 collect f
r = ray [0,0,0] z_axis
offset = z_axis * 0.001
topmost_faces = #{}
for f in up_faces do
(
fv = polyop.getFaceVerts obj f
no_intersection = true
for v in fv while no_intersection do
(
r.pos = polyop.getVert obj v + offset
sect = intersectRay obj r
if sect != undefined do no_intersection = false
)
if no_intersection do topmost_faces[ f ] = true
)
polyop.setFaceSelection obj topmost_faces
max modify mode
subObjectLevel = 4
redrawViews()
)
Hi Serejah, i modify your code a little, but the intersect function works really strange inside the for loop. I use just one box to test, the ray direct up z_axis, but it can intersect with the box below itself. i search a lot, but still have no idea why this happen
r = ray [0,0,0] z_axis
offset = z_axis * 0.001
for obj in selection do --go through all obj in the scene
(
faceList = #{}
up_faces = for f = 1 to polyop.getNumFaces obj where dot (polyop.getFaceNormal obj f) z_axis > 0.999 collect f
for f in upFaces do
(
intersection = #()
fv = polyop.getFaceVerts obj f
for v in fv do
(
r.pos = polyop.getVert obj v + offset
sect = intersectRayScene r --to test if the object intersect with other object in the scene
if sect != undefine do append intersection 1
)
--print(intersection.count)
if intersection.count < fv.count do faceList[f] = true --if the face not been fully overlaped, select it as well
)
)
sorry, there is a typo, the variable up_faces should be upFaces, but this is not the cause of the problem, thanks
-
When intersectRayScene hits nothing it returns empty array so it is never equals to undefined.
-
r = ray [0,0,0] z_axis <– z_axis equals to [ 0, 0, 1 ] (positive z direction) and so the ray will never ever intersect anything below current up_face
-
You add face indexes to to faceList but never actually use it anywhere afterwards
How to find topmost object:
If no interections found above the object then it is the topmost object. Pretty simple logic