Notifications
Clear all

[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 ?

13 Replies

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
			
	)
)

SQ0UUfXQq3

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?

And what is the selected_before stand for?

1 Reply
(@serejah)
Joined: 10 months ago

Posts: 0

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

  1. When intersectRayScene hits nothing it returns empty array so it is never equals to undefined.

  2. 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

  3. 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

Page 1 / 2