Script wish: removing multi/sub material assignment on mesh that only uses one material

Script wish: removing multi/sub material assignment on mesh that only uses one material

Haider_of_Sweden
Collaborator Collaborator
1,662 Views
8 Replies
Message 1 of 9

Script wish: removing multi/sub material assignment on mesh that only uses one material

Haider_of_Sweden
Collaborator
Collaborator

Could someone please help me with a Maxscript, that assigns only that one material from a multi-sub material that is used on a mesh, based on its ID?

 

Background:

I got a mesh with multiple IDs

Naturally, you need a multi/sub material for each ID

I have a script that detaches the mesh based on their ID

So far, each mesh still has a multi/sub material assigned. I might want to reorder the IDs, or attach and do a new Match Material IDs to Material. There might be other cases you need this to be cleaned up.

0 Likes
Accepted solutions (3)
1,663 Views
8 Replies
Replies (8)
Message 2 of 9

denisT.MaxDoctor
Advisor
Advisor
Accepted solution
mapped fn assignSingleSubMaterial node = 
(
	fn getMeshMaterialIds node = 
	(
		ids = #{}
		mesh = node.mesh
		for f=1 to mesh.numfaces do append ids (getFaceMatID mesh f)
		ids
	)	

	res = false
	if iskindof node GeometryClass and iskindof node.mat MultiMaterial do
	(
		ids = getMeshMaterialIds node
		if ids != undefined and ids.numberset == 1 do 
		(
			id = (ids as array)[1]
			if id <= node.mat.numsubs do
			(
				node.mat = getsubmtl node.mat id
				res = true
			)
		)
	)
	res
)

/*
assignSingleSubMaterial objects
-- or 
--assignSingleSubMaterial selection
-- or
--assignSingleSubMaterial geometry
*/
0 Likes
Message 3 of 9

Haider_of_Sweden
Collaborator
Collaborator

A bit late, but thanks, @denisT.MaxDoctor !

 

I wanted to add a Material modifier, and set it to 1. 

addModifier $ (Materialmodifier materialid:1)

 

I think there might be a better way.

The purpose is that once this object has one single material, I would want to reset the IDs as well.

 

How can it be done?

0 Likes
Message 4 of 9

denisT.MaxDoctor
Advisor
Advisor
Accepted solution

if we are working with an editable_mesh or an editable_poly nodes, we can set face ids directly. Also we can do something special for patches and splines. But for other geometry cases, the only way is to use the Material modifier.

so the function could be something like this:

fn setNodeMaterialID node id:1 = 
(
	if iskindof node Editable_Mesh then 
	(
		for f=1 to node.numfaces do setfacematid node f id
		true
	)
	else if iskindof node Editable_Poly then 
	(
		polyop.setfacematid node #all id
		true
	)
	else 
	(
		--addmodifier node (Materialmodifier id:1) 
		false
	)
)

 

0 Likes
Message 5 of 9

Haider_of_Sweden
Collaborator
Collaborator

@denisT.MaxDoctor wrote:

if we are working with an editable_mesh or an editable_poly nodes, we can set face ids directly. Also we can do something special for patches and splines. But for other geometry cases, the only way is to use the Material modifier.

so the function could be something like this:

 

fn setNodeMaterialID node id:1 = 
(
	if iskindof node Editable_Mesh then 
	(
		for f=1 to node.numfaces do setfacematid node f id
		true
	)
	else if iskindof node Editable_Poly then 
	(
		polyop.setfacematid node #all id
		true
	)
	else 
	(
		--addmodifier node (Materialmodifier id:1) 
		false
	)
)

 

 


Haider_of_Sweden_0-1649662428448.png

 

Even though I have an editable Poly, I had to go for the addmodifier option.

That was not how it should work, or? Or is it me using the function wrong?

0 Likes
Message 6 of 9

denisT.MaxDoctor
Advisor
Advisor
Accepted solution

you are using selection in your code.

selection is not a single node, it's a collection of nodes. that's why my function is not working. We can make the function mapped so that it works for a set of objects, or you have to call selection[1] which means the first selected node

