Houdini 19.5 群衆シミュレーション

エージェントプリミティブ

群衆シミュレーションの要員である動く“アクター”であるエージェントについて説明します。

On this page

概要

エージェントプリミティブは一種のパックプリミティブであり、通常では群衆シミュレーションのキャラクタ(エージェント)の表現に使用します。 他のタイプのパックプリミティブと同様に、エージェントプリミティブは単一ポイントを含んでいるので、たいていの状況ではパーティクルとして扱うことができます。

エージェント定義

エージェントプリミティブには、いくつかのデータの参照が記録されており、それらの参照がエージェントのコピー間で共有されていて、 エージェント定義 として参照されることが多いです。 エージェント定義は次のコンポーネントで構成しています: リグ, シェイプライブラリ, 一連のレイヤー, 一連のクリップ, 一連のトランスフォームグループ, オプションのメタデータ。 エージェントの現行レイヤー、トランスフォーム、チャンネル値は、エージェントをアンパックした時に生成されるジオメトリを決定します。

一連のエージェントプリミティブをディスクに保存した時、(パックジオメトリプリミティブと同様に)エージェント定義のコンポーネントもジオメトリファイルに埋め込まれます。 エージェント定義の各コンポーネントを別々にディスクに保存して、エージェントプリミティブから 外部参照 として扱うこともできます。 これによって、例えば群衆シミュレーションからフレームシーケンスを保存する時に大幅に冗長なデータを減らすことができます。 そのような場合では、(パックディスクプリミティブと同様に)エージェント定義のコンポーネント(例えば、シェイプライブラリ)のパスのみがジオメトリファイルに記録されます。 Agent ROPを使用すれば、既存エージェントプリミティブのエージェント定義をディスクに書き出したり、キャラクタリグまたはFBXファイルからエージェント定義を作成することができます。

リグ

リグには、エージェントのトランスフォーム階層(名前の付いたトランスフォームのツリー)とチャンネルが記録されています。 各トランスフォームは、単一の親を持っているか、または階層のルートのどちらかです。 オプションで静止ポーズを指定することができます。これは、例えばジョイントがアニメーションクリップ内に存在しない場合、または、エージェントにポーズやクリップが何も割り当てられていない場合に使用します。 各チャンネルは(チャンネルがアニメーションクリップ内に存在しない時に使用される)デフォルト値を持つことができ、オプションでリグ内のトランスフォームと関連付けることができます。

File Format
VEX Functions
HOM

リグは、JSON形式で記録されています。 階層は、親からその子のリストまでのマップとして表現されており、トランスフォーム名は任意の順番で表わすことができます。

{
    "rig_version": 1,
    "transforms": {
        "root": ["LUpperArm", "RUpperArm"],
        "LUpperArm": ["LLowerArm"],
        "LLowerArm": [],
        "RUpperArm": ["RLowerArm"],
        "RLowerArm": [],
    },
    "channels": {
        "blendshape1": {
            "default_value": 0,
            "transform": ""
        },
        "blendshape2": {
            "default_value": 0,
            "transform": ""
        },
        "RLowerArm.channel1": {
            "default_value": 0,
            "transform": "RLowerArm"
        }
    }
}

以下のVEX関数を使用することで、エージェントのリグに関する情報を照会することができます:

以下のHOMクラスとメソッドを使用することで、エージェントのリグに関する情報を照会したり、エージェントのリグを作成することができます:

シェイプライブラリ

シェイプライブラリには、エージェントで使用可能なジオメトリの集合体(シェイプ)が備わっています。 シェイプライブラリ内の各シェイプは、固有の名前を持ちます。

File Format
HOM

各シェイプはパックプリミティブとして保存されており、namePrimitiveアトリビュートにはシェイプの名前が含まれていて、シェイプのジオメトリはパックプリミティブの中身です。 シェイプライブラリそのものは、通常のgeo/bgeo形式で単一ジオメトリファイルとしてディスクに保存されます。

