Notifications
Clear all

[Closed] Smoothing groups to material ID's

Im trying to create a script that turns your smoothing groups into material IDs. The problem is that when i use polyop.getFaceSmoothGroup it returns an unexpected integer that is different than the actual smoothing group making it hard to easily use that integer for my mat ID.

SG 1 returns 1.
SG 2 returns 2.
SG 3 returns 4.
SG 4 returns 8. and soo on. Anyone have a better way of using this data for mat IDs?

heres my code so far

(
  	--Make sure it is an edit poly or edit mesh.
  	
  	on isEnabled return 
  	(
  		selection.count == 1 and classOf selection[1].baseobject == Editable_Poly
  	)
  	
  	on execute do
  	(
  		
  		--Switch to polygon mode.
  		
  		subobjectlevel = 4
  		
 		--Make sure every poly has a smoothing group. If not return a pop up error screen.
  		
  		base_obj = $.baseobject
  		num_faces = polyop.getNumFaces base_obj
  		notfound = true
  		
  		for i in 1 to num_faces while notfound do
  		(
  			face_SG = polyop.getFaceSmoothGroup base_obj i
  			if face_SG == 0 do
  			(
 				messagebox "Every face must have a smoothing group!"
 				notfound = false	
  			)
  		)
  		
 		--Create a subobject mat with the number of smoothing groups as the number of materials
  		
  		--Step through each material and assign a unique color to the diffuse slot.
  		
 		--Apply a matrial ID to each group of faces in the array based on what smoothing group they have.
  		
  		for i in 1 to num_faces do
  		(
  			face_SGtoID = polyop.getFaceSmoothGroup base_obj i
 			polyop.setFaceMatID base_obj i face_SGtoID	
  		)
  
  
  	)
  )
8 Replies

This is because a single face can be part of multiple smoothing groups…

From the online reference :

polyOp.getFaceSmoothGroup <Poly poly> <int face>
Returns the smoothing group data for the specified face as an integer. The state of each bit in the result specifies whether the face belongs to the corresponding smoothing group.

Here’s a way to find out which smoothing groups a specific face uses:

-- the face to get smoothing groups for
f = 11

-- get smoothing groups for face <f>
sg = polyOp.getFaceSmoothGroup $ f

-- print all smoothing groups for face <f>
for i = 1 to 32 do
	if bit.get sg i then format "Face % is using smoothing group %
" f i

Cheers,
Martijn

Thanks for the quick response. Took me awhile to figure out how to use bit.get in my script but i finally got it. Worked perfectly. Heres how i ended up using it.

(
 	--Make sure it is an edit poly or edit mesh.
 	
 	on isEnabled return 
 	(
 		selection.count == 1 and classOf selection[1].baseobject == Editable_Poly
 	)
 	
 	on execute do
 	(
 		
 		--Switch to polygon mode.
 		
 		subobjectlevel = 4
 		
 		--Make sure every poly has a smoothing group.  If not return a pop up error screen.
 		
 		base_obj = $.baseobject
 		num_faces = polyop.getNumFaces base_obj
 		notfound = true
 		
 		for i in 1 to num_faces while notfound do
 		(
 			face_SG = polyop.getFaceSmoothGroup base_obj i
 			if face_SG == 0 do
 			(
 				messagebox "Every face must have a smoothing group!"
 				notfound = false	
 			)
 		)
 		
 		--Create a subobject mat with the number of smoothing groups as the number of materials
 		
 		--Step through each material and assign a unique color to the diffuse slot.
 		
 		--Apply a matrial ID to each group of faces in the array based on what smoothing group they have.
 
 		for f in 1 to num_faces while notfound do
 		(
 			SG = polyop.getFaceSmoothGroup base_obj f
 			for i = 1 to 32 do
 			(
 				ID = bit.get SG i
 				if ID == true then
 				polyop.setFaceMatID base_obj f i
 			)
 		)
 		
 	deselect
 		
 	)
 )

I hope you don’t mind me commenting on some parts of your script

subobjectlevel = 4

You don’t need to be in subobject mode for the script to work, so this line is not nescessary.

for f in 1 to num_faces while notfound do

Is the “while notfound” part in the second loop supposed to be there? The notfound variable is not used in this loop.

