マテリアルのサブ要素を再帰的に取得する

投稿者: | 2016/09/23

今回はマテリアルのサブ要素(マテリアル、テクスチャ)の取得について。

マテリアルは要素の下に別の要素が入れ子式に接続される、いわゆるツリー構造を持っています。
こういった構造では、再起処理を使って全ての要素を巡回して取得する事が可能です。

以下は指定マテリアル下の全てのサブ要素を取得する関数です。

fn getAllSubItemsFromMtl mtl _subs:#() =
(
    if mtl != undefined and (appendIfUnique _subs mtl) do
    (
        if (superclassof mtl) == material do
        (
            for i = 1 to (getNumSubMtls mtl) do
                getAllSubItemsFromMtl (getSubMtl mtl i) _subs:_subs
        )

        for i = 1 to (getNumSubTexmaps mtl) do
            getAllSubItemsFromMtl (getSubTexmap mtl i) _subs:_subs
    )
    _subs
)

引数

mtl
サブ要素を取得するマテリアルオブジェクト。
_subs:
内部使用限定なので基本的には使用しないでください。

使用サンプル

-- 選択オブジェクトのマテリアルを引数に指定
getAllSubItemsFromMtl $.material

これで該当マテリアルの全てのサブ要素を、配列として取得する事ができます。

ただし、取得されるサブ要素は、マテリアルとテクスチャが混ざった状態で取得されてしまいます。
関数内でどちらかのみを取得するような書き方も出来ますが、「マテリアルの下にあるマテリアルの下にあるテクスチャ」のようなケースで取得が難しくなってしまうので、今回はまとめて取得しています。

実際に使用する時は、取得後に必要な要素だけをフィルタリングする感じでいいかと思います。

-- マテリアルとテクスチャマップを分類
subItems = getAllSubItemsFromMtl $.material
mtls = #()
maps = #()
for s in subItems do
(
    if (superclassof s) == material then
        append mtls s
    else
        append maps s
)

-- collectを使ってマテリアルだけを抽出
subItems = getAllSubItemsFromMtl $.material
mtls = for s in subItems where (superclassof s) == material collect s

コメントを残す

メールアドレスが公開されることはありません。