2012年4月23日月曜日

MAXScript マテリアル毎にノードをまとめる

FBXをインポートしてみたら、ノード数が多いので

sceneMaterialsを使って、マテリアル毎にまとめるテスト

MergeNodeTest.ms

g_NodeNameArray = #() -- シーン中のノード名の配列

-- 再帰関数でノードを列挙する
fn EnumNode n =
(
  for n in n.children do
  (
    -- 配列にノード名を追加
    append g_NodeNameArray n.name
    -- 再帰処理
    EnumNode n
  )
)

-- 文字列の配列から一致する文字列のインデックスを取得
fn GetNameIndex strArray str = (
  for i = 1 to strArray.count do (
    if strArray[i] == str do (  
      return i
    )
  )
  -1  -- 一致する文字列が無い
)

-- マテリアル毎にノードをまとめるテスト
fn MergeNodePerStdMtl = (
  -- シーン内のノード数
  format "Scene Node Num = %\n" g_NodeNameArray.count
  
  -- シーン内のマテリアル数を出力
  format "sceneMaterials.count %\n" sceneMaterials.count
  
  -- シーン内のスタンダードマテリアル名の配列
  strStdMtlNameArray = #()
  
  for mtl in sceneMaterials do (
    -- マテリアルのクラス名を取得
    c = classof mtl
--    format "mtl.name = % class = %\n" mtl.name c

    if c == Standardmaterial do (
      -- スタンダードなマテリアル名を追加
      append strStdMtlNameArray mtl.name  
    )
    
    if c == Multimaterial do (
      nSubMtl = getNumSubMtls mtl
--      format "nSubMtl = %\n" nSubMtl    -- サブマテリアル数
    )
  )
  
  -- strStdMtlNameArrayが空なので抜ける
  if strStdMtlNameArray.count == 0 do return 1

  -- スタンダードマテリアルを使用するノードの配列を作成
  stdMtlNodeArray = #()
  stdMtlNodeArray.count = strStdMtlNameArray.count
  
  -- シーン内のノードをスタンダードマテリアル毎にマージする
  for i = 1 to g_NodeNameArray.count do (
    -- ノードを名前から取得
    n = getNodeByName g_NodeNameArray[i]
    if undefined == n do continue
    
    -- ノードのマテリアルを取得
    mtl = n.material
    if undefined == mtl do continue
    
    c = classof mtl -- マテリアルのクラス
    if c == Standardmaterial do (
      -- 配列のインデックスを取得
      idx = GetNameIndex strStdMtlNameArray mtl.name
      if -1 == idx do continue
      
      if undefined == stdMtlNodeArray[ idx ] then (
        -- 空なので、ノードをセット
        stdMtlNodeArray[idx] = n
      )
      else (
        -- ノードをマージする
        stdMtlNodeArray[idx] = stdMtlNodeArray[idx] + n
        -- マージしたノードは削除
        delete n
      )
    )
  )
)

rn = rootNode       -- ルートノードを取得する
EnumNode rn         -- シーン内のノードを列挙
MergeNodePerStdMtl()  -- スタンダードなマテリアル毎にノードをマージ