shapelib_includes文字列配列Detailアトリビュートを使用することで、シェイプライブラリを読み込む時に含めたい追加シェイプライブラリを指定することができます。 このアトリビュートはタプルサイズが2である必要があり、そこには短縮パス(例えば、$HIPまたは$JOBを基準としたパス)とシェイプライブラリファイルの絶対パスのペアを含めます。

以下のHOMクラスとメソッドを使用することで、エージェントのシェイプライブラリに関する情報を照会したり、シェイプライブラリを修正することができます:

レイヤー

レイヤーはエージェントのジオメトリを制御します: エージェントをアンパックした時に、シェイプライブラリからどのシェイプを使用するかどうか、さらにそれらのシェイプをどのようにトランスフォームまたは変形するべきかどうか。

レイヤーは、一連の シェイプバインド で構成されています。これは、シェイプライブラリからシェイプをリグ内のトランスフォームに取り付けます(例えば、“sword_1”というシェイプを“RHand”トランスフォームに取り付けます)。 各シェイプバインドには、そのシェイプの境界ボックスのスケール係数、シェイプをアンパックした時に使用するデフォーマを指定することもできます。 シェイプバインドにデフォーマが指定されていなかった場合、そのシェイプバインドは Static で、そのシェイプは取り付けられているジョイントによってトランスフォームされるだけです。

File Format
VEX Functions
HOM

レイヤーは、静的または変形のシェイプバインドを別々のリストにしてJSON形式で記録されています。

{
    "version": 2,
    "name": "soldier_display",
    "static": [
        {
            "transform": "LLowerArm",
            "shape": "shield",
            "bounds_scale": [1,1,1],
            "deformer": ""
        },
        {
            "transform": "RLowerArm",
            "shape": "sword",
            "bounds_scale": [1,1,1],
            "deformer": ""
        }
    ],
    "deforming": [
        {
            "transform": "",
            "shape": "skin",
            "bounds_scale": [1,1,1],
            "deformer": "linearskinning"
        }
    ]
}

以下のVEX関数を使用することで、エージェントのレイヤーに関する情報を照会したり、エージェントのレイヤーを変更することができます:

以下のHOMクラスとメソッドを使用することで、エージェントのレイヤーに関する情報を照会したり、エージェントのレイヤーを作成または変更することができます:

デフォーマ

シェイプバインドで利用可能なデフォーマタイプがいくつかあります。

スキニング

これらのデフォーマは、Bone Deform SOPSkinning Method オプションに相当します。 シェイプのジオメトリは、静止ポーズになっていて、且つ、ジオメトリがリグ内のトランスフォームによってどのように影響を受けるのかを示したcaptureアトリビュートが含まれている必要があります。 ジオメトリは、それらのcaptureアトリビュートとエージェントの現行トランスフォームに基づいて変形します。

  • linearskinning

    Bone Deform SOPLinear Skinning メソッドに相当します。 これが標準で最も高速なメソッドであり、現在のところ、ビューポートでのGPUスキニングで使用できる唯一のメソッドです。

  • dualquatskinning

    Bone Deform SOPDual Quaternion Skinning メソッドに相当します。

  • dualquatblendskinning

    Bone Deform SOPBlend Dual Quaternion and Linear Skinning メソッドに相当します。 ブレンドアトリビュートの名前は、deformDualQuaternionBlendAttrib Detailアトリビュートで指定します。

ブレンドシェイプ

エージェントのチャンネル値で指定されたウェイトを使って一連の入力シェイプ間をブレンドします。 これは、Blend Shapes SOPによる処理に相当します。

シェイプのジオメトリがベースシェイプとして解釈され、blendshape_shapenames文字列配列Detailアトリビュートによって追加入力(シェイプライブラリ内の別々のシェイプ)を指定します。 blendshape_channels文字列配列Detailアトリビュートには、各ブレンドシェイプ入力で使用する(エージェントのリグで定義されている)チャンネル名を指定します。 エージェントのそれらのチャンネルの値がブレンドシェイプのウェイトとして使用されます。

