PDA

View Full Version : Automatic material type conversion


wal9000
06-26-2008, 02:52 PM
I'm trying to come up with a process for taking a scene (from Revit through FBX format) and exporting it to vr4max for display. The main problem is that it's using Arch&Design materials, which vr4max doesn't support. So what I'd like to do is make a script that will go through the scene and convert all the used materials to standard materials with the same diffuse map. I don't particularly care about other aspects of the materials (except perhaps opacity), since vr4max isn't nearly as realistic as a render, but going though every scene and doing this manually is quite time consuming and isn't feasible.

I've never used maxscript before (I do have other scripting experience), and although I'm starting to grasp the basics of maxscript, I still have no idea how to go about this. Can anyone lend me a hand?

Thanks!

EDIT: Using 3ds Max Design 2009, if that matters at all

wal9000
06-27-2008, 12:06 AM
Anyone? I'm thinking the process would involve pulling the diffuse map off of one material, creating a new (standard) one with the same diffuse, then selecting by material and applying the new one. Iterate that through all of the materials in the scene and it's done.

Problem is, I have no idea how to write it. Any help would be greatly appreciated.

As far as I can tell, there's no way to change the type of a material once it's created, but if I'm mistaken there please correct me. That would make this much easier.

Chris
06-27-2008, 02:50 AM
I've got a little script that does it, It works for diffuse and cutout channels, but you could remove the cutout/opacitymap lines if you dont want those:


for i in $ do
(
diff = i.material.mapm0
op = i.material.cutoutmap
mat = standardmaterial()
mat.diffusemap = diff
mat.opacitymap = op
i.material = mat
)

this one transfers just the diffuse map:

for i in $ do
(
diff = i.material.mapm0
mat = standardmaterial()
mat.diffusemap = diff
i.material = mat
)

it works on whatever objects you have selected (it will probably bum out if you have 2 objects with the same material)

vScourge
06-27-2008, 02:55 AM
Here's another take. Works on any Arch materials inside Multi/Sub-Object Materials as well. Runs on all geometry objects in scene, but you could replace "geometry" with "selection" to limit it to that if you wish.


fn convertArchToStandard mat = (
-- Make new Standard mat, with original's diffuse map
newMat = Standard diffuseMap:mat.diffuseMap
newMat.name = mat.name
return newMat
)
-- Loop through all objects, checking material on each
for obj in geometry do (
mat = obj.material
if (mat != undefined) then (
if (classof mat == Multimaterial) then (
-- This is a multi-sub material, so loop through all submaterials
for i in mat.materialIdList do (
submat = mat[i]
if (classof submat == Architectural) then (
mat[i] = convertArchToStandard submat
)
)
) else if (classof mat == Architectural) then (
-- Regular, non-multi material
obj.material = convertArchToStandard mat
)
)
)

Chris
06-27-2008, 04:16 AM
Good idea with the multi-sub loop, I just edited it to work with the mentalray Arch & Design shader rather then the max Architectural

fn convertArchToStandard mat =
(
-- Make new Standard mat, with original's diffuse map
newMat = Standard diffuseMap:mat.mapM0
newMat.name = mat.name
return newMat
)

-- Loop through all objects, checking material on each
for obj in geometry do
(
mat = obj.material

if (mat != undefined) then
(
if (classof mat == Multimaterial) then
(
-- This is a multi-sub material, so loop through all submaterials
for i in mat.materialIdList do
(
submat = mat[i]
if (classof submat == Arch___Design__mi) then
(
mat[i] = convertArchToStandard submat
)
)
)

else if (classof mat == Arch___Design__mi) then
(
-- Regular, non-multi material
obj.material = convertArchToStandard mat

)

)

)

wal9000
06-27-2008, 04:31 PM
Thanks for the help! Unfortunately, I can't seem to make it work. I saved the script and ran it, but the scene materials still list everything as being a ProMaterial. Am I missing something obvious?

vScourge
06-27-2008, 04:37 PM
I don't have 3ds Max Design, so I don't have the exact material type you're converting from. The class name is probably just wrong in the script. Do this:

Select an object that has ProMaterial on it
In the MXS Listener, type "classof $.material"
Replace "Architectural" in the classof if's above with whatever #2 printed out

wal9000
06-27-2008, 04:51 PM
There doesn't seem to be a single type. The countertop (I'm experimenting on a simple kitchen model) gives "Simple_Mtl_Hardwood_adsk", the walls are "Simple_Mtl_Generic_adsk", and the sink is "Simple_Mtl_Metal_adsk". There are a few others that I didn't check.

If this is a problem for identifying which materials are Arch & Design, would it be possible to just convert every material instead?

