Lockキーを押し、Interceptモードをオンにします。現在時間がオレンジ色になります。CHOPを繋いでレコーディングできます。Interceptモードではキーボード入力が無視されるのでマウスでシーンの再生ボタンを押してください。chopエクスプレッション関数による値の取得も同様に行えます。Sourceは、各々がお持ちのMIDIデバイス名を選択してください。Proはアフタータッチ対応のMIDIコントローラなので、打鍵後に鍵盤を更に押しこむ事でafチャンネルを変化させることができます。CHOPを繋いでレコーディングできます。chopエクスプレッション関数による値の取得も同様に行えます。■おわりに今回ご紹介したテクニックを使うことで、直感的なデータ入力ができるようになります。特定のキーを押したタイミングでパーティクルを発生させたり、ジオメトリの頂点カラーを変化させたり、キーボードを叩くたびに乱数のSeed値を変化させて、次々と予想だにしないビジュアルを作り出すこともできるでしょう。キーを押す強さが強いほどパーティクルの発生量を多くしたり、色を濃くしたりと言った、複雑な表現もできるようになります。Keyのようなツールを併用することで、手に馴染んだゲームコントローラを操作してHoudiniへのデータ入力を行うことも簡単にできます。CHOPは使用しませんでしたが、これらも使いこなせばなかなかに楽しいことができそうなCHOPなので、いずれ折を見て記事にしたいと考えています。ここまで読んでいただき、ありがとうございました。何か不明点や間違いがあれば、記事へのコメントやTwitterなどで質問、ツッコミください。■おまけ以降は、今回使用したCHOPのマニュアルみたいなものです。CHOPマウスのカーソル位置を取得することができます。タブレットを使用している場合は、筆圧やペンの傾きなども取得できます。・PositionX/Yここで指定した文字列が、それぞれに対応するCHOPチャンネル名になります。画面左下から右上に向かって値が増えていきます。TabletオンにするとPressureやAngleなど、タブレット向けパラメータが有効になります。PositionX/Yと同様、ここで入力した各文字列が、それぞれに対応するCHOPチャンネル名になります。CHOP指定したキーが押されたとき、Typeで指定した方法で値を入力します。オンにする必要があります。Lockを有効化します。Interceptモードが有効になると現在フレームがオレンジ色に着色されます。この状態でキーイベントを取得するよう設定したキーを押すことで、値が入力されます。Keys使用する修飾キーを指定します。上記画像の例では、[A]を押している間だけCHOPチャンネル[a1]の値が1になります。・Name対応するキーが押されたときにオンになるCHOPチャンネル名を指定します。CHOPMIDIキーボードやフェーダーコントローラなどを使用して、Houdiniに外部から直接MIDIデータを入力することができます。MIDIファイルを直接読み込む事もできます。SourceMIDI信号の入力ソースを指定します。MIDIファイルやMIDIデバイスを選択できます。インタラクティブな入力を行いたいなら、接続済みのMIDIデバイス名を選択します。Fileを選択します。Channels入力するMIDIチャンネルの番号を指定します。入力するMIDIチャンネル数が多いと入力データの転送に時間がかかります。使用するノート番号の範囲が0-127の場合、使用するMIDIチャンネル1つごとに128個のデータを解釈することになります。そこでアフタータッチをポリフォニックモードで解釈させるとなると、さらに128倍の負荷がかかります。そのため、インタラクティブに操作したい場合は入力するMIDIチャンネルを一つに絞ったほうがいいと思います。複数のMIDIチャンネルを入力するのは、MIDIファイルを入力する時のみで良いでしょう。Prefix入力するMIDIチャンネル番号を識別するために付加される接頭辞を指定します。ここで指定した文字列のあと、入力されたMIDIチャンネル番号が付加されます。この値が[ch]の時、CHOPチャンネル名は以下のような書式になります。Consoleに表示されます。デバッグに便利なので必要に応じてオンにします。CHOPを使用するので、ここでは何も変更しません。・Noteタブ主にMIDIコントローラの鍵盤部分とピッチベンドコントローラからの入力信号の解釈方法を決定するタブです。・チャンネル名パラメータチャンネル名パラメータは、対応するMIDI信号を受けとるCHOPチャンネルを作成します。ピッチベンドここで指定した文字列が、MIDIチャンネルを示す文字列のあとに続きます。Nameの値が[n]なら、MIDIチャンネル1のノート番号60の値を受け取るCHOPチャンネル名は以下になります。ch1n60これらのCHOPチャンネル名パラメータに何か文字列が入力されると、その時点でCHOPチャンネルが作成され、データの入力待ちが開始されます。使用しないMIDI信号の入力については負荷軽減のため何も入力しないのがベターです。Scope入力を受け付けるMIDIノートナンバーの範囲を指定します。0-127の範囲が使えます。同様の書式で指定できます。Channelノート信号を番号ごとに分けず、一つのチャンネル内で押されたノート信号をすべてまとめて使用します。この時、CHOPチャンネル名にノート番号は付かず、以下のような名前になります。Channelsノート信号をノート番号ごとに個別のチャンネルとして入力します。この時、CHOPチャンネル名は以下のようになります。Note信号のVelocityをどのように受け取るか指定します。・OffVelocityを入力しませんノートを入力するCHOPチャンネルの値はオンオフの2値になります。Amplitudeノートを入力するCHOPチャンネルの値が、Velocityの値になります。ChannelsNote信号の値はオンオフの2値になります。Nameで指定された接頭辞とノート番号で表されるCHOPチャンネルの値として取得されます。Normalize入力されるVelocityデータの値の範囲を指定します。マッピングした状態で入力されます。CCメッセージに関する解釈方法を決定するタブです。MIDIキーボードにスライダやツマミが付属している場合がありますが、そのような鍵盤以外のコントロールから送信されるデータに関する入力設定です。・チャンネル名パラメータチャンネル名パラメータは、対応するMIDI信号を受けとるCHOPチャンネルを作成します。CCメッセージへ割り振られているコントロールを、わかりやすくプルダウンメニューから指定できます。CCメッセージのコントロールナンバーを直接指定します。0-127の範囲が使えます。同様の書式で指定できます。Controllers扱うCCメッセージがLSB/MSBに対応していない場合はこちらを選択します。Controllers扱うCCメッセージがLSB/MSBに対応している場合はこちらを選択します。Normalize入力された値の範囲をリマップします。Offブール値化しますUnwrapこれはちょっとよくわかりませんでした。ラベルから察するに、ターンテーブルのような値をインクリメント/デクリメントするコントローラ向けに、値が0-127の範囲外にセットされたときに値をループさせるか否かを決めるオプションのような気がします。・SysタブMIDIクロックメッセージやシステムメッセージに関する解釈方法を決定するタブです。今回は、手元で検証できる環境がないので端折りますが、この辺をちゃんと設定すれば外部のDAWとHoudiniの間で内部時間や、再生操作や停止操作などを同期できるはず。メイキングストーリー」のおさらいをしていました。いうわけで、今日はプロテスのエフェクトです。今回もサンプルファイルを付けてみました。興味のある方はぜひ覗いてみてください。Drive)MYAM_imitation_FF_KINGSGLAIVE_Protes.zipzipファイル解凍後に出てくるHoudiniProjectフォルダにSetProjectしてからシーンを開いてください。振る舞いを決める部分で、ベースになるプロテス障壁の形状を分流してそれぞれを個別のグループに入れながらPaintSOPなどで@Cdの設定を行い、最後にMergeSOPで各データフローを統合してから、最終的に使用しないグループに含まれる成分を削除するという解説だったように思います。今回は、この部分を極力簡略化し、カラーを独自アトリビュートに変換したあとでAttributeTransferSOPでレンダーモデルに転送する方法を試してみました。空間転写は処理負荷が高いので、もう少し上手に軽い方法を使えばよかったと思っていたりします。何か間違いなどあればご遠慮無くツッコミください。メイキングストーリー」のおさらいをしています。いうわけで、とりあえず手始めに今日はワープエフェクトに関してです。今回もサンプルファイルを付けてみました。完全な再現とまでは行かなくとも、ボリュームと移流の扱い方に関しては、だいたい再現できていると思います。興味のある方はぜひ覗いてみてください。Drive)MYAM_imitation_FF_KINGSGLAIVE_WarpFX※ノード名がセミナー中の説明と合ってなかったので、修正しましたzipファイル解凍後に出てくるHoudiniProjectフォルダにSetProjectしてからシーンを開いてください。概要ワープエフェクトは、5つの単純な要素を組み合わせて作ります。荒いボリュームからパーティクルへ力を渡し、移流して動かしますその後、TrailSOPなどを使用して火花っぽい見た目を作ります。Ash:灰Spark同様に移流してパーティクルを動かします。その後、灰オブジェクトをパーティクル上にコピーします。Fire:小さな火の玉Spark同様に移流してパーティクルを動かします。その後、あらかじめ作成しておいた火の玉シミュレーションのキャッシュをパーティクル上にコピーします。その際、キャッシュのスタート時間をランダム化して見た目にばらつきをもたせます。Steam:体から立ち上る蒸気Sparkなどで使用する荒いボリュームを複製後に編集し、高解像度化したボリュームを蒸気として使用しました。初速と重力によって動く単純なパーティクルにクリスタル片オブジェクトをコピーして作ります。複雑なワープエフェクトは、実は単純な要素を組み合わせて作られています。シーンファイルについてスケール調整の手間を省いたので、現実スケールに対しシーンスケールが大きめになっているため、ダイナミクスオブジェクトの動きが若干遅く感じられると思います。何か間違いなどあればご遠慮無くツッコミください。Yamabe.Michiyoshi返信Houdiniを触り始めた頃、アトリビュートや変数のデータの取り回し方がわかりにくいと感じていました。中でも特にローカル変数の挙動がよく理解できずに、正しく値を操作できても何だか狐につままれたような気持ちになっていました。最近はそのようなこともなくなり、意図したとおりに値を操作できるようになってきたので、実践している値の取り回し方を備忘録的な意味で書いてみます。今回もまたちょっとしたサンプルファイルをつけてみます。Drive)MYAM_attributeAccess_exsampleHoudiniで扱うデータのスコープHoudiniの中で主にユーザーが直接扱うデータには、以下のようにいくつかの種類とスコープがあります。グローバル変数ローカル変数パラメータアトリビュートHoudiniに触り始めた頃、わかりにくいと感じていた部分が、ローカル変数とパラメータとアトリビュートの相互の関係性です。※グローバル変数は、環境に依存しすぎる気がするので、最近でも極力手を付けないようにしています。(パス文字列の簡略化などに使えばとても便利ですが)よって、今回の記事では扱いません。SOPを使い、アトリビュートを作成すると同時にローカル変数も定義して、下流のパラメータエクスプレッションの中でローカル変数を参照して処理をするやり方が散見されます。これは勝手な印象ですが、特に古いバージョンのチュートリアルで顕著だったように思います。チュートリアルの後、自分なりに実践してみてうまく値を扱えない時に感じたのがデータフローの上流で作ったはずのローカル変数が下流で参照できない・・・と思ったらなぜか使える場合があったりする・・・オペレータの性質から想像するに、マニュアルを引くまでもなく明らかに使えそうに思えるローカル変数が使えない・・・オペレータのリファレンスマニュアルに記載されてるローカル変数が使えない・・・アトリビュートを直接操作したい・・・ローカル変数を参照できない理由がわからない・・・まるで異次元に迷い込んだようだ・・・地獄だ・・・といったあたりです。平たく言うと「ローカル変数が値の操作を混乱させる諸悪の根源」のように感じていたわけです。デジタルアセットとローカル変数の罠また、このローカル変数というやつは、デジタルアセット上で使用できないという、恐るべき制約も手伝って、更に話をややこしくしています。※ColorSOPのマニュアルに記載あり。SOPはデジタルアセットで、Colorパラメータ内ではローカル変数を使用できません。上流で独自アトリビュートを作成し独自のローカル変数を作っても参照できません。紛らわしいことに、そもそもColorSOP自体、上流で@Cdアトリビュート操作があることを想定していません。@Cd操作の開始点として使用する前提です。SOPを使用し、その中でローカル変数を参照することで問題なく@Cdアトリビュートを直接操作できます。このような紛らわしさもまた、一つの地雷と言えそうです。ローカル変数よ、さようならではどうすればいいのか。SOPを介してアトリビュートを直接管理や操作をするのがベストだと考えています。最近のバージョンでは、VEX周りがかなり進化しています。SOP内だけでなく、各オペレータのパラメータエクスプレッションでも、VEXのように@記法で直接アトリビュートを参照したり、それができない場合でもpoint関数などを使ってアトリビュートを直接参照する事ができます。値の管理と操作を、一貫したVEXの世界で行えるのは、この上なくシンプルで理想的です。今のところこの方法で困ったことは一度もありません。よって、もう、ローカル変数の出番は無いとすら思います。SOPを使うアトリビュートの参照は@記法を使って直接参照するまたはpoint関数などのアトリビュート値を直接取得する関数を使うローカル変数は使わない$CEXなど便利なローカル変数はあるが、同様のVEX関数もあるのでそちらを使うようにする。これが同じ悩みを持つ方の一助となれば幸いです。何か間違いなどあれば遠慮なくツッコミをください。プロシージャルモデリングテクニカルセミナー」が開催されました。Bookで掲載された作品「Spine」がどのように作られたかを、著者の秋元氏が自ら解説するという貴重なセッションがありました。そこで感銘を受け、自分なりの解釈も踏まえつつ真似してみたくなり、早速作ってみました。記事と解説をすべてトレースするのではなく、VOPで処理されていた場所をVEXで処理するなど、ちょっとだけアレンジしています。シェーダーまでは手を付けられなかったので、簡易モデルと動きのみです。hiplcファイルを公開してみます。ファイルには、簡単なモデルと本体モデルとシリンダーの挙動を組み込んであります。時間経過に伴いウネウネ動く仕込みもしてあるので、再生してみると楽しいかもしれません。長い間、仕事ではパイプライン系ツールを書くことが多くなり、幾何学や物理などの数学とはだいぶ疎遠になってしまいました。内容を、Houdiniを使って追いかけていきたいと思います。単純な力を与えて動かす。質量を考慮しながらシンプルな力(重力+風)を与えて動かす。小さいものほど風の影響を受けやすく水平方向によく動く。力と流体抵抗Y=0の位置から流体があると仮定し、ポイントが抵抗を受ける。この流体の範囲に入った時、ポイントは赤くなります。引力(固定アトラクタ)原点の位置に引力を発生するポイントを配置し固定。その他のポイントは原点のポイントと引き合う。引力(ポイントの相互作用)各ポイントはそれぞれ相互に引き合う力を持っている。質量や引力の設定にもよるが、小さな塊ができ、それぞれの塊が引き合い徐々に大きな塊になっていく。(ポイント半径に合わせたコリジョンは設定していないので、実際には、塊は大きくなりません。Houdiniの単位系Houdiniは標準的なSI単位を採用している。力とは、質量を持った物体に加速度を生じさせるベクトル。・ニュートンの運動の第1法則(慣性)静止している物体は静止状態を続け、運動している物体は不平衡力の影響を受けないかぎり、一定の速さで一定の方向へ運動を続ける。・ニュートンの運動の第3法則(作用・反作用)力は常に反作用が対になって生じ、その強さは等しく、向きは正反対である。-F[N]押し合う物体の質量が違う場合や、接地面の摩擦力が違う場合、同じ力が加わってもそれぞれの物体が静止し続けるとは限らない。力とProcessing・ニュートンの運動の第2法則(運動方程式)質量(m)に加速度(A)を掛けあわせると力(F)になる。書籍では質量を1として計算し、F=Aとして簡単化する。通常、物体にはいくつかの外力が同時に作用する。そのような場合、全外力の合計値を使用する。物体に働く力は、特殊な状況を除いて常に変化し、積算されないので、毎フレームで新たな値を計算して使用する。windForceやgravityForceなどを追加してみる。先に計算された外力を質量で割ることで、各ポイントごとに設定された質量を考慮したシミュレーションが行われる。自由に直接指定するシミュレーション物理公式などを利用し、計算する。地球と重力と力のシミュレーションこの時点では、質量が小さいものほど重力の影響を強く受けるようになっている。物体の落下速度は、その質量にかかわらず一定。重力加速度の式から正しい加速度を求めて適用するため、重力に質量を掛けあわせてる。摩擦は散逸力(非保存力)。※散逸は、抵抗力によって運動エネルギーを熱エネルギーに変換する現象。散逸力とは、摩擦力などのエネルギーを減少し、別の力に変換させる力。車のブレーキなどは運動エネルギーを熱エネルギーに変換。摩擦の方向は速度方向の逆。・公式を使用する際のポイント右辺を計算し、左辺に代入する。変数がベクトルかスカラーかを見極める。記号が隣り合っている場合は乗算を表す。特定の表面上に生じる摩擦力の強さ。物体が接触面から受ける反作用で接触面に対して垂直方向に物体を押し返す力。物体が接触面から受ける垂直抗力の大きさは物体の質量に比例する。v:正規化済みの速度ベクトル式中の-1と掛けわせることで摩擦による力の発生する方向を取得する。この場合、速度ベクトルの真逆方向に摩擦力による力が発生する。物体が空気や液体(流体)の中を通り抜けるとき、抵抗力が働く。Resistance)などと呼ばれる。m1とm2:相互に作用する2つの物体が持つそれぞれの質量。r:物体間の距離ベクトルを正規化したベクトル。物体同士が引き合う方向。r^2:物体間の距離の2乗。物体同士が引き合う力は距離が長いほど弱くなり、近いほど強くなる。相互引力と反発2.9の計算を、各ポイント間で計算し、毎フレーム全ポイントの影響を合計して適用する。何か間違いがあればツッコミをいただけると助かります。Yamabe.Michiyoshi2ふと、平井氏のTweetに誘発されて作ってみた。ダイナミクスを使わず、キーフレームによる移動をもとに、正しくボールを転がすソルバです。できたのでちょっと嬉しい。長い間、仕事ではパイプライン系ツールを書くことが多くなり、幾何学や物理などの数学とはだいぶ疎遠になってしまいました。内容を、Houdiniを使って追いかけていきたいと思います。ベクトルなしでは始まらない・バウンドするボールポイントの速度と移動可能な範囲を指定。ポイントは毎フレームで指定した速度に相当する距離移動し、範囲外に出た時に速度を反転させる。SOPで軌跡を見やすくしている。ベクトルクラスを使わないので、まとめて計算ができず、とても面倒。プログラマのためのベクトルPVectorクラスで速度と可動範囲を定義。Houdini上では、速度と可動範囲をベクター型の変数で置き換えた。ついでに、3D上で動くようにした。ベクトルクラスを使うと複数の値をまとめて計算できるようになりとても楽です。ベクトル加算ベクトル同士の加算。ProcessingでのPVector.add()を解説。その他のベクトル演算ベクトルクラスのメンバメソッドの解説。Processingでは変数型にメンバメソッドが含まれる。Houdiniでは、VEX関数を用いて同様の処理を行う。ベクトルクラスのメソッドadd(),sub(),mag(),normalize()などベクトル減算ベクトル同士の減算を解説。ProcessingでのPVector.sub()を解説。ベクトル乗算(除算も)ベクトルとスカラーの乗除算の解説ProcessingでのPVector.mult()とPVector.div()を解説。ベクトルの大きさベクトルの長さはピタゴラスの定理で求める。ProcessingでのPVector.mag()を解説。ベクトルの正規化ベクトルを単位ベクトルにする。ProcessingでのPVector.normalize()を解説。速度は位置に影響を与える。Moverクラスを定義する。Moverオブジェクトはどのようなデータを持つか位置、速度などMoverオブジェクトはどのような機能を持つか動く、表示する※ここでは、Houdini標準アトリビュートの@vや@forceなどを使わず、独自のアトリビュートを用いて、最初から自前で計算します。@Pは計算結果を代入するために使います。SOPのように見える。SOPの上流にあるすべての要素と言えそう。Frameによって指定された時間に一度だけ行われ、キャッシュされて初期化される。SOPの中で定義する。SOPは毎フレーム実行される関数であると考えて良いと思う。SOP内では、現在のポイントの位置に加える変位を計算し、毎フレーム変異させる処理を行う。加速度は速度に変化を与える。事前に加速度を設定し、変化させない。SOPの中で加速度をnoise関数やRandom関数で変化させる。マウスに向かう加速度Houdini上でマウスカーソルの3D座標が取れるかは謎なので、代わりに、特定のポイント位置へ向かう加速度を発生させるアルゴリズムで作ってみる。速度に制限をかける現実的に、速度が無限に高まることはないので、一定の速度を超えないように@velocityを抑制し、速度制限する。通常のプログラミングにおけるstaticメソッドに関する解説。Houdiniオブジェクトはクラスっぽいけどクラスそのものではないので、再現できないとおもわれる。ムービーのように、なんとなく魚群風に見える映像が出来上がった。※当ブログの内容は、個人的な研究記録です。所属組織の業務とは一切関係ありません。