マテリアル ID によってマルチマテリアルをソートする方法はありますか。

3ds Max 4 以降、マルチマテリアル内のマテリアル ID をサブマテリアルの順序とは無関係に指定できます。サブマテリアルを追加する長いプロセスを経ると、マテリアル ID が入り乱れていることがあります。特に他人にシーンを引き渡す場合、マテリアル ID でソートすることによってサブマテリアルを昇順に並べ替えることをお勧めします。

次の関数では、MAXScript によって提供されている sort または qsort といった組み込み関数を使用せずに、単純なバブル ソート アルゴリズムによってこの操作を実行します。

バブル ソート アルゴリズムとは、2 つの値を比較してその順序が正しくなければ場所を入れ替える方法です。変更が必要なくなるまでこのプロセスが繰り返されます。このメソッドの名前は、低い値は「表面」に浮かび上がってきて、高い値が「底へ」沈んでいく事象に基づいています。

この関数はフラグ変数を設定し、このフラグが true に設定されるまで while ループが繰り返されます。2 つのマテリアルの場所が入れ替えられたら、必ずフラグは false に設定され、ソートがまだ終了していないことを示します。while ループ内では、for ループがサブマテリアル全体を調べて、隣接するマテリアル ID 値同士を比較します。現在値が次の値より大きければ、ID、各サブマテリアル、名前、および使用可能スイッチの場所を変更する必要があります。

スクリプト:

    fn sortMultiSubById m =
    (
    if classof m == MultiMaterial then--make sure the material is MultiMaterial
    (
     local sorted = false--initialize a local variable as a sort status flag
     while not sorted do--repeat until the flag is set to true
     (
      sorted = true--set the flag to true in the beginning
      --loop though all sub-materials except the last one:
      for i = 1 to m.numsubs-1 do
      (
       --if the MatID of the current sub-material is greater than the next one...
       if m.materialIDList[i] != undefined and m.materialIDList[i+1] and m.materialIDList[i] > m.materialIDList[i+1] do
       (
        --store the current material in a temp. variable
        tmp = m.materialList [i]
        --copy the next material into the current one
        m.materialList [i] = m.materialList[i+1]
        --copy the current material into the next one using the temp var.
        m.materialList[i+1] = tmp
        --do the same with the material IDs
        tmp = m.materialIDList[i]
        m.materialIDList[i] = m.materialIDList[i+1]
        m.materialIDList[i+1] = tmp
        --then copy the states of the enable checkboxes
        tmp = m.mapEnabled[i]
        m.mapEnabled[i] = m.mapEnabled[i+1]
        m.mapEnabled[i+1] = tmp
        --and finally switch the places of the user-defined names.
        tmp = m.names[i]
        m.names[i] = m.names[i+1]
        m.names[i+1] = tmp
        --set the flag to false as we switched places, ergo sorting goes on
        sorted = false
       )--end if
      )--end for
     )--end while
    )--end if
    )--end fn

    -- Sample usage:
    sortMultiSubById $Box001.material