Notifications
Clear all

[Closed] Working with the Edit_Mesh modifier/Material ID Painter Script

Hey,

So i’m basically trieing to figure out a way to get/set selections on an edit_mesh modifier. The documentation on that modifier is really lackluster and the bit that it gives you didn’t really do anything for me.

Why I even bother with the edit_mesh modifier you ask? Well, I have been working on a material ID painter that works off the painter interface functions, I basically get the hit face index and set that faces material ID to the currently selected ID. The problem is that it seemingly works off the active object as a trimesh value, so I allways get the face indices of the internal triangles of my edit_poly modifier or editable_poly base object. While I can work with an edit_poly modifier, this forces me to triangulate the mesh before applieing the edit_poly modifier – which I don’t really want to do for sake of editing simplicity.

Has anyone ever gotten this to work at all? Or do you have other suggestions that could solve my problem?

9 Replies

if you know the face index of trimesh then you’re step away from getting a poly index by three verts indexes

1 Reply
(@ashuradx)
Joined: 11 months ago

Posts: 0

well, I know the triface index, but since I don’t know how to access tridata from an edit_poly modifier I can’t really get the proper vertex indices – this might be part of a possible solution though!

Since you don’t modify topology you can get trimesh before painting and use it like that


tri = snapshotAsMesh polyobj
fVerts = getFace tri faceIndex
polyFaceIndex = (polyop.getFacesUsingVert polyobj fVerts[1]) * (polyop.getFacesUsingVert polyobj fVerts[2]) * (polyop.getFacesUsingVert polyobj fVerts[3])
polyFaceIndex = (polyFaceIndex as array)[1]

1 Reply
(@ashuradx)
Joined: 11 months ago

Posts: 0

clever! I’ll see if this works, guess I should set up the snapshot in the initialisation function of my Paint tool and delete it in the “End” and cancel funcrtions.

@Serejah
This worked perfectly! Thanks a lot!
I just wodner wether it could be speed up a little, allthough the minor slowdown this caused isn’t too bad.

Well, you can create a sort of lookup table to speed it up.
Didn’t test it in max, but hope you get the idea


vertFaces = #()
for f=1 to polyop.getNumFaces polyobj do 
(
   fv = polyop.getFaceVerts polyobj f
   for v in fv do
   (
      if vertFaces[v] == undefined then vertFaces[v] = #{ f } else vertFaces[v][f] = true
   )

)

then you check it as before


tri = snapshotAsMesh polyobj
fVerts = getFace tri faceIndex
index = ((vertFaces[ fVerts[1] ] * vertFaces[ fVerts[2] ] * vertFaces[ fVerts[3] ]) as array)[1]

1 Reply
(@ashuradx)
Joined: 11 months ago

Posts: 0

My solution was to run this chunk of code before initialising my paint tool:


local source = pb_terrain.object
local tri = snapshotasmesh pb_terrain.object
local poly = snapshot source
convertto poly editable_poly

local TriFacecount = getNumFaces tri
trifaceLUT = #()

for f = 1 to TriFacecount do(
    
    local fVerts = getFace tri f
    local polyFaceIndex = (polyop.getFacesUsingVert poly fVerts[1]) * (polyop.getFacesUsingVert poly fVerts[2]) * (polyop.getFacesUsingVert poly fVerts[3])
    local polyFaceIndex = (polyFaceIndex as array)[1] as integer
    append trifaceLUT polyFaceIndex
)
    
delete poly

So after creating this triface to polyface LUT I can just do this in my paintstroke function:


local polyface = trifaceLUT[faceindex] as integer

if classOf target == Edit_Poly then (
    target.setSelection #Face #{}
    target.select #Face #{polyface}
    for i = 1 to sp_growth.value do (
        target.ButtonOp #GrowSelection
    )
    target.SetOperation #SetMaterial
    target.materialIDToSet = MatID
    target.Commit ()
)
else (
    
    polyop.SetFaceSelection TheObject #{polyface}
    for i = 1 to sp_growth.value do (
        target.GrowSelection ()
    )
    sel = polyop.getFaceSelection target
    polyop.setFaceMatID TheObject sel lb_materials.selection
)

this works rather quickly at the cost of short initialisation period when starting the tool and I can live with that. On most meshes this initialisation period is barely noticeable actually.

I think getFacesUsingVert makes it unusable on middle and high poly meshes.
see for yourself



(
    
delete objects

poly = Teapot segments:12
convertToPoly poly
tri = snapshotAsMesh poly
    

gc();t1=timestamp();hf = heapfree

        
    trifaceLUT = #()
    polyopGetFacesUsingVert = polyop.getFacesUsingVert
    trifaceLUT = for f = 1 to tri.numfaces collect (

        local fVerts = getFace tri f
        local polyFaceIndex = (polyopGetFacesUsingVert poly fVerts[1]) * (polyopGetFacesUsingVert poly fVerts[2]) * (polyopGetFacesUsingVert poly fVerts[3])
        (polyFaceIndex as array)[1]
        
    )

format "Time: %sec. Mem: %
" ((timestamp()-t1)/1000 as float) (hf-heapfree)
format "%

" trifaceLUT


gc();t1=timestamp();hf = heapfree

trifaceLUT2 = #()
vertFaces   = #()
polyopGetFaceVerts = polyop.getFaceVerts

    for f=1 to polyop.getNumFaces poly do (

        for v in polyopGetFaceVerts poly f do (
            
            if vertFaces[v] == undefined then vertFaces[v] = #{f} else vertFaces[v][f] = true
            
        )
        
    )


    for i=1 to tri.numfaces do (
        
        f = getFace tri i
        
        trifaceLUT2[i] = ((vertFaces[f[1]] * vertFaces[f[2]] * vertFaces[f[3]]) as array)[1]
        
    )

format "Time: %sec. Mem: %
" ((timestamp()-t1)/1000 as float) (hf-heapfree)
format "%
" trifaceLUT2


identical = true
for i=1 to trifaceLUT.count while identical where trifaceLUT[i] != trifaceLUT2[i] do identical = false
format "
LUTs are identical: %
" identical    

)

[quote=]Time: 3.256sec. Mem: 4056968L
#(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, …)

Time: 0.173sec. Mem: 3928624L
#(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, …)

LUTs are identical: true
and if you save lut poly face index as bitarray without converting to integer it could be twice as fast
Time: 0.081sec. Mem: 2773056L