ポイント番号によるマッチングの代わりに、id Pointアトリビュートを使って異なる入力間のポイントをマッチングさせることができます。 これは、Blend Shapes SOPPoint ID Attribute オプションに相当し、id Pointアトリビュートを使用することで、一部のポイントセットだけを変形させるといった疎らなブレンドシェイプを行なうことができます。 blendshape_ptidattr文字列Detailアトリビュートをベースシェプに追加することで、idのデフォルト値を上書きすることができます。 同様に、blendshape_primidattr文字列Detailアトリビュートを使用することで、 Primitive ID Attribute パラメータ(デフォルトはid)を指定することができます。

blendshape_attribs文字列Detailアトリビュートを使用することで、ブレンドさせるアトリビュートを指定することができます(Blend Shapes SOPAttributes パラメータに相当します)。 デフォルトの挙動では、ポイントポジション(P)と法線(N)だけをブレンドします。

さらに、各ブレンドシェイプ入力は、 中間 シェイプ(補間の挙動を調整できるように特定のウェイトで適用される補正形状)を定義することができます。 中間シェイプは、プライマリシェイプのジオメトリ上のblendshape_shapenames文字列配列Detailアトリビュートで指定します。 そして、blendshape_inbetweenweights 浮動小数点配列Detailアトリビュートには、それぞれの中間シェイプに該当するウェイトを指定します。 中間シェイプは1のウェイト(プライマリシェイプが適用されるウェイト)または0のウェイトを持つことができません。

  • blendshape

    Blend Shapesデフォーマをジオメトリに適用します。

  • blendshape+linearskinning, blendshape+dualquatskinning, blendshape+dualquatblendskinning

    これらのデフォーマは、blendshapeデフォーマの後にスキニングデフォーマのどれかを適用します。

HOM
HDK

カスタムデフォーマは、HDKでGU_AgentShapeDeformerをサブクラス化することで実装することができます。 デフォーマは、GUregisterAgentShapeDeformer()エントリーポイントからGU_AgentLayer::registerDeformer()をコールすることで登録されます。

クリップ

クリップには、エージェントのトランスフォームチャンネル値の駆動に使用することができるアニメーションデータが備わっています。

File Format
VEX Functions
HOM

クリップは、通常の.bclip形式で保存されます。

エージェントのトランスフォームのチャンネルは、ローカル空間で記録され、その名前はtransform_name:channelの形式になっています。channelt[xyz], r[xyz], s[xyz], shear[123]です。

Note

[srt]チャンネルには、各ジョイントの完全なローカルトランスフォームを記述しており、プリトランスフォームがあった場合、ソースアニメーションのオブジェクトの[srt]チャンネルには一致しません。

以下のVEX関数を使用することで、エージェントのクリップに関する情報を照会したり、エージェントのクリップを変更することができます:

以下のHOMクラスとメソッドを使用することで、エージェントのクリップに関する情報を照会したり、エージェントのクリップを作成または変更することができます:

トランスフォームグループ

トランスフォームグループは、エージェントのリグ内のトランスフォームとチャンネルの名前付きサブセットです。 エージェントのスケルトンの部分にクリップを適用する時に、このトランスフォームグループを使用することができます。 0から1までのウェイト値をグループの各トランスフォームに割り当てることもできます。

File Format
VEX Functions
HOM

トランスフォームグループは、JSON書式で保存します。

{
    "version": 2,
    "name": "upper_arms",
    "members": [
        {
            "name": "LUpperArm",
            "weight": 1
        },
        {
            "name": "RUpperArm",
            "weight": 1
        }
    ],
    "channels": [
        {
            "name": "arm_blendshape_L"
        },
        {
            "name": "arm_blendshape_R"
        }
    ]
}

以下のVEX関数を使用することで、エージェントのトランスフォームグループに関する情報を照会することができます:

以下のHOMクラスとメソッドを使用して、トランスフォームグループに関する情報を照会したり、トランスフォームグループを作成することができます:

メタデータ

