[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?
if you know the face index of trimesh then you’re step away from getting a poly index by three verts indexes
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]
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.
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]
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
here’s a much better way to do it.
https://forums.autodesk.com/t5/3ds-max-programming/get-face-poly-by-face-mesh-in-maxscript