Time Dependent Cook : YES? or NO?

お久しぶりです。そこそこ忙しくて、ブログを書くのを怠ってました。 今回の内容はビギナー向けですが、非常に重要な考え方なので紹介しようと思います。Time Dependent Cookについてです。 Time Dependentという言葉は、Houdiniを使ってないと聞き慣れないかもしれませんし、気にしたこともないかもしれません。 サンプルファイル (Fedora21, Houdini15.0.393, linux-x86_64-gcc4.8) What is Time Dependent? ではTime Dependentとはなんでしょうか?直訳すると「時間に依存」です。 [Time Dependent Cook:Yes]はフレームが変わるとcookする。逆にNoの場合は、 時間に依存してない。つまり、フレームが変わってもcookしません。 1回cookすれば、それを使いまわします。単純な話、レンジが100Fの場合でYesなら100回cookします。Noなら1回のcookですみます。 これを気にせずアセットを作るなんてことは、トーシロー、素人です。一昨日来やがれ。言い過ぎました。 このTime Dependent Cookの情報をどうやって知るかというと、ノードをミドルクリックすれば一番下に出てきます。SOP、DOP、OBJ、COP、CHOP、SHOP、ROP全てのノードで出てきます。(ん?ROPのTime Dependent Cookってなんでしょうね?) また、会社の人に教えてもらいましたが、ノードを光らせてどのノードがそうなのかを識別させることもできます。 どうして重要なのか? 続いて、活用方法を紹介したいと思います。Houdini始めたら誰しもが使うScatterを使って解説します。 例えば、この歩いている人間にPointを発生させたいとします。普通にScatterすると毎フレーム違う場所に発生してしまいます。これを回避するには、ScatterのパラメータにあるGenerateをIn Texture Spaceにします。一気に処理が重くなりますね パラメータを変えるまでは120fps出ていたのに、 10fpsも出なくなってしまいました。致命的ですね。 速くするにはScatterするのを1回だけにして、後からPositionを動かせばいいのです。TimeShiftでScatterのソースを止めます。そして、ScatterのOutput Attributesから2つを有効にします。これはScatterしたPrim NumberとUVを保存してくれます。 保持したら、最近ついた新しいノードをつかいます。Attribute Interpolateです。1st InputにScatterしたPointをさして、2nd Inputに動いてる人をさすだけPointが動きます。 Attribute Interpolateなかったころ、どうやっていたかというとVopのPrimitive Attributeを使っていました。ちなみにですが、sourceのPrim NumとUVはIntersect Vopでもとれます。 Pointが動いたということで、どれくらい速くなってか試してみましょう。一番最後にTrail Sopをさして、Compute Velocityをvを計算させてみます。毎フレームScatterする場所が違うと、vもおかしな値が入ってしまうので、正確に動作しているかも判断できます。 では、Scatterを毎フレーム計算させた場合です。 続いて、1FだけScatterしたものです。 一目瞭然ですね。処理も速いですし、Velocityもうまく計算されています。 Attribute Interpolateを使うと速くなるよということが言いたかったわけではありません。何が言いたかったかというと、重い処理を極力少なくすれば速くなるよということです。 それを判断する材料の1つがTime Dependent Cookということです。 ...

8月 7, 2016 · 1 分 · Shohei Okazaki

[RnD] Pyro with Vorticity

レゾをそんなに高くしなくても、手軽にコントロールでき、形を崩しいい感じのShapeを作るを目的にしたRnD Houdini歴5年目にして、やっとSopレベルもそこそこになってきたので、最近Dopに力を入れ始めました。データの流れを考えながら構築していったり、Sopでの知識は必ず役に立ちますし、データを可視化できるので、今までもっていたMicroSolverに対する苦手意識がなくなりました。 FumeやらPhoenix FDにvorticityというのがついてるのに、Pyroにはないのとお思いの方、朗報です。 自分で作れます。 あのプラグイン達はBlackboxになっているので、どのような手法をとっているかは伺えしれませんが、結果的によければOKです。 普通に煙をエミットするとのっぺりとした部分ができてしまいます。 これを崩すにはTubulenceをかけたり、Pyroの場合はDisturbanceを使ったりします。Turbulenceの使い方を間違えると、エミットしてから時間が立っているとこにも強くかかってしまうと、ダサい煙になってしまいます。また、Disturbanceも強くかけ過ぎると、ボロボロになってしまいます。コントロールが難しいです。 Vimeoにあげた動画の、最初の煙はエミットされてからすぐに、モコモコしてるのが分かると思います。これが、求めていたものです。コントロールも結構簡単です。 作り方は、、、いくつかのMicroSolverとSop Solverの組み合わせですw Vorticleを作って、渦度が高くないところも高くして影響を与えるみたいなことをしてます。 (Divergenceをいじってもこんな結果ができるはずです。) 手軽に自分で作れるこそが、Houdiniの強み

11月 7, 2015 · 1 分 · Shohei Okazaki

Volume Displacement

