Notifications
Clear all

[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.

13 Replies

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]
	)
)
1 Reply
(@troopermanaic)
Joined: 11 months ago

Posts: 0

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

1 Reply
(@troopermanaic)
Joined: 11 months ago

Posts: 0

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

1 Reply
(@troopermanaic)
Joined: 11 months ago

Posts: 0

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.

Page 1 / 2