Houdini 基本を掘り下げる

ひと通り公式の基礎チュートリアルが終わったので、ヘルプ参照したり、ググりつつ基本を固めたい。

間違いを発見した時、遠慮なく突っ込んでいただけると喜びます。

用語

・コンテキスト

処理を行う状況や分野のこと。
ModelingやAnimationなど、処理を行う分野が分かれており、内部に作れるノードの種類も変わる。

20140504_01_0

・ch

信号処理を行う
主に扱うネットワークタイプは CHOP

・CHOP
Channel Operators
音声データや関数の組み合わせから波形を組み立てて、任意のパラメータに出力できる。

・obj

モデル、ライト、カメラなどシーンを構成するオブジェクトを処理する
主に扱うネットワークタイプは SOP/VOPなど

・SOP

Surface Operators
Surfaceオペレーションを行うノードのことを一括りにSOPノードなどと呼ぶようだ。(PolyExtrude SOPなどという書き方をよく見かける)
SOPに関しては、コンテキストの一種とは言い難いと思う。

・COP

Composite Operator
色調補正や画像合成を行える。

・DOP

Dynamics Operator
物理演算

・out

レンダリング画像やモデル、画像合成の結果などを出力する
主に扱うネットワークタイプは ROP

・ROP

Render Operator
レンダリング処理

・part

パーティクルの振る舞いを出力する
主に扱うネットワークタイプはPOP

・POP

Particle Operator
パーティクル処理

・shop

シェーディングに関する出力を行う
主に扱うネットワークタイプはSHOP

・SHOP

Shading Operator
カスタムシェーダの作成や3Dテクスチャの生成ができる

・vex

・VOP

VEX Operation
カスタムノード処理

ノードにコンテキスト名をつけて括る理由

例えばGroupノードは、同じ名前でSOP、DOP、VOPなど複数のネットワーク内で作成、使用できるが、所属するネットワークのコンテキストタイプに応じて全く別の働きを持つ。
そのため、どのコンテキストに属しているか明示する意味合いもあるのだろう。

パラメータに関して

Attributeとは

各コンポーネントが持つ固有の値のこと。
コンポーネントとは、Point/Vertex/Primitiveなどのオブジェクトを構成する要素のこと。

GeometryのPointが持つ[P]AttributeはPointの座標を表す。
ParticleのPointならVelocityなども持つ。

Attributeを追加する

Pointにアトリビュートを追加するには、Pointを持つノードの下流にPointノードを接続し、各種Attributeの動作を Add ATTRIBUTE_NAME に変更する。

同様に、Vertexノード、Primitiveノードを接続することで、それぞれに対応するAttributeを追加することができる。
※これらのノードを通った時に通ったデータが持っている情報から、Addした各Attributeを計算し下流で使えるように有効化するという方があってる気がする。

20140504_01_1

各コンポーネントのAttributeの値は、Details Viewで確認できる。
簡易的な内容は、ノードを中ボタンクリックで表示できるポップアップウインドウでも確認できる。

Expression

各種パラメータボックスには、直接計算式を記入することができる。
これは数値型のパラメータにかぎらず、例えばファイルパスなどを格納する文字列パラメータでも同じ。

変数

Expressionには変数名を記入することができる。
例えば、$FF(浮動小数点型のフレームナンバー)など。
この変数名は、そのまま計算に用いることができる。
$FF + 1 などとしてもよい。

どのような変数が使えるかは、Houdini Helpで調べると良い。

Global Expression Variables

Standard Variables

・Local Variables

例・xformノードのLocal Variables

いつ、どの変数が使えるのか?

Standard Variables にリストアップされている変数の中に、特定のノード内で使えるものとそうでないものがあるという、一見して不思議な動作を考察。

変数が見つからず、Expressionが正しく評価できない場合、ノードアイコンが赤い斜線で装飾される。

20140504_01_3

この状態でノード上にカーソルを置き、中ボタンを押すと以下のエラーが確認できる。(下図は別のノードで表示したものなので、パスが違うが)

20140504_01_2

調べた限り、ある変数名が任意のノード中で使えるかどうかを判断するのは、試行錯誤による判断が必要という意見がよく見つかるように思えた。

・対処法 NodeごとのLocal Variablesを使用する

確実に使える変数は、Helpで各ノードの項に記載されているLocal Variables のようだ。ただし、ここに記載されていない変数も使用できるケースが有るのでややこしい。

・対処法 Point/Vertex/Primitive SOPノードを経由させる

また、Point/Vertex/Primitive SOPノードを経由することで作成される変数は、下流で確実に使える状態になっているので、まずはこれらのノードを使用し明示的に変数を作成したあとで、下流で使用する。

・対処法 AttribCreate SOPを使用する

対処法として挙げられていたのは、下流で必要な値を取得したい場合は、予めAttribCreate SOPを使用して任意の値を明示的にAttributeの形で保持し、下流で使用する。

オペレータへ入力するデータの型について

オペレータが操作する対象の型に対し、処理対象として入力するデータの型が適合しているか明確に意識する必要がある。

例えば、Poly ExtrudeなどはPrimitive型のデータを元に処理されるので、Primitive型のデータを入力しなければ正しく処理は行われない。
※GUI上から頂点選択後にPoly Extrudeを実行したとき正しく動作しているようにみえるのは、実行時に選択されている頂点を包含するPrimithiveリストが自動的に割り出され、Poly ExtrudeノードのGroupパラメータに与えられるからである。

