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

投稿者: | 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

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

ただし、取得されるサブ要素は、マテリアルとテクスチャが混ざった状態で取得されてしまいます。
関数内でどちらかのみ取得する事も出来ますが、今回は両方同時に取得しています。理由として、テクスチャのみを取得しようとした時に、「マテリアルの子マテリアルのテクスチャ」の様なケースで処理が複雑になってしまう為です。説明の為に極力シンプルにしています。

以下は取得後にマテリアルとテクスチャを分離しています。

-- マテリアルのサブ要素を取得
subs = getAllSubItemsFromMtl $.material

-- マテリアルを抽出
mtls = for s in subs where (superClassOf s) == material collect s

-- テクスチャを抽出
maps = for s in subs where (superClassOf s) != material collect s

2018/09/03: マテリアルとテクスチャの抽出をcollectに変更。
for文の中で個別にappendするよりも、1つの処理を1つのループに纏める方が今風らしいです。

コメントを残す

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