[Closed] References and material ID's
hi,
i’m trying to set material id’s on a lot of meshes, problem is that some objects are references (instancing is needed) and setFaceMatID “cannot change mesh with modifiers present.”
is there a way to remove the reference, but keep the instancing so that new material ID’s to be set by maxscript?
- make all references(instances) unique
- create new base object
- in loop for every node that should be instanced collect modifiers in a buffer, delete modifiers, replace reference, apply modifiers from the buffer.
there is an easier way:
- create new base object and apply it to instanced one
should_be_instanced_node.baseobject = new_base_object - delete base object
call lines of this sample line by line:
-- delete objects
-- create two boxes
a = box name:"base" pos:[0,0,0]
b = box name:"refs" pos:[0,0,25]
-- add modifiers to box A
addmodifier a (Edit_Poly())
addmodifier a (Edit_Normals())
-- make box B reference of box A
if not areNodesInstances a b do referencereplace b a
addmodifier b (materialModifier materialID:3 name:"mat_id")
-- it adds modifier as was expected to box B only because b reference of A (not instance)
addmodifier a (materialModifier materialID:3 name:"mat_id")
-- it adds modifier to both boxes A and B because b reference of A and A is not reference of B
-- delete added material modifiers (revert two steps back):
deletemodifier a a.mat_id
deletemodifier b b.mat_id
-- now make boxes instances:
-- to synch the adding modifiers to both objects we have to make them insatnces (not references):
ref_nodes = #()
InstanceMgr.GetInstances a &ref_nodes
-- ref_nodes contains all references and instances of a
for n in ref_nodes where not areNodesInstances n a do instancereplace n a
-- now all objects in ref_nodes are instances
addmodifier a (materialModifier materialID:3 name:"mat_id")
-- it adds same modifier to both boxes A and B because they are instances
fn replaceReferenceWithInstance nodes: =
(
if nodes == unsupplied do nodes = objects as array
while nodes.count > 0 do
(
list = #()
node = nodes[1]
InstanceMgr.GetInstances node &list
if list.count > 1 do
(
for n in list where not areNodesInstances n node do instancereplace n node
)
for n in list where (k = finditem nodes n) != 0 do deleteitem nodes k
)
)
-- replace all references with instance
replaceReferenceWithInstance()
somehow, manually selecting everything, adding a modifier and deleting it again gets rid of references but keeps instancing, which is what i want, but i can’t seem to do this in maxscript?
addModifier obj (materialModifier materialID:1 name:"MaterialMod")
deleteModifier obj 1
setFaceIDs obj
thanks for the tips denis, but i don’t think i can create new base objects and references. or maybe i’m not following you completely, maxscript is definately not my strongest side
the models can be huge, with hundreds of nuts and bolts etc. and i do not know which objects are actually references or base objects.
where is the difference between a manual add/delete modifier and doing it with maxscript? do i need some kind of delay/update/refresh/redraw?
probably i don’t understand your problem. You have some mesh instanced objects, and you want to have unique modifiers for those objects. That means the objects have to be references (not instances).
to get all instances you can use InstanceMgr interface (.GetInstances). to check is nodes are instances you can use areNodesInstances method.
sorry, i might be complicating things, basically i wanted to convert a reference to an instance, so that i can use setFaceMatID.
manually this works when adding and removing a modifier from the stack, but in maxscript there’s something weird going on.
if there was a way to tell setFaceMatID to target the lowest index modifier in the stack (base object?), that would be an even better solution, but i don’t know if that is possible
mmm, oookeeey, if i run my script twice or more (adding and deleting modifiers), setID will work, but it is ofcourse taking ages
my friend, this will be a good day at work! checking this out now, i’ll learn a lot from this, thank you!
wow, the speed! your script is brilliant and lightning fast!
the issue is still the same though, even though all references looks to be effectively converted, maxscript still throws this when trying to set ID :
-- Runtime error: Cannot change mesh with modifiers present: Editable Mesh
i’m using this code (yours with setID function added) :
fn replaceReferenceWithInstance nodes: =
(
if nodes == unsupplied do nodes = objects as array
while nodes.count > 0 do
(
list = #()
node = nodes[1]
InstanceMgr.GetInstances node &list
if list.count > 1 do
(
for n in list where not areNodesInstances n node do instancereplace n node
)
for n in list where (k = finditem nodes n) != 0 do deleteitem nodes k
)
)
-- replace all references with instance
replaceReferenceWithInstance()
fn setIDs nodes: =
(
if nodes == unsupplied do nodes = objects as array
for n in nodes do
(
isEditableMesh = isKindOf n Editable_Mesh
if isEditableMesh then
(
for i=1 to n.numfaces do setFaceMatID n i 9
)
)
)
setIDs()
it is driving me insane. if you run the above script on this scene http://www.kimgar.com/files/testScene2.zip the runtime kicks in…
to set material id for all faces of geometry you can add material modifier with this ID. YOU CAN’T change mesh properties with modifiers present as system says.
this is when it gets weird, there is definately no modifiers present. running your script replacing references, and mine slowly adding and deleting a modifier killing references, double checking stack for modifiers, <modifierarray>.count = 0, still, max insist there is something in the stack, and refuses to change ID’s…