for f in 1 to num_faces while notfound do
(
	SG = polyop.getFaceSmoothGroup base_obj f
	for i = 1 to 32 do
	(
		ID = bit.get SG i
		if ID == true then
			polyop.setFaceMatID base_obj f i
	)
)

Maybe this is how you want it to work, but this loop causes the material ID to be set to the last used smoothing group. So if a face uses smoothing group 1 through 6, it will set the ID to 6.

Cheers,
Martijn

Thank you for your feedback… Im very new to mxs so Im sure im doing something wrong or i have things i shouldnt have.

The “while notfound” in the second loop is there to prevent the script from performing this task if there are any faces that dont have a smoothing group. It was the only way i could prevent an error from happening if there were any faces without sg’s… I we see if your solution will work though. Seems cleaner

Thx!

Ah, I get it

Instead of the “while notfound” in the second loop, you could say:

if notfound then
(
	for f in 1 to num_faces do
	(
		SG = polyop.getFaceSmoothGroup base_obj f
		for i = 1 to 32 where bit.set SG i do polyop.setFaceMatID base_obj f i
	)
)

I’ve also turned the i-loop into a one-liner. Check out the where statement in the online reference.

Ok Im still having a bit of trouble with this script…

When I try to assign a unique name to my sub materials it will not work… It will just repeat the same “01” suffix over on the next one and not continue with “02,03.04…” any idea why this is? Is my script not formmated right for this operation to work?

check towards the bottom… thanks for any help.

(
     --Make sure it is an edit poly or edit mesh.
 	on isEnabled return 
 	(
 		selection.count == 1 and classOf selection[1].baseobject == Editable_Poly
 	)
 	
 	on execute do
 	(
 		rollout shader_name_prompt "Enter Shader Name"
 		(
 			edittext ShaderName ""
 			button create_shader "Create Shaders and ID's"
 			
 			on create_shader pressed do
 			(
 			    --Create a subobject mat with the number of smoothing groups as the number of materials
 				
 				shader = multimaterial numsubs:32
 				meditmaterials[1] = shader
 				shader.name = $.name
 				shader.materialList[1].name = ShaderName.text
 				
 			    --Make sure every poly has a smoothing group.  If not return a pop up error screen.
 				
 				base_obj = $.baseobject
 				num_faces = polyop.getNumFaces base_obj
 				notfound = true
 				
 			    for i in 1 to num_faces while notfound do
 				(
 		    		face_SG = polyop.getFaceSmoothGroup base_obj i
 					if face_SG == 0 do
 					(
 						messagebox "Every face must have a smoothing group!"
 		    			notfound = false	
 					)
 				)
 				
 			    --Apply a matrial ID to each group of faces in the array based on what smoothing group they have.
 		
 				for f in 1 to num_faces while notfound do
 				(
 		    		SG = polyop.getFaceSmoothGroup base_obj f
 					for i = 1 to 32 do
 					(
 		    			ID = bit.get SG i
 						if ID == true then
 		    		    polyop.setFaceMatID base_obj f i
 					)
 				)
 				$.material = shader	--assign material to object
 				
 				--Step through each material and assign a unique color to the diffuse slot.
 
 				for s in 2 to shader.numsubs do
 				(
 		    		shader.materialList[s].name = uniquename (ShaderName.text + ".")
 				)
 				
 				for d in 1 to shader.numsubs do
 				(
 		    		shader.materialList[d].diffuse = (color (random 1 255) (random 1 255) (random 1 255))
 				)
 			)-- end on
 		)-- end rollout
 		createDialog shader_name_prompt 250 50
 	)-- end execute
 )

uniqueName can only be used when creating objects, not materials.
From the online reference:

uniqueName <prefix>

Generates a unique scene node name from a prefix string by adding a series of digits, in the same manner the 3ds max does as you create objects in the scene. This name is only guaranteed to be unique until the next scene node creation.

AFAIK, there’s no uniqueName equivalent for materials. This function might work for you though:

okMtlForScene <material>
Tests the material name against other material names in the scene, and returns true if there are no other materials with the same name, false otherwise. Before assigning material to scene, call this to avoid duplicate names.

Be sure to check the “Material Common Properties, Operators, and Methods” topic in the online reference.

  • Martijn

hmm i never noticed that uniquename was only for objects. The other command will definately help me though. Man I keep missing stuff in the online help

Thanks again.