Cloud Noise シミュレーションをせずにVolumeを何かしら編集するエレメントといったら雲や霧だと思います。 エフェクトの人で雲を作るときに、ネット検索で引っかかり一回は目にしたことであろう、この論文http://magnuswrenninge.com/productionvolumerendering, Resolution Independent Volumes 何やら、難しそうですね。てか4年(2011)も前なんですね。 個人的な見解ですが、H13?から用意されたCloud Noise Sopはこれを元に作られていると見ています。理由は中を見ればわかります。 Surfaceの場合、DisplacementはNormal方向に対して、ポジションをオフセットします。となると、VolumeのNormalを計算する必要があります。つまりGradientを用意します。 Density VolumeをPolygonにしてからSigned Distance Field(SDF)を作っています。SDFは表面までの距離を記録しています。これをVolume VopでVolume Gradientを使って読み込んだSDFから勾配を計算し、このVector方向にDisplacementしています。 SOPでもVDB AnalysisかVolume Analysisを使って勾配のVector Fieldを作れます。 DisplacementによってVolumeが膨らむことを考慮して、2でBounding Boxを大きくしています。 Noiseを生成しています。 NoiseはForを使って、最初のNoiseより少し小さなNoiseを足していくようなことを繰り返すことによって複雑なNoiseを作り出しています。あとはAdvectionもありますね。 論文で紹介されているやり方に似ていると思いませんか? 中を覗いてみることによって、細かいところは理解できなかったとしても、VolumeにDisplacementする大枠はつかめたのではないでしょうか? SDFからGradientを計算し、その方向にNoiseで作った値をDisplacementするという流れです。次に、この考えを応用してみます。 Pyro Displacement VolumeのDisplacementの方法がわかったところで、続いてシミュレーションしたVolumeに対しての方法を紹介します。 前述の方法は静止しているPに対してNoiseをかけていました。今回は シミュレーションされたVolumeに対して処理を施します。PにNoiseをかけると煙の動きとあいません。Maya Fluidだと煙の進行方向と動きのスピードに合わせて、Noiseのオフセットにキーを打つみたいなことをした経験があるかたもいるかもしれませんが、そんなことはしません。 restが必要です。他のソフトではP_refとか言われていますね。 rest Filedを作るにはいくつか設定が必要です。Smoke ObjectとSolverに設定すべき項目があるので設定します。 ヘルプによるとRest Fieldは、流体の位置を追跡するフィールドと解説されています。また、Dual Restは長いシミュレーションの時に有効で、異なる開始フレームで始まる2つのrestができて、その2つをブレンドして使います。そして、Detailアトリビュートにrest_ratioとrest2_ratioの2つが追加されます。VopまたはShader内で読むときは、restとrest2をMixでまぜbaisにratioを入れてあげます。 最後にSDFも用意しておきましょう。 ここまで用意できれば、後はrestを元にNoiseを作ってDisplacementするだけです。SOPでやるかShaderでやるかは、アナタ次第です。 ちなみにShaderでやる場合は、Pyro Shaderを参考にすると良いです。 上の動画はBasic Smokeを元に作りました。 How to set rest(hip) おまけ。Compress Volume Cache とあるセミナーで、キャッシュサイズの節約法みたいな話がでていたみたいなんで、ここでも触れてみたいとおもいます。といっても、これまた用意されているOTLとノードの解説なんで、手抜き感が否めないですが、意外と知らない方が多いので紹介します。 ShelfからPyroを組んでる人は、Dop I/O SOPを使ってキャッシュをとってる人がいるかもしれません。そのSOPにCompressionタブがあり、これを使います。これはVolume Compressノードの値を逃しているだけです。 このノードは基本的に、以下の画像の赤枠をいじればよいかと思います。Compress設定は、レンダリングに影響が出ない範囲で、最適な値を各自見つけてください。 ...

7月 19, 2015 · 1 分 · Shohei Okazaki

Dynamically Fractured Object

