Notifications
Clear all

[Closed] [MaxScript] even edgeloop vertex distribution/spacing?

Hi, iwe been struggling with a somewhat geometry math related situation.
I got such good help here last time i asked a question so i thought id ask another.
I tried searching through the forums but i couldnt find a similar working solution for maxscript.

So the main goal is to basically replicate the looptools->space function in graphitemodelingtools (3ds max) in maxscript.

I already wrote a function some time ago that gives me arrays of sorted vertex loops from edgeloop selections.
Sorted as in for an open loop the first array index is the first vert on the edgeloop, second index is the second vert in the edgeloop and so on.

But im at a loss about how to determine the new positions for the verts.

I got as far as determining the total length of the edgeloop by using PolyOp.GetVert to get vert position.
Then adding to the distance via distance “last vertex position” “vertex postion”.
Then getting the even distance between each vert by dividing with the amount of verts in the set.
The issue now is that how do i determine the actual new worldspace position each vertex should get along the loop.

unfinished code snippet:
Note the AspDev.GetVertPosition/AspDev.SetVertPosition are just wrappers for polyop.GetVert/SetVert.

for vertSet in sortedVertSets do
    (
        local vertCount = vertSet.count

        local loopLength = 0
        local pvPos
        --finish calls to getVertPosition
        local vPosArray = for vert in vertSet collect
        (
            vPos = AspDev.GetVertPosition modOrObj vert node:node
            if classOf pvPos == point3 do loopLength += (distance pvPos vPos)
            --store last vPos
            pvPos = vPos
            --finally collect current vPos to vPosarray
            vPos
        )
        local pointA = vPosArray[1]
        local pointB = vPosArray[vertCount]
        --this should have the correct spacing distance??
        local loopSpacing = loopLength / vertCount

       --what now?

        --batch setVert op
        AspDev.SetVertPosition modOrObj vertSet vPosArray node:node
    )

Thanks in advance

8 Replies

After some more research i have found that the solution is even more complex than i had first assumed.

The method i had first envisioned would be translating each vert “forward” in the loop.
i would only get expected even spacing on a completly straight loop. But would result in the last edge being shorter in a curved edgeloop.

It seems to me that i will need to use an interpolation curve created by using the vertex positions as curve points. And then getting even points along the resulting curve to get proper spacing of the edgeloop.

I Started by testing with creating a smooth max spline object from the edgeloop verts and then using interpSpline3D to get even points along the spline. This works but the resulting interpolation is very smooth, and creates way too much displacement in most cases.

I tried using both a line curve (no smoothing). But it really shrinks and changes the loop too much.
a CVCurve with a lower interpolation order might work. But getting the creation via maxscript api working is really clumpsy and difficult. Its also very slow.

Im thinking right now that the only real way is by implimenting a catmull-rom curve interpolation(or similar) function. Anybody got any hints on doing this in maxscript by building via an array of point3. And returing an array of evenly spaced point3?

So did you already solved this? and are you dividing the total length by vertex count? should it be edge count?

1 Reply
(@lande3d)
Joined: 11 months ago

Posts: 0

Not solved yet no. Currently trying out using curve interpolation via splineshapes. Dividing by amount of vertex gaps(edge count).

hmmm… I doubt SpaceLoop is using a spline


fn gvSpcLoop =
(
obj = $
edgeLen = 0.0
obj.EditablePoly.ConvertSelection #Edge #Vertex
selEdgeVert = (polyop.getVertSelection obj) as array
for i = 1 to (selEdgeVert.count - 1) do 
(
getDist = distance (polyop.getVert obj selEdgeVert[i]) (polyop.getVert obj selEdgeVert[(i + 1)])
edgeLen +=  getDist 
)

getEdgeCount = ((polyop.getEdgeSelection obj) as array).count
lengthToDistrib = edgeLen / (getEdgeCount as float)

for  i = 2 to (selEdgeVert.count - 1) do
(
startPos = polyop.getVert obj selEdgeVert[(i - 1)]
dirPos = normalize ((polyop.getVert obj selEdgeVert[i]) - polyop.getVert obj selEdgeVert[(i - 1)])

newPos = 	startPos + (dirPos * lengthToDistrib)
polyOp.setVert obj selEdgeVert[i] newPos 
)
)


try to run gvSpcLoop() on selected uneven spaced loop and see if this works?

2 Replies
(@lande3d)
Joined: 11 months ago

Posts: 0

Thanks man. That looks really promising. Il try it out.
I also doubt spaceloop uses a spline this way. It was just something i wanted to try if it could be workable as a simple solution. My best guess is that spaceloop Is probably using a c++ interpolation function.

(@lande3d)
Joined: 11 months ago

Posts: 0

Ok i got to test it.
Its a pretty good method. Its better than both interpolating a linear curve and a smooth curve. The results are somewhere inbetween of these in terms of smoothness.
Thank you so much. I think i can call it solved.
I had to change it to work with sorted vertloops instead of directly with the bitarray sorting( if the topology is edited the index orders get scrambled ). As well as put it in a loop to make it support multiple loops. but after that it works well in all cases.

it was from PolyBoost which was once just a maxscript and just re-written on C.

the website is still alive: http://www.polyboost.com/

1 Reply
(@lande3d)
Joined: 11 months ago

Posts: 0

Ye. too bad i cant find the original maxscript file anywhere.