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