0 Likes
Message 7 of 9

Haider_of_Sweden
Collaborator
Collaborator

I was going to use it together with your first assignSingleSubMaterial anyway, so I tried with mapped and selection and it works.

 

How did you intend it to be used?

 

 

Also. a strange behavior (for me at least, illiterate in MXS as I am) I encountered during my tests, is when I wrote setNodeMaterialID objects

 

Haider_of_Sweden_0-1649667621771.png

 

 

I selected only the split objects, not the single objects with multi-sub-materials.

Then I ran both assignSingleSubMaterial objects and setNodeMaterialID objects (note objects), this happened

 

Haider_of_Sweden_1-1649667839633.png

 

 

 

does Objects mean ALL objects in the scene?

0 Likes
Message 8 of 9

denisT.MaxDoctor
Advisor
Advisor

run all definitions...

and do example code (commented part) line by line:

 

 

 

 

 

fn test_setMatID node:selection[1] rangeID:[1,64] = 
(
	for f in (node.faces as bitarray) do polyop.setfacematid node f (random rangeID[1] rangeID[2])
)

fn collectByMatID node = 
(
	ids = #()
	for f in (node.faces as bitarray) do 
	(
		id = polyop.getfacematid node f
		if ids[id] == undefined do ids[id] = #{}
		append ids[id] f
	)
	ids
)

fn collectMatIDs node = 
(
	ids = #{}
	for f in (node.faces as bitarray) do append ids (polyop.getfacematid node f)
	ids
)
fn detachByID node parent:undefined = if iskindof node Editable_Poly do
(
	ids = collectMatIDs node
	num = 0
	for id in ids do
	(
		node.selectByMaterial id
		if (polyop.detachfaces node node.selectedfaces delete:on asnode:on name:("id_" + id as string)) do
		(
			objects[objects.count].parent = parent
			num += 1
		)
	)
	num
)
mapped fn setPolyMaterialID node id = if iskindof node Editable_Poly do 
(
	polyop.setfacematid node #all id
	true
)
mapped fn assignSingleSubMaterial node resetID = if iskindof node Editable_Poly do
(
	res = false
	if iskindof node.mat MultiMaterial do
	(
		ids = #{}
		for f=1 to node.numfaces do append ids (polyop.getFaceMatID node f)
		
		if ids.numberset == 1 do 
		(
			id = (ids as array)[1]
			if id <= node.mat.numsubs do
			(
				node.mat = node.mat[id]
				res = true
			)
		)
		
		if resetID != unsupplied do setPolyMaterialID node resetID
	)
	
	res
)

fn hsv_to_rgb hsv = 
(
	rgb = black -- it might be any color
	rgb.v = hsv.z
	rgb.s = hsv.y
	rgb.h = hsv.x
	rgb
)

fn test_makeMultiMaterial name: numsubs: =  
(
	mat = Multimaterial name:name numsubs:numsubs
	num = mat.numsubs
	step = 255.0/num
	for k=1 to num do 
	(
		mat[k].name = "IDx" + k as string
		mat[k].diffuse = hsv_to_rgb [(k - 0.5)*step, 255,255]
	)
	mat
)

mapped fn test_pushPoly node offset = 
(
	v = polyop.getfacenormal node 1 
	node.transform *= transmatrix (v * offset)
)	

/*

delete objects
gc()

bx = converttopoly (box name:"BX") -- this is a poly box with 6 mat ids
ids = collectMatIDs bx
meditmaterials[1] = bx.mat = test_makeMultiMaterial numsubs:ids.numberset
d = dummy name:#master transform:bx.transform
detachByID bx parent:d 

test_pushPoly d.children 10

assignSingleSubMaterial d.children 1

format "name:% >> mat:%\n" bx.name bx.mat

for c in d.children do format "name:% >> ids:% mat:% (%)\n" c.name (collectMatIDs c) c.mat c.mat.diffuse
*/

 

 

 

 

 

0 Likes
Message 9 of 9

denisT.MaxDoctor
Advisor
Advisor

I've fixed couple bugs in the previous code 

 

0 Likes