マテリアル・マップ
3ds Max Python チートシート の章一覧
マテリアルもマップも クラスを呼んで作り、プロパティに入れる だけです。
3ds Max 2022 の既定は フィジカルマテリアル(PhysicalMaterial)なので、本章もこれを中心にします。
マテリアルを作って割り当てる
m = rt.PhysicalMaterial(name="MyRed", base_color=rt.Color(200, 30, 30), roughness=0.4)
# MXS: m = PhysicalMaterial name:"MyRed" base_color:(color 200 30 30) roughness:0.4
b = rt.getNodeByName("Box001")
b.material = m # MXS: b.material = m
for o in rt.selection: # 選択にまとめて割り当て
o.material = m
rt.getNodeByName("Sphere001").material = None # 割り当てを外す(MXS: $Sphere001.material = undefined)
- 同じマテリアルを複数のノードに入れると 共有 されます(パラメータを変えるとそのマテリアルを持つすべてのノードに反映)。別々にしたいときは
rt.copy(m)したものを入れます。 - 旧来のスタンダードマテリアルは
rt.StandardMaterial(diffuse=rt.Color(...))です。プロパティ名がマテリアルの種類ごとに違う点に注意します。
マップ(テクスチャ)を差し込む
import os
tex_path = os.path.join(rt.getDir(rt.Name("maxroot")), "maps", "uvwunwrap", "UV_Checker.png") # UV_Checker.png は 3ds Max に同梱の画像
bmp = rt.Bitmaptexture(fileName=tex_path, name="Checker_Tex") # MXS: bitmapTexture fileName:"..."
m = rt.PhysicalMaterial(name="Textured")
m.base_color_map = bmp # ベースカラーに差す(MXS: m.base_color_map = bmp)
m.bump_map = rt.Noise(size=5) # バンプにノイズ
m.bump_map_amt = 0.5
rt.showTextureMap(m, True) # ビューポートにテクスチャを表示(MXS: showTextureMap m on)
rt.redrawViews() # 表示直後は反映されないことがあるため明示的に再描画する
rt.getNodeByName("Box001").material = m
- スタンダードマテリアルなら
m.diffuseMap = bmpです。どのスロットがどんな名前かはrt.getPropNames(m)で確かめます。 - タイリングなどの UV 設定はマップの
coordsの中にあります。pymxs では入れ子になったプロパティへの代入がそのまま効かないことがあるため、bmp.coords.U_Tiling = 2ではなくbmp.setmxsprop("coords.U_Tiling", 2)と書くと確実です。
マテリアルエディタに入れる / 開く
m = rt.PhysicalMaterial(name="Slot1Mat")
rt.setMeditMaterial(1, m) # スロット 1 に入れる(番号は 1 始まり)
rt.meditMaterials[0] # 添字で読むと 0 始まり(同じスロット 1)
rt.MatEditor.mode = rt.Name("basic") # コンパクトエディタに切り替え(rt.Name("advanced") でスレート)
# rt.MatEditor.open() # エディタを開く
- 同じスロットを 関数では 1、添字では 0 で指します。混ぜるとずれるので気を付けます。
マルチ/サブオブジェクトマテリアル
mm = rt.Multimaterial(numsubs=3, name="MyMulti") # MXS: multimaterial numsubs:3
colors = [rt.Color(200, 40, 40), rt.Color(40, 200, 40), rt.Color(40, 40, 200)]
for i, c in enumerate(colors, start=1):
rt.setSubMtl(mm, i, rt.PhysicalMaterial(base_color=c)) # サブマテリアルを設定(番号は 1 始まり)
subs = list(mm.materialList) # サブマテリアルの一覧
ids = list(mm.materialIDList) # それぞれのマテリアル ID
b = rt.getNodeByName("Box001")
rt.convertToPoly(b)
b.material = mm
rt.polyop.setFaceMatID(b, [1, 2], 2) # 面 1・2 を ID 2 にする
- サブマテリアルの「番号(スロット順)」と「マテリアル ID」は別物です。面に割り当てるのは ID の方で、既定では 1, 2, 3… と並びます。
シーンのマテリアルを集める
for o in rt.objects: # 準備: 各オブジェクトに別々のマテリアルを割り当てる
o.material = rt.PhysicalMaterial(name="Mat_" + o.name)
used = []
for o in rt.objects: # ノードに割り当てられているマテリアル
if o.material is not None and o.material not in used: # `in` は == で比べるので重複を除ける
used.append(o.material)
names = sorted(m.name for m in used) # 使われているマテリアル名の一覧
all_physical = list(rt.getClassInstances(rt.PhysicalMaterial)) # シーン全体の PhysicalMaterial インスタンス一覧
by_mat = {} # マテリアル名 -> ノード名のリスト
for o in rt.objects: # マテリアルごとにノードをまとめる
if o.material is not None:
by_mat.setdefault(o.material.name, []).append(o.name)
rt.sceneMaterialsでもシーンのマテリアルを取れますが、更新のタイミングによって最新でないことがあります。rt.UpdateSceneMaterialLib()を呼ぶと強制的に更新できます。ノードから集めるのが確実です。getClassInstancesはマップにも使えます(次の項目)。targetを省くとマテリアル エディタのスロットに入っているだけのマテリアルも対象になります。ノードの階層だけに絞りたいときはtarget=rt.rootNodeを指定します。
テクスチャのパスを調べる / 付け替える
import os
rt.getNodeByName("Box001").material = rt.PhysicalMaterial(
base_color_map=rt.Bitmaptexture(fileName=r"D:\old_project\maps\wood.png")) # 準備: 見つからないパス
missing = []
for bmp in rt.getClassInstances(rt.Bitmaptexture): # シーンの全ビットマップ(エディタのスロット内も含む)
path = bmp.fileName
if path and not os.path.exists(path):
missing.append(path)
new_dir = rt.getDir(rt.Name("image")) # 付け替え先のフォルダ(例。実際は移動先のフォルダを指定する)
for bmp in rt.getClassInstances(rt.Bitmaptexture):
if bmp.fileName in missing:
bmp.fileName = os.path.join(new_dir, os.path.basename(bmp.fileName))
- パスの存在確認や分解には Python の
os.path(またはpathlib)が使えます。 - ビットマップのファイル名一覧だけでよければ
rt.usedMaps()が最短です(ただしマテリアル エディタのスロットの中だけにあるマップは含まれません)。 - テクスチャ以外の外部ファイル(IES・プロキシなど)も含めて一覧したいときは
rt.AssetManager(→「ファイル・データ」章)を使います。
落とし穴まとめ
- 同じマテリアルを入れると共有される。別々にするなら
rt.copy(m)。 - マテリアルの種類ごとにプロパティ名が違う(
base_color_map/diffuseMapなど)。 - マテリアルエディタのスロットは、関数では 1 始まり、添字では 0 始まり。
- サブマテリアルの番号とマテリアル ID は別物。
関連
- 面のマテリアル ID を面ごとに扱う: 「メッシュ・ポリゴン」章
- 外部ファイルの一覧: 「ファイル・データ」章
コメント