同様に、Poly BevelはPointに対する処理を行う。

よって、Groupノードによる下流オペレータへ渡すコンポーネントのフィルタ処理は、渡したいコンポーネントの型を元にフィルタするのが望ましい。

オペレータから出力されるデータの型について

オペレータへの入力が要件を満たしている場合は何事も無く処理後のデータが出力される。

例えば、Polygon Geometryを編集するノードからの出力は、特に出力データタイプを指定できるノードでない限り、Polygon Geometryデータが出力される。

※入力が要件を満たしておらず、ノードのステータスがWariningであれば入力されたデータは何も手を加えることなく下流のノードへ渡されるようだ。

20140504_01_4

ExpressionからAttributeを参照する

参照したいAttributeを保持するコンポーネントの型に応じて、それぞれ以下の関数を使う。

・Point

float point (string surface_node, float point_number, string attribute, float index)

・Vertex

float vertex (string surface_node, float primitive_number, float vertex_number, string attribute, float index)

・Primitive

float prim (string surface_node, float prim_num, string attrib_name, float attrib_index)

・Detail

float detail (string surface_node, string attrib_name, float attrib_index)

Numeric配列型Attribute

AttribCreateを使用すれば、複数の数値を保持する配列型のAttributeを作成することができる。

また、この配列型の値を使用する際、インデックスに応じて以下のように指定する。

  • $varName1
  • $varName2
  • $varName3
  • $varName4

Numeric配列とVector型

・Numeric型

・Vector型

Attributeの可視化

ビューポート上で任意のAttributeの状態を可視化できる。

Display OptionsのMarkersタブから下記のボタンを押してCustom Attributeを追加する。
20140504_01_5

左から順にGeneric/Text/Vector/Scene

上図のボタンを押すと、下図のようなウインドウが現れる。

20140504_01_8

おそらく、Nameはスクリプトなどから呼び出す際のオプション名

・Generic

A generic option is intended to work with primitive render hooks, created through the HDK. It passes an enable/disable value along with a single string argument to any render hook that looks for it. It can be toggled on in one display geometry context (like Display Model) but left off in another (Ghost Scene Object).

・Text

文字で値を表示する。
これは、数値も文字列として表示される。

20140504_01_7

・Vector

ベクトルを線で表示

20140504_01_6

・Scene

A scene option is intended to work with scene render hooks, created through the HDK. Scene hooks can query the enable state of any scene display option. Unlike generic display options, a scene option is global and is not affected by the geometry context.

Attributeの所属クラス変換と全要素を使用する計算

AttribPromoteノードを使用して、任意のAttributeを、別のクラスのAttributeに変換できる。

同時に、Attributeに含まれるすべての値から平均値や最小値、最大値、などいくつかの用意された条件にマッチする値を抜き出すこともできる。

20140504_01_9

・Original Name

検索したいAttribute名

・Original Class

変換元のAttributeが所属しているクラス

・New Class

変換先のクラス

・Promotion Method

Attributeの値をどのように計算して変換先に格納するかを指定

・Change New Name / New Name

変換先のAttribute名を指定し、新規作成する。

・Delete Original

変換元アトリビュートを削除するか決定する。

Attributeを別のノードにコピーする

AttribCopyノードを使って、任意のAttributeを写しこむ。
Attributeのコピーは、各コンポーネントのインデックスがマッチするもの同士で行われる。

20140504_01_10

パラメータ設定はだいたい見たとおり。

・Source/Destination Group 

未記入ならオブジェクト全体の指定クラスからコピー元となるオブジェクトセットを探す。

・Source/Destination Group Type

未記入ならオブジェクト全体の指定クラスからコピー先となるオブジェクトセットを探す。

・Match by Attribute / Attribute Match

コピー元と先に指定した名前のAttributeがある場合にアトリビュート値のコピーを行う。

・Attribute Name

コピーするAttribute名を指定

・Match P Attribute

ポイントのポジションである[P] Attributeの値も強制的にコピーするか指定

・Attribute Class

どのクラスのデータをコピーするか指定する。

・Copy Local Variable

ローカル変数名もまとめてコピーし、下流で使えるようにするか決定する。

Attributeを転送する

AttribTransferノードを使い、距離を元にAttributeを転送できる。

・Attributesタブ

20140504_01_11

一様に転送するAttributeの指定ができる。

・Conditionsタブ

20140504_01_12

距離に応じた転送が行える。

各パラメータの詳細は後日記載する

Particles I&II&III

https://vimeo.com/8447016
https://vimeo.com/8447185
https://vimeo.com/8447373

Partコンテキスト

パーティクル操作のためのコンテキスト。
これを使わなくてもobjコンテキスト内ではパーティクルが作れた。

Partコンテキストを使うことでどんな利点があるのか気になる。

Location (POP)ノード

ポイントエミッタ

基本的なパラメータはpopnet-oldなどと同じ。

・Birth Groupパラメータ

生成されるパーティクルが格納されるグループ名

・Preserve Groupパラメータ

上流で作られたグループを保持し、このノードで作られるグループをフローに追加する。

・Velocityパラメータ(Attributes)

初速方向の決定

・Varianceパラメータ(Attributes)

初速のランダムベクトル。
±入力されたベクトルの範囲でランダム化される。

Position(POP)ノード

Velocity (POP)ノード

パーティクルの速度を変更するオペレータ
Velocity TypeをVectorにし、パラメータを

vector3($VX, $VY, $VZ) * 0.9