FXらしく少し見栄えの良いものを紹介します。 破壊です。といっても、激しいやつではありません。 破壊をするときは、Pre-Fractureしてからシミュレーションをかける事が大半だとも思いますが、何かしらのトリガーによって自動的に破壊が起こる仕組みを作ってみます。 今回のトリガーさんはImpactです。何かしらが対象物に当たり、ある一定以上の衝撃を受けた部分を壊していきます。 (昔からshelfにRBDで似たようなのができるボタンがあったと思いますが、使ったことないのでよく知りません。) 簡単なところやパラメータに関しての説明はしませんので、hipファイルを見ながら、ブログを読んでいただけるとありがたいです。 シーンファイル(Houdini14.0.291-gcc4.8 Fedora20) そもそもRBD Packed Objectを使ったことない人は、これからの説明を理解することは困難だと思うので、日本語字幕も付いているH13 Masterclass | Bulletを見ることをおすすめします。 Emit Pack Objects このチュートリアルの19:30くらいからのPackエミットを使って、破壊を引き起こす飛んでくる物体をつくります。しかし、チュートリアルのままだと、エミットの量が倍になってしまいます。この問題は、RBD Packed Objectが複数あると起こっていしまいます。 上の画像のように白い柱と赤いボックスは、別々のRBD Packed Objectです。この2つがGeometryというデータを持っているため、SopSolverが両方に処理を行ってしまいます。なのでエミットの量も2倍になっています。 問題を解決するには、片方だけに処理が行われるようにしなければいけません。 Empty Data DOPで任意のDataを作り、Enable Solver DOPで作ったDataに対してのみ作用するようにします。(ここの使い方が正しいかは、あまり自信がないです) これで意図する結果が得られました。 Get Impact Attributes 続いて、Impactの情報を取得するために、Impact Analysis DOPを使います。これはImpactの時間や強さ、法線、ぶつかったオブジェクトのOBJID等を取得できます。 このImpactの情報を元にFractureしていきます。 初めに衝撃を受けたピースの判定をします。Impactの情報の中にはimpactobjectとimpactprimnumがあります impactobjectは$OBJIDのことで、impactprimnumはPackのPrimitive Numberです。 このimpactprimnumをArrayアトリビュートに格納します。 int numpoints = npoints(0); i[]@_impactList; for(int i=0; i<numpoints; i++){ int prinum = point(0,"impactprimnum",i); append(@_impactList,prinum); } Arrayの中に重複した値がある場合がありますが、今回は問題にならないので無視します。 H14からArrayをアトリビュートに保存できるようになりましたが、すごい便利ですね。 Vopを使ってprimnumがこのArrayの中にある値と同じときに、任意のGroupに入るようにしています。 ...

5月 2, 2015 · 1 分 · Shohei Okazaki

Wrangleを使おう 2.5

一個書き忘れてたことがあったので、さらっと。 数学定数、円周率(π)・自然対数の底(e)・黄金比(φ/τ)とか、時々使うけど漠然としか値を覚えていない奴らがいます。正確な値を知るために毎回、調べるのは億劫です。 例えば、Wrangleで初めに#include <math.h>と書けば、以降このノード内ではM_PIが3.1415926の値を持っていることになります。 #include <math.h> f@_check = M_PI; なにが起こっているかというと、$HH/vex/includeにmath.hというファイルがあります。そのファイルの中で、定義されたものを読み込んでいます。この他にもあるので中を見てみてください。 このファイルは自分で作ることもできます。例えば黄金比を呼び出したい場合。 #define PHI 1.61803 これを、HOUDINI_PATHに設定している場所のvex/includeに.h形式で保存するか、HOUDINI_VEX_PATHに登録しているところに保存すれば、これ以降、読み込むことができます。 #include <test.h> f@_check = PHI; 決められたところに保存しなくても、test.hのところを/home/user/test.hとパスを入れても呼び出すこともできます。

3月 2, 2015 · 1 分 · Shohei Okazaki

Wrangleを使おう 2

Wrangleは、アトリビュートを作ったり編集するだけでなく、Pointを作ったりPrimitiveを作ったりもできます。初心者向けのチュートリアルで時々みるPointSopを使って、Pを編集してるやつをWrangleで置き換えてみます。こんなやつです。 まずラインの作り方 line sopできますが、wrangleでやってみます。ただの直線を作るときに、わざわざwrangleでやる必要はないかと思いますが、近くのpoint同士を結びつけるときなど普通にやろうとすると、めんどくさい時に重宝するので覚えときましょう。 int res = 10; float height = 5.0; int line = addprim(0, "polyline"); for(int i=0; i<res; i++){ vector pos =set(1, height/(res-1)*i, 0); int cp = addpoint(0,pos); addvertex(0, line, cp); } 長さ(height)とポイント数(res)を決めてあげて、これらのポイントを結んでラインを作ります。なぜ、Vertexを作る必要があるかというと、Primitiveを構成するにはVertexが必要です。Pointではありません。Help: ジオメトリの作成 もちろん、Vopでもつくれます。 ラインが作れたら、各Pointの位置を編集するだけです。簡単ですね。 int res = 100; float rad = 3; float height = 5; float freq = 10; int line = addprim(0, "polyline"); for (int i = 0; i < res; i++){ vector pos; pos.x = sin(radians(i) * freq) * rad; pos.y = height / (res-1) * i; pos.z = cos(radians(i) * freq) * rad; int cp = addpoint(geoself(),pos); addvertex(0, line, cp); } 1つ気をつけないといけないのは、エクスプレッションのsin/cos/tanはDegree、VexはRadianなので変換が必要です。 ...

3月 1, 2015 · 1 分 · Shohei Okazaki

Wrangleを使おう 1

12.5から搭載されたWrangleですが、結構避けてる人が多い印象です。 せっかくノードベースでやってるのに、イライラするMayaのExpressionを思い出させられて避けてるのかもしれません。 しかしMayaから移行した人にとっては、Expressionと似ているので敷居は高くないはずです。エフェクト屋でPythonとかMelなどのScriptを、全く書けないという人はいないと思うんで、その知識も役立ちます。 ...

2月 18, 2015 · 1 分 · Shohei Okazaki