vScourge
06-27-2008, 05:19 PM
I'm not sure. I think you're into some stuff specific to the Design app. Although the ones you listed look more like material instance names than typical Max material class names.

wal9000
06-27-2008, 05:42 PM
I think it's more specific to the new FBX importer than the design app, although for all I know that's only in max design. How would you do a script that just converts all materials, regardless of what type they are? What effect would the fact they they seem to be instances have?

Once again, sorry for my noobness. I'd barely used Max at all (except some really basic stuff) until this summer.

magicm
06-27-2008, 07:18 PM
I don't have max2009 design so I can't test it with these new materials, but something like this might work:

(
-- Replace 'Architectural' with whichever class you want to convert
local ArchMats = getClassInstances Architectural

-- Locals
local StandardMat, Props, Prop

-- Iterate through all material instances
for ArchMat in ArchMats do
(
-- Create a standard material
StandardMat = standardMaterial name:(ArchMat.name + "_Converted")

-- Collect property names of the original material
Props = getPropNames ArchMat

-- Iterate through property names
for Prop in Props where isProperty StandardMat Prop do
(
try
(
-- Try to set the property on the standard material
setProperty StandardMat Prop (getProperty ArchMat Prop)
)
catch
(
format "Cannot set property % : \"%\".\n" Prop (getCurrentException())
)
)

-- Replace the original material with the new standard material
replaceInstances ArchMat StandardMat
)
)

I just wrote this real quick, it doesn't check anything but simply tries to transfer all properties from the old to the new material. So make sure you save/hold your scene before running the script.

Anyway, replace Architectural (at the first line of the script) with any of the material classes you have and see what it does.

Cheers,
Martijn

wal9000
06-27-2008, 08:17 PM
Hmm. I get "Type error: getClassInstances requires MAXClass, got: undefined" when I replace Architectural with Simple_Mtl_Hardwood_adsk, so perhaps that's not the correct class. Is there another way of finding the class than "classof $.material" as was suggested below?

It's actually not Arch & Design (mi) as I'd thought it was using. The materials all seem to be various ProMaterials, in this case "ProMaterials: Hardwood". There are separate ProMaterial types for glass, wall paint, masonry, plastic, etc. But I have no clue why getClassInstances isn't liking the class that classof gives me for the hardwood.

ZeBoxx2
06-27-2008, 09:02 PM
I get "Type error: getClassInstances requires MAXClass, got: undefined" when I replace Architectural with Simple_Mtl_Hardwood_adsk
Is that -exactly- as used?

The reason I ask is because the class has -two- underscores before 'adsk':

Simple_Mtl_Hardwood_adsk -- incorrect
Simple_Mtl_Hardwood__adsk -- correct



getClassInstances Simple_Mtl_Hardwood__adsk -- should work just fine

magicm
06-27-2008, 09:09 PM
When you execute the following line in the Listener, you should get a list of all the available material classes you have. So the ones you want to change should be in there too:
for m in material.classes do print m
Also, try executing superClassOf $.material (with an object containing the arch material selected). This should return material.

Hmm. I get "Type error: getClassInstances requires MAXClass, got: undefined" when I replace Architectural with Simple_Mtl_Hardwood_adsk, so perhaps that's not the correct class.
I have no idea why classOf $.material would return an invalid class name (evaluating to undefined). As far as I know that's impossible :/ Unless of course, as Richard stated, the class name has a typo ;)

I do know a similar problem arises when working with the bitmap class, but I suspect this is simply because the word "bitmap" could actually mean three different things in mxs, namely an actual bitmap value, a rollout control and a class:
b = bitmap 10 10
BitMap:
c = classOf b
BitMap
getClassInstances c
-- Type error: getClassInstances requires MAXClass, got: BitMap
Martijn

wal9000
06-27-2008, 09:10 PM
Good catch, ZeBoxx! I'm dumb.

New errors now:
Cannot set property #diffuse_color : "-- Unable to convert: Wood-100_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-095_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-096_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-095_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
OK

EDIT: I'm guessing that the Wood-095, Wood-096, and Wood-100 refer to the three different woods used for the countertop, door, and table, but I could be wrong.

magicm
06-27-2008, 09:18 PM
Good catch, ZeBoxx! I'm dumb.

New errors now:
Cannot set property #diffuse_color : "-- Unable to convert: Wood-100_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-095_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-096_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
Cannot set property #diffuse_color : "-- Unable to convert: Wood-095_hardwood_color:Simple Image Map (Bitmap) (adsk) to type: Point3".
OK
Like I said, my script doesn't do any intelligent conversion, it's just a crude attempt at transferring properties from one material type to the other. I don't have 2009/design so I'm afraid I can't be of much help.

Martijn

CGTalk Moderation
06-27-2008, 09:18 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.