などとすると毎評価ごとに速度が0.9倍され減速するパーティクルが作れる

Acceleration (POP)ノード

Split (POP)ノード

パーティクルからパーティクルを発生させる。
これを使用して、任意のパーティクルから速度を持たないパーティクルを発生させれば、パーティクルの軌跡が作成できる。

Follow (POP)ノード

パーティクルをパーティクルに追従させる。

Source Groupで引き付けられる側のパーティクルグループを指定
Leaderタブ、Leader Groupで引きつける側のパーティクルグループを指定

引きつけの速度などはFollowタブで設定。
Stop At Leaderをオンにしておくと、追従後にパーティクルはストップする

Collision (POP)ノード

任意ノードとパーティクルのCollisionを検知できる。

Collosion Eventパラメータには、このCollisionが有効になった際に発生するCollisionイベントの名前を記入する。

このイベント名は、後で以下の関数などで使う。

popevent( “EVENT_NAME” )

この関数に与えられた名前を持つEventが発生した時、関数はTrueを返す。なので、別のSourceノードのImpulse Activationなどに仕込めば、Collisionイベント発生時にのみパーティクルを発生させるような事が可能。

Collect (POP)ノード

パーティクル版のmergeノード

Curl-Noise(POP)ノード

パーティクルにNoiseを与える。
Noiseの影響はUpdateタブでAdvection Typeから指定。
ポジションや速度、外力として与えるなど、様々な選択ができる。

popnet-oldオペレータ

Over Samplingを上げると、Constタイプで時間に対しスムースに作成されるパーティクルの間隔がスムースになる。

パーティクルの外観

20140503_01_0

・Sprite(POP)ノード

スプライトを設定
同じように操作しているつもりだけど、何故かうまくスプライトの割り当てができない。

20140503_01_1

 

バージョン違いによる差異だろうか。

チュートリアルでは、一度popnetに対してスプライトを当ててから、別のパーティクルに当て直しているように見えるこの手順は一旦スキップする。

・Instance(POP)オペレータ

オブジェクトインスタンス

・Render(POP)オペレータ

パーティクルをそのままレンダリングする際の見た目を決定する

Color(POP)オペレータ

パーティクルのカラーや透明度を指定する

Property(POP)オペレータ

任意のタイミングで、任意のアトリビュートを操作できる。

Trails Effect Tutorial

https://vimeo.com/5891547
https://vimeo.com/5891661

ボックスから発生するトレイルエフェクトチュートリアル

1・以下の3つを作成

・motionPath_curve
エミッターとなるボックスが沿うモーションパスカーブオブジェクト

・trail_emitter
エミッターとなるボックスオブジェクト

・trail_lines
トレイルエフェクトオブジェクトが入るGeometryノード

20140502_01_0

2・モーションパスにボックスを沿わせて動かす

trail_emitterのPath ObjectにmotionPath_curveを指定
Positionにスタートフレームで0、エンドフレームで1となるようにキーを打つ。
これで時間を動かすと、カーブに沿ってボックスが動くようになる。

20140502_01_1

3・Trailノードを使ってボックスの頂点の軌跡を取り出す

※この時、trail_emitter内のboxノードに直接Trailノードをコネクトしても、trail_emitter内に存在するbox自体は、ローカルな空間内では動いていないので軌跡が作成されない。
グローバル空間での動きを元にTrailを作成する必要がある。

trail_linesの中にObject Mergeノードを作成する。
このノードは、パスを指定してどこからでもジオメトリデータを取得できる。パラメータリストの下部で呼び込みたいオブジェクトのパスを指定する。

20140502_01_3

Transform情報はbox自身の移動情報を使用するので、以下のように設定する。

20140502_01_2

そして、Object MergeにTrailノードを接続すると、Trailが正しく有効になる。

20140502_01_4

20140502_01_5

4・エフェクトの発生点を作成する

trail_emitterを非表示にしておき、後面を選択後に削除。

blastノードが作られ面の削除が行われる。
blastノードのパラメータで、Delete Non Selectedをオンにする。
こうすることで、選択されていなかった面が削除される。

5・Trailで複製された面が持つ頂点同士を接続する

Trailノードのパラメータで、Result TypeをConnect as Polygonsにする

20140502_01_6

20140502_01_7

同じ番号を持つ頂点同士が接続される。

デフォルトの設定では、ここで作られるポリゴンのラインは閉じているため、急激なカーブを行う箇所などでは面が見えてしまう。
開いたカーブにするため、以下のパラメータをオフにする。

20140502_01_8

6・Trailが作るラインがいい感じの見た目になるようにパラメータを調整

20140502_01_9

20140502_01_10

上記のような設定にしてみた

7・Trailで出来たラインをNurbs Curveに変換する

Convertノードを作成し接続
Convert To を Nurbs Curveにする

20140502_01_11

8・ラインのパラメータ位置計算のため、rankアトリビュートを作成する

Attrib Createノードを作成。
Name を rankに

9・カスタムアトリビュートをビューポートに表示する

Dキーでディスプレイオプションを開き、Customの項目でNew text display option

20140502_01_12

20140502_01_13

ApplyやAcceptを押すと、Customの項目にrankが追加されたことがわかる。

20140502_01_14

これがオンになっていると、同名のアトリビュート値が各ポイント上に表示されるはずだが、なぜかされない。

ちなみに、このカスタム表示を使えば、各頂点上の法線方向なども視覚的にわかりやすく表示できるようになるらしい。