メタデータを使用することで、エージェント定義内に追加で独自のデータ(例えば、エージェントの構築に使用されたアセットに関する情報)を格納することができます。 これはエージェントのインスタンス間で共有されるので、固有のエージェント定義毎にエージェントプリミティブ上に同じ値を含んだアトリビュートを作成するよりも効率的な代替手段になり得ます。

メタデータは 辞書 として格納され、辞書アトリビュートVEX辞書と同じ挙動をします。 この辞書のキーは必ず文字列で、値には文字列、数値、配列、(入れ子化された)辞書を設定することができます。

File Format
VEX Functions
HOM

メタデータはJSON形式でシリアライズ化します。 オプションで値には、typevalueのキーを含んだオブジェクトとして型情報を明示的に指定することができます。

{
    "my_float": 2.3,
    "my_string": "some_value",
    "my_typed_value": {
        "type": "int",
        "value": 2
    }
}

以下のVEX関数を使用することで、エージェントのメタデータに関する情報を照会することができます:

以下のHOMクラスとメソッドを使用して、エージェントのメタデータに関する情報を照会したり、変更することができます:

エージェント毎のデータ

トランスフォーム

概要
VEX Functions
HOM

各エージェントには、一連の 現行トランスフォーム が記録されています(リグ内の各トランスフォームの4×4マトリックス)。 トランスフォームは、エージェントの現行アニメーションクリップで駆動させたり、手動で制御することもできます。 これらのトランスフォームは、agentworldtransformsagentlocaltransformsのPrimitive Intrinsicsからアクセスすることができます。

他のタイプのパックプリミティブと同様に、エージェントは、自身の位置を決めるための全体的なトランスフォーム(これは、PorientのPointアトリビュートで制御します)も持ちます。

以下のHOMメソッドを使用することで、エージェントのトランスフォームを読み込んだり、修正することができます:

チャンネル値

概要
VEX Functions
HOM

各エージェントには、一連の チャンネル値 (リグ内のチャンネル毎に浮動小数点)が格納されています。 チャンネル値は、エージェントの現行アニメーションクリップで駆動させたり、手動で制御することもできます。

チャンネル値は主にBlend Shapesデフォーマで使用しますが、他のアプリケーション用に利用することもできます。

これらのチャンネル値は、agentchannelvalues Primitive Intrinsicからアクセスすることができます。

以下のVEX関数を使用することで、エージェントのチャンネル値を読み込んだり修正することができます:

以下のHOMメソッドを使用することで、エージェントのチャンネル値を読み込んだり修正することができます:

クリップ

概要
VEX Functions
HOM

各エージェントには、そのエージェント定義からの 現行アニメーションクリップ のリストが格納されています。 クリップのリスト、クリップ時間、ブレンドウェイトは、エージェントに保存されているトランスフォームチャンネル値を駆動させる際に使用されます。 これらのプロパティは、以下のPrimitive Intrinsicからアクセスすることができます:

  • agentclipnames: アニメーションクリップ名のリスト。

  • agentcliptimes: クリップがサンプリングされる時間のリスト。

  • agentclipweights: アニメーションクリップのブレンドウェイトのリスト。これらのウェイトは、ブレンド前に正規化されます。

以下のPrimitive Intrinsicsは、基本のアニメーションブレンドモデルを拡張して、アニメーションクリップのレイヤー化とブレンドができるようにツリー構造を表現します。 各 レイヤー には、ブレンドモード、関連ウェイトを含んだ1つ以上のポーズが入っています。 このレイヤーの出力は、その入力から計算された新しいポーズです。 入力ポーズには、クリップからサンプリングされたポーズ、または、他のレイヤーで生成されたポーズを指定することができます。

  • agentcliptransformgroups: 各クリップで使用するトランスフォームグループの名前を指定します。これは、リグ内のトランスフォームまたはチャンネルのサブセットにクリップを適用する際に使用されます。

  • agentcliplayerids: 各クリップを入力とする(agentcliplayermodesの)レイヤーインデックスを指定します。

  • agentcliplayermodes: 各レイヤーのブレンドモードを指定します(このリストの長さは、階層内のレイヤー数を制御します)。 有効な値は0(デフォルトのinterpolateブレンドモード)と1(additiveブレンドモード)です。 additiveブレンドモードは、入力間を補間するのではなくて、他のクリップの移動と回転の(ブレンドウェイトで制御された)割合を最初の入力クリップに適用します。

  • agentcliplayerweights: 各レイヤーのブレンドウェイトを指定します。agentclipweightsと同様に、これは、レイヤーの出力が他のレイヤーの入力として使われた時に使用されるので、このウェイトは最上位レイヤーには使用されません。

  • agentcliplayerparents: agentcliplayeridsと同様に、レイヤーを入力とするレイヤーインデックスを指定します。最上位レイヤーの親インデックスは-1です。

