PDA

View Full Version : How do i select the highest positioned Vertex of a mesh plane?


retrojuice
03-14-2012, 01:14 PM
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! :D

Retrojuice.

MrPingouin
03-23-2012, 03:32 PM
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]

3rd Dimentia
03-26-2012, 04:01 AM
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
03-26-2012, 08:20 AM
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]

3rd Dimentia
03-26-2012, 09:10 PM
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.

denisT
03-26-2012, 10:16 PM
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 ;)

denisT
03-26-2012, 10:22 PM
However I just tried it on a large mesh and it was 6 times slower than mine
because your code doesn't work right. sorry for saying that.

3rd Dimentia
03-26-2012, 11:31 PM
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.

3rd Dimentia
03-26-2012, 11:32 PM
double post

denisT
03-26-2012, 11:39 PM
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?

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

3ak
03-27-2012, 12:00 AM
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.

denisT
03-27-2012, 02:56 AM
...

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!

3rd Dimentia
03-27-2012, 09:54 AM
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
)

denisT
03-27-2012, 02:00 PM
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:

Because I'm pretty sure the following line handled that

But my latest attempt iterates slightly differently.

...


the code is correct. it was correct as well. i just was not accurate reading it.

well...
the method(1) uses kinda BubbleSort algorithm. to make full sort we always have to make (n*n + n)/2 comparisons.
3ak's method(2) uses QuickSort algorithm, which needs approximately n*log(n) comparisons. (this is not actually true but close enough).

the method1 wins because we are looking for small amount of elements.
and it's easy to calculate when method2 will outrun method1.

so the simple conclusion is - don't do full sort if you need only several pick elements.

CGTalk Moderation
03-27-2012, 02:00 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.