20140502_01_15

10・VOP SOP

VOP SOPを作成してコネクト

20140502_01_16

VOP SOPに入る

11・rankの値を使用するため、Parameterノードを作成する

20140502_01_17

ノード名はわかりやすいものにする

Nameはアトリビュート名
Labelはわかりやすいものにする

InvisibleがオフだとVOP SOPノードにパラメータが表示されてしまうのでオンにして隠しておく。

ノードカラーも、inputとVOP SOP内で生成されるものとで分けておくと良い。

12・RampParameterを作成し、コネクトする

Trailエフェクトのぶれ具合をramp制御したいのでRampParameterを作成し、コネクトしておく。

RampParameterノードは0〜1の値を受け取り、それぞれの値に応じた値を出力する。

20140502_01_22

Rampの動作は以下のようにしておく

20140502_01_18

Nameに$OSという名前の変数を使うと、ノード名そのものがここで作られるパラメータ名として使われる。VEX内部で生成するパラメータはこのパターンで命名するのが楽かも。

13・Turbulence Noiseノードを作成する

このノードを使用して、Trailのブレを作る

20140502_01_21

14・Noiseスケール用のParameterノードを作成する

Turbulence Noiseで作られた3軸のノイズ値を個別にスケールできるように、 3 Float型のParameterノードを作成。

この時、Default値は 1,1,1にしておく。(0,0,0 のままだと、Noiseがかかっていないように見えてしまう)

20140502_01_19

15・MultiplyノードにNoise計算用ノードをコネクト

20140502_01_20

16・Noiseと元々のカーブを加算する

最後に、Multiplyで作られたNoise成分と、元々のカーブのポイントを足し合わせる。

20140502_01_23

Multiplyの計算結果は、あくまでもノイズ成分。
これを、元々のカーブに足し合わせることで、Noiseの加わったランダムなカーブが出来上がる。

20140502_01_24

赤がモーションパスカーブ
緑がNoise加算前のTrailカーブ
白がNoise加算後のTrailカーブ

20140502_01_25

チュートリアルをアレンジしてレンダーしてみた

Houdini sidefx official Lesson12 Compositing

パーティクルアトリビュートを個別に取り出しやすくする

sourceノードにAttribCreateノードを接続する。

20140430_01_1

AttribCreate内でNameに任意のアトリビュート名。
Valueに変数名を使用することで、任意の変数に名前をつけて明示的に外に出せるようだ。

20140430_01_2

マルチパスレンダリング

Mantraノード内、Outputタブ。

20140430_01_3

Extra Image Planesで+ボタンから出力するパスが追加できる。
デフォルトで定義されているパスはVEX Variableの項目右端のプルダウンから簡単に指定可能。

VEX Typeは変数の型を指定。もともとVector型として定義されているパスをFloatなどで出力するとどうなるのか?後でテストする。

Channel Nameは出力されるファイル名のようだ。

Quantizeでピクセルのビット深度の指定。

この設定をしただけではマルチパスレンダリングされないので注意

Material Shader Builder

マルチパスレンダリングのため Extra Image Planeを追加したら、SHOPでMaterial Shader Builderを作成し、オブジェクトへアサインする必要がある。

これでもまだマルチパスレンダリングは行われない

20140430_01_4

VEXパラメータの追加

Material Shader Builderの中でParameterノードを追加し、Nameに先ほど作成したExtra Image PlaneでVEX Variableでつけた名前をNameパラメータに指定する。

20140430_01_6

ExportパラメータをAlwaysにしてレンダリングするとマルチパスレンダリングされたことがわかる。

20140430_01_5

ウインドウ上部のチャンネル名プルダウンから、表示するチャンネルを指定できる。

上図は、Velocityチャンネルを表示。

MPlayについて

Iキーを押すとカーソルの下にあるピクセルの各種情報が表示される

20140430_01_7

以下のボタンを押すと、現在表示されているチャンネルに含まれる値の範囲を最大限引き伸ばして表示できる。

20140430_01_8

イメージファイルへのレンダリング

mantraノードのProperties->Output

Output Pictureパラメータにファイルパスをファイル名込でセット。
拡張子を記入しておくと、自動的にその拡張子のフォーマットで書き出される。

ここにipとだけ記入しておくと、MPlayで直接レンダリングされる。

imgコンテキストを使用するコンポジット

コンポジットプロジェクトの設定は Edit -> Composite Project Settings
コンポジット作業は、imgコンテキスト内で行う。

コンポジット中の画像はComposite Viewで確認できる。

ノードベースのコンポジットソフトと同じように、素材ノードの下流に各種処理ノードをつなげて処理を進める。

まずはImage Networkノードを作り、カットごとなどある程度の単位でサブネットワークを作るのが良い。

イメージファイルの読み込みはfileノードから行う。

Channel Copyノードでイメージファイルから任意のチャンネルを取り出したり、取り出した画像にBlurやExpand,Limitなどといった画像処理ノードををつないでマスクを生成するなどしながら画像合成を行う。

20140430_01_9

20140430_01_10

レンダーノードのmerge

複数のレンダーノードを作成し、mergeノードにまとめると、mergeノードのRenderボタンからまとめてレンダリングできる。

Houdini sidefx official Lesson11 Dynamics

Rigid Body

剛体シミュレーション。
Rigid Bodyの作成は、Rigid Bodiesタブから RBD object 選択後、Rigid Body化するオブジェクトを選択し、Enter

Rigid Bodyの基本ノード構成

