Notifications
Clear all

[Closed] Cursor position from face selection

How do I find the the position the cursor is in for a face selection? Its not the middle of all the faces as that would be outside the face selection in this case. Is it weighted some how?

Thanks

11 Replies

This returns the position in pixels of the “Transform Axis”:

gw.transpoint (gettransformaxis $ 1).pos

If you need the World position of the “Transform Axis” then it is simply:

(gettransformaxis $ 1).pos

where “1” is the index of the axis in case multiple axis are shown.

Thanks! I haven’t delved much into gw. calls, or gettransformaxis. The second one is the one I needed.

Is there a way to get similar data without having to have the faces selected, and instead using a face list/array?

1 Reply
(@polytools3d)
Joined: 10 months ago

Posts: 0

There must be a way for sure, but I don’t know of any build in function for this, so we need to figure out the weighing algorithm, which is different for verts, faces and edges.

The vertex is just the average of the vertex positions, but the faces and edges are not so obvious.

This (or similar) was asked before, with no answer. Maybe Kostadin knows a way.

I’ll see if I can work something out.

The algorithm to calculate the position of the Transform Axis for the selected faces seems to work like this:

  1. Get the selected faces and break them into groups of faces connected by edge
  2. For each group calculate its center using their vertices positions
  3. Average the groups centers
  4. You are done!

For edges it might be very similar.

Awesome, i’ll give this a shot!

Thanks for the help

I’ve edited the previous comment. You need to use indeed the vertices positions instead of the faces centers for each group of faces.

Unfortunately it doesn’t work without prior edge/face selection too


delete objects

t = teapot()
convertToMesh t
setFaceSelection t #{159..160, 167..168, 187..190, 195..198, 203..206, 213..214, 281..292, 409..412, 533..536, 541..544, 549..552, 557..560, 565..568, 575..576, 643..646, 651..654, 659..662, 667..670, 675..676, 971..974, 979..982}

select t
subobjectlevel = 4

g = (dotnetclass "autodesk.max.globalinterface").instance
inode = g.COREInterface14.GetINodeByHandle t.inode.handle asdotnetobject:true
iobj  = (inode.EvalWorldState g.COREInterface.Time true asdotnetobject:true).Obj
imesh = iobj.mesh_
meshTempData = g.MeshTempData.Create imesh
meshTempData.freeAll()


selectionLevel_FACE = 4
selectionLevel_EDGE = 8

cc = meshTempData.ClusterCenters selectionLevel_FACE

gc()
pts = #()
pts = for i=1 to cc.count collect cc.get_Item (dotnetobject "system.intptr" (i-1))    
pts = for p in pts collect [p.x,p.y,p.z]    

delete helpers
for p in pts do point pos:(p * t.transform) centermarker:on cross:off wirecolor:yellow

1 Reply
(@polytools3d)
Joined: 10 months ago

Posts: 0

Just to clarify, the algorithm I’ve described does work. What does not work is the SDK method you are relying on to retrieve the clusters centers. You can still calculate them manually. You would have to if you are using an older Max version and wanted to do it in MXS only.

With your code, you could also just select the desired faces, use the MeshTempData Class and then restore the selection.
This should work for Meshes and Polys


(
    fn GetTransformAxisPos node faces:#{} =
    (
        sel = getFaceSelection node
        setFaceSelection node faces
        
        g = (dotnetclass "autodesk.max.globalinterface").instance
        inode = g.COREInterface14.GetINodeByHandle node.inode.handle asdotnetobject:true
        iobj  = (inode.EvalWorldState g.COREInterface.Time true asdotnetobject:true).Obj
        imesh = (iobj.ConvertToType 0 g.TriObjectClassID).Mesh_
        
        meshTempData = g.MeshTempData.Create imesh
        meshTempData.freeAll()

        selectionLevel_FACE = 4

        cc = meshTempData.ClusterCenters selectionLevel_FACE

        setFaceSelection node sel

        result = [0,0,0]
        pts = for i = 0 to cc.count-1 do
        (
            pos = cc.get_Item (dotnetobject "system.intptr" i)    -- Change to only i in Max 2017+
            result.x += pos.x
            result.y += pos.y
            result.z += pos.z
        )
        
        result /= cc.count

        inode.Dispose()
        iobj.Dispose()
        imesh.Dispose()
        meshTempData.Dispose()
        
        return result
    )

    /* TEST */
    delete objects
    t = converttopoly (teapot())
    axisPos = GetTransformAxisPos t faces:#{76..77, 81, 88, 108..109, 113, 120, 261, 266, 268..269, 271, 274, 276..277, 279, 298, 300..301, 303, 306, 308..309, 311}

    point pos:axisPos cross:on constantscreensize:on drawontop:on wirecolor:green
)

I didn’t mean that your way of doing it is wrong. That’s just due my poor english

I know, but the comment might be misunderstood by others not able to test the .Net version, and so it could discourage them to implement it in MXS.
Here is a simple MXS version for Polys, which needs to be optimized, in case anyone needs it.


(
    
    fn GetTransformAxisPos node faces:#{} =
    (
        GetFaceEdges = polyop.getfaceedges
        GetEdgeFaces = polyop.getedgefaces
        GetFaceVerts = polyop.getfaceverts
        GetVert      = polyop.getvert
        
        groups = #()
        doneEdges = #{}
        
        for j in faces do
        (
            grp = #(j)
            faces[j] = false
            
            for i in grp do
            (
                edges = GetFaceEdges node i
                
                for k in edges where not doneEdges[k] do
                (
                    efaces = GetEdgeFaces node k
                    
                    for h in efaces where faces[h] do
                    (
                        append grp h
                        faces[h] = false
                    )
                    doneEdges[k] = true
                )
            )
            append groups grp
        )
        
        result = [0,0,0]
        
        for j in groups do
        (
            grpCenter = [0,0,0]
            vertsCount = 0
            
            for i in j do
            (
                fverts = GetFaceVerts node i
                vertsCount += fverts.count
                
                for k in fverts do grpCenter += GetVert node k
            )
            result += grpCenter / vertsCount
        )
        
        return (result / groups.count)
    )
    
    gc()
    st=timestamp(); sh=heapfree
    
    axisPos = GetTransformAxisPos $ faces:(polyop.getfaceselection $)
    
    format "time:% heap:%
" (timestamp()-st) (sh-heapfree)

    point pos:axisPos constantscreensize:on drawontop:on wirecolor:green
)

Awesome! Thanks for the help guys : )