[Closed] Need help with something in multimaterials
Hey I actually used to know this but I somehow completely forgot it, basically I’m trying to get the number of faces and verts in each material in multimaterials.
For example say I had a square thats half blue and half red. I need to get the number of faces and verts each material occupies in that material.
for OBJ in geometry do(
if classof OBJ.material == multimaterial do(
for a=1 to OBJ.material.count do(
print OBJ.material[a]
)
)
)
any help would be deeply appreciated.
Faces make sense, vertices… well, what would be the number you’d expect with you example, square half blue, half red? Anyway, for the face count for individual objects:
fn getFacesByID obj IDs:#() =
(
for face = 1 to obj.numFaces do
(
local id = getFaceMatID obj face
if NOT isKindOf IDs[id] Number then IDs[id] = 1
else IDs[id] += 1
)
IDs
)
for obj in geometry
where isKindOf obj.mat MultiMaterial do
(
format "% : %
" obj.name obj.material.name
local ids = getFacesByID obj
for id = 1 to ids.count where isKindOf ids[id] Number do
format " % : % faces
" obj.mat[id].name ids[id]
)
For scene totals:
(
fn getFacesByID obj IDs:#() =
(
for face = 1 to obj.numFaces do
(
local id = getFaceMatID obj face
if NOT isKindOf IDs[id] Number then IDs[id] = 1
else IDs[id] += 1
)
IDs
)
local mats = getClassInstances MultiMaterial
for mat in mats do
(
local objs = refs.dependentNodes mat
local ids = #()
for obj in objs do getFacesByID obj IDs:ids
format "%
" mat.name
for id = 1 to ids.count where isKindOf ids[id] Number do
format " % : % faces
" mat[id].name ids[id]
)
)
I’m sorry I was vague. Its 5:20 AM and I’m tired.
What I meant was, say that I have a flat model that consists of 3 faces 2 of the faces have the same material.
As you can see though the image the model only has 5 verts in total but there is a different amount of verts I want to print which is 3 then 5 in an array “I want to stress that I do not want to split the verts”.
Its all based upon the total amount of verts the faces use based upon a single material in multimaterial models.
if you do it for one object:
#1 check if the object has multi-material assigned
#2 collect all faces by its material id (as bitarrays)
#3 get all map vertices used by every face set
for all nodes in scene:
#1 collect all nodes that have a specified material assigned
#2,#3 do the same as above for every node skipping a check that the material assigned
Ah yes that actually makes allot of sense. Ill test it out later on today.
*EDIT
OK I figured out how to get the amount of faces in each material in multimaterial objects, how would I get the vert count now I don’t know how to do step 3.
IDMAT_Array=#()
clearlistener()
fn compare item=(
IDCount=0
for a=1 to IDMAT_Array.count do(
if item == IDMAT_Array[a] do(
IDCount=IDCount+1
)
)
print IDCount
)
for OBJ in geometry do(
if classof OBJ.material == multimaterial do(
for a=1 to OBJ.numfaces do(
IDMAT=OBJ.material[getfacematid OBJ a]
append IDMAT_Array IDMAT
)
for a=1 to OBJ.material.count do(
compare OBJ.material[a]
)
)
)
Sorry for bump I just haven’t figured out the last part of of denisT’s suggestion and need a little bit of help. I was thinking about using my method above to select faces and print the vert count of selected faces but strangely enough I don’t know how to do that. “I never had to print vertcount from faces before.”
I didn’t want to create another thread for this but I also have one last question. Is it possible to make a dynamic dropdownlist? I’ve searched this forum with no avail. Basically I want to have all meshe & point names in the scene in a dropdown list but I only know how to do this via Array. Id like this to update every time I remove or add a mesh or point. “If I knew this I probably would be able to apply it to dotnet treeview as well”.
dropdownlist ddl_name items:#("item1","item2")
....
on btn_01 pressed do
(
ddl_name.items = #("item1","item2", "item3")
)
if you use a variable
f = ddl_name.items
then you may operate with f like with any other array:
append f "555"
deleteItem f 2
and then ddl_name.items = f
This isn’t what i’m trying to do. It technically is a way to do things and is my current method but I’m trying to stay away from arrays so that my GUI will be more dynamic. For example this is my current method “for reasons beyond what I’m explaining here”
clearlistener()
rollout ITEMS "Items" width:288 height:56(
dropDownList ITEMLIST "DropDownList" pos:[8,8] width:272 height:40
fn fillIndropDownList NODES =(
for n in NODES do(
ITEMLIST.items = append ITEMLIST.items n.name
)
)
on ITEMS open do(
NODES=for OBJ in objects collect OBJ
fillIndropDownList NODES
)
)
createdialog ITEMS
Where NODES are defined id like to make it completely dynamic but I know “on ITEMS open do” would not be able to achieve this. Currently say if I had meshes in my view and I load this and delete or create some them while the script is open, they will stay in the dropdownlist and not update the new ones created.
So instead of just creating an array and adding and removing. Id like to just have it always know whats in the world space.
there are two ways used to do what you want (dynamically update a list of nodes):
1 – use scene callbacks
2 – make you tool as plugin (or custom attribute) and use its parameter block changing handles
both ways have also ‘sub-ways’
#1
a) use general scene callbacks
b) use node event callbacks
#2
a) scripted plugin (node or modifier)
b) scripted custom attribute
every possible solution depends on what your tool does do.
here is a sample of #1(a) :
try(destroydialog nodeMonitorDilaog) catch()
rollout nodeMonitorDilaog "Node Monitor" width:200
(
listbox nodes_lb width:196 height:40 pos:[2,2]
fn collectNodes =
(
classes = #()
nodes = #()
for node in objects do
(
class = classof node
if (k = finditem classes class) == 0 do
(
append classes class
k = classes.count
nodes[k] = #()
)
append nodes[k] node
)
#(classes, nodes)
)
fn updateNodeList =
(
data = collectNodes()
items = #()
for k=1 to data[1].count do
(
append items (data[1][k].localizedname + " (" + data[2][k].count as string + ")")
for node in data[2][k] do append items (" " + node.name)
)
nodes_lb.items = items
)
on nodeMonitorDilaog close do
(
callbacks.removescripts id:#node_monitor_id
)
on nodeMonitorDilaog open do
(
callbacks.removescripts id:#node_monitor_id
action = "nodeMonitorDilaog.updateNodeList()"
callbacks.addscript #sceneNodeAdded action id:#node_monitor_id
callbacks.addscript #nodePostDelete action id:#node_monitor_id
callbacks.addscript #nodeRenamed action id:#node_monitor_id
updateNodeList()
)
)
createdialog nodeMonitorDilaog
there are many thing we have to do with it (optimization, list redraw issue, sorting order, resolve not unique names, class changed event, etc). but i shows at least the idea.
there are another events that can change our list but not added to our monitored callbacks. some of them can duplicate each other (#sceneNodeAdded and #nodeCreated for exampe)…
so… i would use method #1(b) – Node Event Callbacks
danisT you are a wizard brother. Thanks again this actually works allot better then the method i’m currently using.
Back on the original topic, I never figured out how to get the vert count in face sets. I know you mentioned them earlier and I did every step except the last.
Here’s my current script
IDMAT_Array=#()
clearlistener()
fn compare item=(
IDCount=0
for a=1 to IDMAT_Array.count do(
if item == IDMAT_Array[a] do(
IDCount=IDCount+1
)
)
print IDCount
)
for OBJ in geometry do(
if classof OBJ.material == multimaterial do(
for a=1 to OBJ.numfaces do(
IDMAT=OBJ.material[getfacematid OBJ a]
append IDMAT_Array IDMAT
)
for a=1 to OBJ.material.count do(
compare OBJ.material[a]
)
)
)
IDMAT_Array gets the amount of faces per material in a multimaterial editable mesh. How would I print the vert count of those faces?
Sorry for another bump this will be my last attempt at this.
I realized before that my code was dirty and found a way better and cleaner way to get what I’m looking for up until vertcounts. What I’m trying to do is get the vertex count in applied materials in multi material meshes.
example~
like said before I want to create an array that would take the above image and print out “3,4” if that theoretical mesh was in your scene.
for OBJ in geometry do( --filters editable_meshes in scene
if classof OBJ.material == multimaterial do( --filters multimaterial editable_meshes
for a=1 to OBJ.material.count do( --filters ammount of materials in multimaterial editable_meshes
print OBJ.material[a] --standard materials in multimaterial editable_meshes
for b=1 to OBJ.numfaces do( --filters ammount of faces in editable_meshes
if a == (getfacematid OBJ b) do( --filters material in faces
print (meshop.getVertsUsingFace OBJ b)
)
)
)
)
)
so up until I print (meshop.getVertsUsingFace OBJ b) is where I’m brick walling on this. I left print OBJ.material[a] to show where the next material is.
I need to get the vertex count in each material.