20140428_01_0

torus_object1に対してRigid Body化した直後

torus_object1の内側

20140428_01_1

通常通り、ジオメトリが作成され、restにつながっている。
restノードはソリッドテクスチャをオブジェクトへ追従させるために使うノードらしい。

dopimportノードは、別の階層にある DOP Networkへジオメトリデータを転送するのに使っている

20140428_01_4

Object Mask = dopobjscreatedby(“/obj/AutoDopNetwork/torus_object1”)

AutoDopNetworkの内側

20140428_01_2

dopimportで出力されたジオメトリデータをRBD Objectノードで受け取っている。

SOP Pathパラメータにて、どのジオメトリを受け取るか指定

20140428_01_3

SOP Path = opinputpath(“/obj/torus_object1/dopimport1”, 0)

Rigid Body Solver

実際にシミュレーションを行うノード。

20140428_01_5

Solver Engineパラメータで、使用するソルバを指定する。
おそらくBullet以外を使うことは殆ど無いんじゃないだろか

以降のコネクションには、ここでリジッドボディに関連するジオメトリをまとめるmergeノードと、重力等の外力ノードが並ぶ。
これに続けてWindノードなどをつないで外力を足すことも可能。

Ground Plane

無限遠のCollisionオブジェクトを足すことができる。

Rigid BodiesタブからGraund Plane。

20140428_01_6

20140428_01_7

Rigid Bodyオブジェクトの初期状態

各RBD ObjectノードのInitial Stateタブにて設定。

Collisionのパフォーマンス調整

RBD ObjectのCollisionsタブにて設定

20140428_01_8

Modeの変更可で処理の高速化ができそう。
Modeパラメータは、実際に各RBD オブジェクトがどのようなCollision形状を使用して衝突判定を行うかを決定する。

このCollision形状を確認するには、Show Collision Geometryをオンにし、一度初期フレームに戻る。

20140428_01_9

20140428_01_11

20140428_01_10

DivisionsパラメータでCollision形状の精度を調整する。
当然だが、極力少ない面の数で構成されるように調整するのが良い。

シミュレーションのパフォーマンス調整

AutoDopNetworkのパラメータで行う。
Sub Stepで1ステップを何分割して計算するか指定。
このへんはその他のシミュレーションツールと同じ考え方で良さそう。

剛体の振る舞い調整

RBD ObjectのPhysicalタブで行う。
このへんもMayaなどと同じ考えで設定できそう。

※Mayaにないパラメータ
Dynamic Friction Scale:静止摩擦が限界を迎えた後の摩擦係数。
説明を読む限り、Frictionは静止摩擦で、それに対してこの数値を掛けあわせた値が動摩擦係数として動作するということらしい。
よって、この値が0の場合は、滑り出したら摩擦係数0の状態で動作するようになる。逆に、1の場合は常に静止摩擦の値で摩擦係数が発生することになる。
Temperature:温度。浮力や発火の検知に用いる値らしい。
例えば、燃料オブジェクトにこの剛体が接した時、燃料オブジェクトの発火温度をこの値が上回っていたら発火させる。
この発火処理がどのように行われるかは現時点では不明。

RBD Objectの追加

追加したいオブジェクトを選択し、通常通りRBD Objectを作成すると、AutoDopNetworkにRBDオブジェクトが追加される。

20140428_01_12

RBD Objectはいったんmergeノードにまとめられた上で各ソルバノードへジオメトリの出力を行うようだ。

これは、Static RBDオブジェクトの追加も同様。

20140428_01_13

閉じていない形状のRBDオブジェクト

デフォルト設定では、RBDオブジェクトは閉じていない形状でも閉じてい状態で計算される(Bulletの制限?)

20140428_01_14

ボールはチューブの内側に落ちず、チューブが持つボリュームに乗る。
これを防ぐには、チューブの表面に厚みをもたせ、形状を閉じておく必要がある。

カーブ上に散布するオブジェクトの向き

ここでは、散布されたオブジェクトをそれぞれ次のオブジェクトに向けるある一点のオブジェクトに向いてほしい方向は「次のポイントの位置-現在のポイントの位置」で表わせる。

pointノードについてもう少し

pointノードのinput2は、ポイント参照用のオブジェクトを入力できる。
参照用オブジェクトを使用すれば、法線方向の計算などで使用することができる。

20140428_01_15

上図の例では、上見えているカーブを複製し、複製されたカーブを少し下にずらしている。
複製されたカーブなので、各頂点番号は一致している状態。

ここで、上のカーブをpointノードのinput1に、下のカーブをinput2へ接続し、pointノードのNormalに以下のエクスプレッションを仕込む。

NormalX : $TX2-$TX
NormalY : $TY2-$TY
NormalZ : $TZ2-$TZ

$TX2はinput2側の頂点位置を指す。
こうすることで、input1の各頂点法線は、input2の各頂点との差分ベクトルを持つようになる。

Dominoチュートリアル

20140428_01_16

このチュートリアルでは、まずドミノピースを並べるためにカーブを作成する。その後、カーブをResampleし、等間隔で頂点をもたせる。
最終的には、このカーブが持つ各頂点上にピースを複製して散布する。

Resample済みのカーブを受け取るSortノードを作成し、ソート方法をShiftにした上でOffsetパラメータを変更すると、各頂点番号が循環する。

ここでは、この性質を利用して、全く同じ形状で一つ頂点番号がずれたカーブを法線方向計算のための参照先として利用する。

