Notifications
Clear all

[Closed] How do i select the highest positioned Vertex of a mesh plane?

I’ve been learning max scrpt for some time now, and am in the process of finnishing up a simple, forest creation tool. However, I’m new and a little stuck. What I’m trying to do is access a local mesh plane (which has been modified with noise), and select the highest vertex and basically spawn a tree on it. Mayeb select the highest 5 vertex’s and spawn trees on them…

So far, I can only spawn on a selected vertext like below:

 newPos = getVert $.mesh 1
 newPos = newPos *$.transform
 treeMaker newPos

Any input would be greatly appreciated. Oh, and I will be sticking around!

Retrojuice.

13 Replies

Here’s one way to do it :

1- You can use “nodeLocalBoundingBox()” on your noised box (maybe collapsed as a mesh first), it will return you the highest and lowest point of the box.

2- You specify a threshold somewhere in your tool

3- You parse all the vertices of the noised box.
When the difference between the Z-transform of your vertex and the Z-transform of the highest point is under the defined threshold, you spawn a tree on it.

Nota : using the nodeLocalBoundingBox may implicate that your box is at [0,0,0]

This is one way to do what you want. Send this function a mesh or poly object along with the number of verts you want it to find and it will return an array of vert numbers from highest to lowest measured in Z


 (
 	fn findHighestVerts obj highestCount =
 	(		
 		--snapshots the mesh so you can use meshops even if the incoming is a poly object
 		tempMesh = snapshotAsMesh selection[1]
 
 		-- creates a multidimensional array the size of the highestCount.  Each element contains [1]first vert number [2]first vert height
 		highestVerts = #()
 		firstVert = #()
 		firstVert[1] = 1
 		firstVert[2] = (meshop.getvert tempMesh 1)[3]
 		for i = 1 to highestCount do highestVerts[i] = firstVert
 		
 		-- iterates through the verts and compares it to the height of the last vert in the array ( we start at 2 here cause we know that vert 1 occupies ALL slots in the array at this point)
 		for i = 2 to getNumVerts tempMesh do
 		(
 			vertPosZ = (meshop.getvert tempMesh i)[3]
 			if vertPosZ > highestVerts[highestCount][2] do
 			(
 				--if the current vert is higher than the last vert in the array, it replaces the last vert in the array with the current one.
 				highestVert = #()
 				highestVert[1] = i
 				highestVert[2] = vertPosZ
 				highestVerts[highestCount] = highestVert
 				
 				-- tests the newly added vert against each next vert in the array and if it's higher in Z, it swaps the new vert up the array until it is in the correctly ordered spot.
 				inOrder = false
 				(
 					for j = highestCount to 2 by -1 while inorder == false do
 					(
 						if highestVerts[j][2] > highestVerts[j-1][2] then
 						(
 							temp = highestVerts[j-1]
 							highestVerts[j-1] = highestVerts[j]
 							highestVerts[j] = temp
 						)
 						else inOrder = true
 					)
 				)
 			)
 		)	
		delete tempMesh
 		
 		-- build a single dimential array of just the vert numbers
 		returnVerts = #()
 		for i = 1 to highestCount do append returnVerts highestVerts[i][1]
 		
 		-- returns the array of vert numbers
 		returnVerts
 	)
 	
 	clearlistener()
 	findHighestVerts selection[1] 5
 )
 
 3ak

This little script returns array of verts positions sorted in Z and creates 5 Point helpers on the highest vertices:

fn compAB a b =	if a.z<b.z then 1 else if a.z>b.z then -1 else 0	
verts = #()
obj = snapshotasmesh $selection[1]
for i = 1 to obj.numverts do verts[i] = (getvert obj i)
qsort verts compAB

for i = 1 to 5 do point pos:verts[i]

Wow 3ak, that’s some tidy looking code. However I just tried it on a large mesh and it was 6 times slower than mine. 90368 vs 13119. It would also be much more of a memory hog since it stores all vert positions. I might try a version of mine later today with your qsort method implemented rather than my manual sort to see if it improves my clumsy-looking code.

Cg.

2 Replies
 3ak
(@3ak)
Joined: 11 months ago

Posts: 0

It’s because our scripts do different things) I, and believe denisT sort array of vertices in Z and you leave it untouched and find 5 biggest vertices in Z.

(@denist)
Joined: 11 months ago

Posts: 0
however you are right. it must be much faster to find 1,2,3, or N highest verts than sort whole array.
it actually gave me an idea... 

NEW MINI-CHALLENGE IS COMING SOON!

here is my version:


 fn findHighestVerts obj = 
 (		
 	mesh = snapshotasmesh obj
 	indexes = #{1..mesh.numverts}
 	zpos = #()
 	verts = for v in indexes collect 
 	(
 		p = getvert mesh v
 		append zpos p.z
 		p
 	)
 	zp = dotnet.valuetodotnetobject zpos (dotnetclass "System.Single[]")
 	vv = dotnet.valuetodotnetobject (indexes as array) (dotnetclass "System.Int32[]")
 	zp.Sort zp vv
 	vv.Reverse vv
 
 	for v in vv.Clone() collect verts[v]
 )
 
 

just wanted to make it faster

because your code doesn’t work right. sorry for saying that.

because your code doesn’t work right. sorry for saying that.

Hey Dennis, no need to say sorry. Your feedback is always welcome. If it doesn’t work, I definitely want to know about it. But the code works for me. How are you testing it to make it not work? Is it that it doesn’t create the point helpers but instead just returns the vertex indices? Or is it not actually returning the correct verts for you?

Cheers,
Cg.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

nobody cares about the points helpers… your method as i see doesn’t go through all verts. how can it be right?
try to print output for all verts. the right method has to return sorted by Z vert positions (or indexes).

double post

OK, here’s another try including qsort and I also fixed my initialisation of my array by putting the first N verts into it rather than filling it up with only vertex1 information which would most likely cause problems sometimes. Dennis, I still don’t know what you meant by:

your method as i see doesn’t go through all verts.

Because I’m pretty sure the following line handled that

for i = 2 to getNumVerts tempMesh do

But my latest attempt iterates slightly differently.


   (
 	fn compAB a b =	if a[2]<b[2] then 1 else if a[2]>b[2] then -1 else 0
 	 fn findHighestVerts obj highestCount =
 	 (		
 		 tempMesh = snapshotAsMesh selection[1]
 		 highestVerts = #()
 		for i = 1 to highestCount do highestVerts[i] = #(i,((meshop.getvert tempMesh i)[3]))
 		qsort highestVerts compAB
 		 for i = (highestCount+1) to getNumVerts tempMesh do
 		 (
 			 vertPosZ = (meshop.getvert tempMesh i)[3]
 			 if vertPosZ > highestVerts[highestCount][2] do
 			 (
 				 highestVerts[highestCount] = #(i,vertPosZ)
 				 qsort highestVerts compAB
 			 )
 		 )	
 		 returnVerts = #()
 		 for i = 1 to highestCount do append returnVerts highestVerts[i][1]
 		for theVert in returnVerts do point pos:(meshop.getvert tempMesh theVert)
 		delete tempMesh
 		 returnVerts
 	 )
 	 findHighestVerts selection[1] 5
  )
   
Page 1 / 2