以下のVEX関数を使用することで、エージェントの現行クリップを読み込んだり、修正することができます:

以下のHOMメソッドを使用することで、エージェントの現行クリップを読み込んだり、修正することができます:

レイヤー

概要
VEX Functions
HOM

各エージェントは、そのエージェント定義からの 現行レイヤー のリストを持ちます。 エージェントをアンパックする時やエージェントをビューポートに表示する時やエージェントをレンダリングする時に使用されるジオメトリは、これらのレイヤーからのシェイプバインドの組み合わせによって指定します。 エージェントに複数のレイヤーを割り当てる単純な方法は、異なるジオメトリセットを組み合わせてバリエーションを作成することです。

さらに、エージェントには複数の Collisionレイヤー を持たせることができます。これらのレイヤーは、エージェントを簡易的に表示させる必要がある時(例えば、Bullet Solverを使ったラグドールシミュレーション)に使用されるジオメトリを定義します。 Collisionレイヤーは、それらが存在すれば、エージェントの境界ボックスを決定する時にも使用されます。

現行レイヤーとコリジョンレイヤーは、agentcurrentlayersagentcollisionlayersのPrimitive Intrinsicsからアクセスすることができます。

以下のVEX関数を使用することで、エージェントの現行レイヤーを読み込んだり、修正することができます:

以下のHOMメソッドを使用することで、エージェントの現行レイヤーを読み込んだり、修正することができます:

境界ボックス

エージェントにCollisionレイヤーがあれば、エージェントの境界ボックスを計算する時に、それらのレイヤーが使用されます。 エージェントに何もCollisionレイヤーがなければ、代わりにエージェントの現行レイヤーが使用されます。 レイヤーの境界ボックスは、そのレイヤーに参照されている各シェイプの境界ボックスを結合することで計算されます。

静的シェイプの場合、そのシェイプの境界ボックスは、そのシェイプバインドの境界スケールで拡張されてから、そのシェイプとバインドされているジョイントに応じてトランスフォームされます。 変形シェイプの場合、そのシェイプの境界ボックスは、Capture Weightに参照されているジョイントの位置から計算されてから、そのシェイプバインドの境界スケールで拡張されます。

See also

群衆シミュレーション

はじめよう

  • 基本

    Houdiniにおける群衆シミュレーションの考え方の概要を説明します。

  • セットアップ

    群衆シミュレーションのセットアップと編集の方法

動くパーツ

  • エージェント

    群衆シミュレーションの要員である動くアクターであるエージェントについて説明します。

  • ステート

    各エージェントのアニメーションや仕草を制御する仮想的な雰囲気。

  • トリガー

    エージェントの状態を変更する条件を指定する方法です。

  • キャッシュ

    群衆シミュレーションの効率的なキャッシュ化と読み込みのTips。

挙動

外観

  • 多様性

    エージェントに異なる外観と行動を作成することで、より現実的な群衆を作成する方法。

  • 布の取り付け

    Vellum Clothをエージェントシェイプジオメトリの一部として追加/拘束すれば、エージェントの動きに基づいて布をシミュレーションすることができます。

地形

  • 足の着地

    エージェントのアニメーションを地形に適応させて滑りを回避するためのセットアップ方法。

  • 地形

    エージェントが歩く地形ジオメトリを指定する方法です。

  • 障害物

    エージェントが回避する障害物を設定する方法です。