20140428_01_17

頂点数が同じで、元の頂点の並びが同じカーブ同士なら、片方のカーブ上にある頂点番号を一つシフトすると$TXと$TX1の差は、ちょうど隣り合う頂点の位置の差分となる。

よって、この値をNormalに与えれば各頂点の法線は、強引ではあるが次の頂点方向を向くようになる。

この時、末端のポイントだけは正しい方向を向けられないので、DeleteノードをPointノードの後ろに配置し、ポイントの削除を行う。

オブジェクトの頂点上にRBDオブジェクトを散布する

任意のオブジェクトを選択した状態で以下を押す

20140428_01_18

すると、ダイアログが開く。RBD Packed〜 と RBD Point〜の違いが不明なので調べる。

その後、散布したいオブジェクトを選択し、Enterキーで決定。

散布された各オブジェクトは、通常通りRBDオブジェクトとして動くようになる。

あとは、地面を配置してドミノをスタートさせるオブジェクトを作り、最初のピースを倒すだけ。

RBD Object と RBD Fracture Object

RBD Objectは、一つのジオメトリに複数ピースのジオメトリが含まれている場合、それらが一塊でなかった場合でも一つのRigid Bodyオブジェクトとして扱われる。

20140428_01_19

RBD Fracture Objectは、1ジオメトリ内に含まれるすべてのジオメトリを個別のRigid Bodyオブジェクトとして扱う。

20140428_01_20

RBD Glue Object

糊付けされたように、もともと結合力を持っているRigid Bodyが作成できる。例えば家具など、力が加わることで破壊され、他と切り離されるまでは結合を保とうとする振る舞いが作成できる。

シェルフ内で当該機能が見つけられなかった。
別の方法で作る方法を探る。

RBD Pin(Rigid Body Constraint)

剛体に制限を与えることができる。
以下を押す。対象となる剛体オブジェクトを選んでEnter、Pinの位置を選択し、もう一度Enter

20140428_01_21

RBD同士をPinでつなぐ

RBD Pin作成時に2つのRBDを選択すれば、それぞれがPinで繋がれる

20140428_01_22

Rigid Pin Constraintノード

20140428_01_23

Constrained Objectはコンストレインをうけるオブジェクト
Goal Objectは、コンストレインを与えるオブジェクト

Goal Objectが空欄だとGoal Locationで定められた位置にゴール位置が固定される。

RBD Spring Constraint ノード

バネで剛体をつなぐコンストレイン。

20140428_01_24

20140428_01_25

Limit Forceは、バネが切れる力のしきい値のようだ。
低めの値にしておくと、一定の速度がかかった時にバネが消えて、剛体は自由落下する。

20140428_01_26

20140428_01_27

その他のRigid Body Constraint

RBD Hinge Constraintや、RBD Angular Constraint等がある。
使用するソルバによって使えるコンストレインが変わるらしい。

破壊可能なRigid Body

RBDを作成後、Make Breakableを押す

20140428_01_28

破壊のパラメータは Fracture Parameterノード内で操作する。

20140428_01_29

20140428_01_30

20140428_01_31

Houdini sidefx official Lesson10 Particles

Particleノード

20140427_01_0

入力は、左から順にソースオブジェクト、コリジョンオブジェクト、フォースオブジェクト。

パーティクルは、ソースオブジェクトのポイントの位置からIDの順にしたがって発生する。

リアルタイムプレイバックオプション

あまり変わってるように見えないけど、タイムスライダ右側の時計アイコンのオンオフで全フレームを極力高速に連続再生するか、設定されたフレームレートを守って再生するかを決められる。

20140427_01_1

パーティクルの初期設定

ソースオブジェクトからpointノードに接続し、Particleタブの中で初速等を設定する。

20140427_01_5

20140427_01_2

初速に Y=-9.8を入れてみたところ

20140427_01_4

20140427_01_3

パーティクルをソースオブジェクトの法線方向に飛ばす

ソースオブジェクトにコネクトされるpointノードで、standardタブにあるNormalの項目をAdd Normalにする

20140427_01_6

20140427_01_7

この法線パラメータも初速として考えることが可能。
初速と同様にY=-9.8とすると全く同じ動きをする。

パラメータ名と動作をより正確にマッチさせるなら、Velocityパラメータに$NX,$NY,NZを元にするエクスプレッションを仕込むのが正しい気がする。

パーティクルをランダムな位置から発生させるには

ソースオブジェクトをScatterに接続し、オブジェクトの表面に一度パーティクルを散布し、散布されたパーティクルをパーティクル発生点にする。

Sortノード

入力されたコンポーネントのIDの並びを任意のルールでソートする。
例えば、ソースオブジェクト上のパーティクル発生位置を固定しながら、発生順だけをランダム化したい場合に使うと便利。

Collisionオブジェクト

パーティクルが衝突するオブジェクト。
このオブジェクトは体積を持っているべき。

形状を作成したら、particleノードの2番目の入力にコネクトする

デフォルトでは、Collisionオブジェクトにパーティクルがヒットした際の動作は「消滅」に設定されている。

Hit Behabiour = Die On Contact

このパラメータをBounce On Contactに設定すれば、Collisionオブジェクトにヒットしたパーティクルが跳ね返るようになる。

20140427_01_8

20140427_01_9

Collisionアトリビュートは Gain Tangent/Normalのようだ。
Collisionヒット時にそれぞれの方向にどの程度の倍率で力が変化するかを指定できる。

+/- Limit Planeパラメータは、強制的に発生させるCollisionバウンディングボックスと言える。多分オブジェクトを使用するCollisionより高速かつパーティクル抜けがないので、室内シーンなどでは積極的に使うのがいいように思う。

20140427_01_10

上図は、-Limit PlaneをCollisionオブジェクトより高い位置に設定した例

パーティクルのSplit

Collisionヒット時にサブパーティクルを発生させることができる。
設定は、Splitパラメータから行う

Hit Behaviour=Die On Contact かつ Split=Split On Death に設定すると、単純にパーティクルがCollisionヒット時に分裂するような状態が作れる。

Stateパラメータ

Start Time:シミュレーション開始までの秒数
Prerole Time:シミュレーション開始時点までに事前計算を行っておく秒数。カットの開始時にある程度パーティクル数を出しておきたい場合に使用する。
Time Inc:パーティクルの評価タイミングの精度。細かくすればするほど評価精度が高まる。通常は1/$FPSで良くて、早過ぎるパーティクルなど、精度が求められるパーティクルだけ高精度化するのがいい。

ソースGeometryの変形

Particleノードの Behaviourパラメータを Modify Source Geometry にすると、ソースオブジェクトの頂点が、発生したパーティクルに追従するようになる。この性質を利用すれば、ソフトボディが簡単に作れそう。

パーティクルの寿命

Life Expectはパーティクルの寿命(秒)
Life Varianceはパーティクル寿命のランダム幅(秒)

Magnetノード

任意のGeometryをMetaBallによって変形できるノード。
チュートリアルでは、雨メタボールをパーティクル上にコピーし、メタボールがヒットした位置の頂点を盛り上げる変形を行うようにした

パーティクルの発生数に関して

パーティクルの発生数に関するアトリビュート

Impulse Activation:0=パーティクルは発生しない、それ以外は発生する。
Impulse Birth Rate:評価タイミングごとに発生させるパーティクルの数

Const Activation:0=パーティクルは発生しない、それ以外は発生する。
Const Birth Rate:一秒間に発生させるパーティクルの数

Particle -> Poly Line -> Skin -> Polygon Mesh

20140427_01_11


パーティクルの発生点として2つのポイントで構成されるラインを作成


ラインの中心にピボットを移動し、transformにつなげて回転させる。


このオブジェクトをパーティクル発生源にし、Initial Velocityを持たせて移動するように設定する。この時、Impulse Activationを1,Impusle Birth Rateを$NPTとし、ソースオブジェクトが持つ頂点数分を毎フレーム生成するように指定。


パーティクルをAddノードに接続し、By GroupタブでAddパラメータを Groups of N Pointsにし、Nを2にする。
こうすることで、パーティクルが2つ発生するごとに一つのグループにまとめられ、それぞれが別のPolyLineオブジェクトとして扱われるようだ。


Skinノードにコネクトし、面を貼って完成

popnet内でのパーティクルグループ

popnetノード内で、パーティクルのグループを作れる。

groupノードを作成し、Createタブで新規作成するグループ名を Group Nameに入力、Createタブ内、Ruleタブでグループに含める条件を入力することで、条件に当てはまるパーティクルをここで作成したグループに含めることができる。

20140427_01_12

下図は、パーティクルIDを走査し、偶数と奇数でグループを分け、それぞれのグループに別々のカラーとフォースを割り当てた例。

ColorノードやForceノード内で、Source Groupパラメータに、ここで作ったグループ名を入力することで、グループごとの編集が可能になる。

Groupノード内で Ruleタブ内にあるEnableを忘れずにオンにしておくこと。これを忘れると当然効果が現れない。

20140427_01_13

なお、パーティクルの寿命が尽きた時、全パーティクルが持つIDが変化してしまうため、一工夫して変化させない仕組みを作る必要があるようだ。

Houdini sidefx official Lesson9 Custom Shaders

VOP SOP

頂点を直接操作するためのノード
オブジェクトの変形などができるようだ

20140426_01_0

フルネームでアトリビュート名を表示する

Edit -> Preferences -> Network Editor, Nodes and Trees

で、以下のオプションをオンにする。

20140426_01_1

20140426_01_2

こんなかんじでフルネーム表示される。

アトリビュートの型

アトリビュート名の左右にあるボックスは、コネクタであり、値の型ごとにカラーが決まっている。このへんは他のDCCツールのノードエディタと同じ概念。

異なる型同士を接続sる場合は、変換ノードを間に挟む。
変換ノードには、Float to Vector等がある。

20140426_01_3

各コネクタの上にカーソルを置いて待つとコネクタの詳細情報がポップアップする

20140426_01_4

20140426_01_5

20140426_01_6

これは、型の確認に使える。

VOP SOPノードのボタン

20140426_01_7

ノードの右側にはボタンが有る。
左から順にデバッグ/バイバス/表示モード切り替え。

デバッグは後に説明がありそう
バイパスはそのノードを一時的に無効化する
表示モードは、全アトリビュート表示、コネクト済みアトリビュートのみ表示、全アトリビュート非表示を切り替えられる。

頂点移動の例

20140426_01_9

Noiseを使用してGridを変形する。

20140426_01_8

ここでやってること


入力されたメッシュであるglobal1が持つ頂点からそれぞれ Position(Vector)を取得し、Noiseノードに渡す。この時、特にグループなどが指定されていなければ、global1には入力されたメッシュ上にある全頂点が含まれる。


Noiseノードの計算結果をDisplacementノードに渡し、移動後の頂点位置を出力する。Displaced Position(Vector)


VOP SOPの計算結果を出力するためのOutputノードに、変形後の頂点位置を渡すことで、変形が完了する。

VOP SOPの使い方考察

見たところ、VOP SOP内ではトポロジの変更を行うノード(smoothやsubdivideなど)が作れないようだ。
よって、VOP SOPはすでにあるメッシュなどに対し、何らかの処理をするためのものだと思う。
トポロジ変更はVOP SOPの上流で完了させておく必要がありそうだ。

シェーダーネットワーク

shopでMaterial Shader Builderを作成

20140426_01_10

このノードの内側に入るとVOP SOPと同じ要領でシェーダーネットワークを編集できるようだ。

20140426_01_11

Global Variablesノード

出力したい内容に応じて使用する入力値が異なるので、Global Variablesノード内のアトリビュートを適宜切り替えて使用する。
VOPノードの動作は、このノードから出力される値をもとに行われるようだ。

Surface Modelノード

一般的なシェーディングノード。
だいたいこれを使っとけば問題ないらしい。
ダブルクリックすると中身を見ることができる。すでに複雑なネットワークが組まれていることがわかる。

既存のシェーダノード内にあるネットワークを編集する

20140426_01_12

ノードのラベル部分を右クリックして表示されるメニューから、Allow Editing of contentsを選択すると、ノード名が赤色になり、内部のノードネットワークが編集可能になる。

大体の流れとしては、Global Variable → 任意のチャンネルごとに見た目調整処理 → Surface Model → Surface Output → Collect の順にノードをコネクトすれば良さげ。

アトリビュートのPromote

Material Shader Builder内に存在する各ノードの中から、任意のパラメータへのエイリアスをMaterial Surface Builderノードへ持たせることができる。

外に出したいプラグを中ボタンクリックし、Promote Parameterを選択

20140426_01_13

こうすると、ノードのパラメータの左側に突起が出現し、Promoteされたことがわかる。

20140426_01_14

また、Material Shader Builderノードのパラメータを確認すると、パラメータが追加されたことがわかる。

20140426_01_15

また、Promoteは、パラメータリストに表示されている各パラメータの右端にあるボタンからも行える。

20140426_01_17

20140426_01_16

ノード内の未コネクトパラメータをまとめて外にだす場合は、ノードラベル右クリックから Create Input Parameters を選択する

Promote済アトリビュートのExpose

Promoteは、実際には、実体アトリビュートとアトリビュートへのエイリアスの間に値を中継するためのノードが挿入されて行われる。
ノードのPromote済みプラグを中ボタンクリックし、Expose Input Node を選ぶことで、中継ノードが表示される。

20140426_01_21

上図はdisplacementnml1のscaleアトリビュートはPromote済みで、それをExposeした様子。

この中継ノードを操作すると、値の範囲やタイプなど、パラメータの振る舞いを変更することができる。

Propertiesノード

任意のパラメータを持たせるためのデフォルトでは何のパラメータも持たないノード。Edit Parameter Interfaceで任意のパラメータを追加して使用する。

MaterialパラメータをGeometryノードに渡す

GeometryのMaterialパラメータ欄右端のプルダウンから以下のメニューを選択すると、geometry内のmaterialタブにシェーダが持っているパラメータのエイリアスがまとめて表示されるようになる。

20140426_01_18

20140426_01_19

この操作により外へ出されたパラメータは、マテリアル本体が共有されていても、値は共有されないようだ。

つまり、ひとつのシェーダを使いまわしてバリエーションを作成することができる。

これが、アトリビュートとチャンネルの違いということなのだろうか?
ちょっとぴんとこないので、あとで調べる。

オブジェクト内に直接シェーダーを埋め込む

オブジェクトの内側で SHOP Networkノードを作成するとオブジェクトに、シェーダーを埋め込むことができるようだ。

その後、GeometryノードのMaterialタブにて使用するシェーダーを選ぶ際、以下のようにオブジェクトツリー内のシェーダーが選択できる。

20140426_01_20

また、この時、Export Relative Path を選択してからマテリアル指定を完了すると、相対パスでマテリアルが指定されるため、Geometry自体が階層を移動してもマテリアルのアサインは保たれる。

Displacementの最適化

Displacementはデフォルトの設定では、欠けが発生するなどして、正しくレンダリングされない(チュートリアル中に理由が詳しく述べられているようだけど、よく聞き取れず)

これを回避するためには、Propertiesノードを作成し、レンダリング用の特別なアトリビュートを作成と、シェーダネットワーク末端のCollectノードへ接続する。

アトリビュートの追加はPropertiesノードで通常通りEdit Parameter Interface

For Renderingタブ → mantra → Shading → Displacement Bound

20140426_01_22

20140426_01_23

20140426_01_24

Displacement Boundの値を上げることで、精度が上がり、正しくレンダリングできるようになる。

20140426_01_25

それで出来た草シェーダ

VEXとVOP考察

VEXは、Vertex Expression?
VOPで作成するノードグラフは、実際にはVEXコードをグラフィカルに表示しているだけのようだ。

また、Material Shader Builderのパラメータを見ると Compilerの項目がある。これが意味するところは、リアルタイムにVEXがコンパイルされ、最適化された状態で常に使用されるということなんじゃないだろうか。

VEXのコードを表示するには

VOPの操作による処理を記述できるノードを右クリックし、View VEX Code を選択する