てんちょーの技術日誌

自分がつまづいたこととかメモ

[Houdini] Vellum Constraints を読んでみた その4

概要

こちらの続きです

shop-0761.hatenablog.com

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

読んでいく

Tetrahedral Volume

ドキュメントより

各四面体を、その四面体の体積を維持する拘束に変換します。

Note これは、シアー(傾斜)またはストレッチ(伸縮)の拘束を含んでいません。 適切なソフトボディを作成するには、さらにDistance拘束を追加する必要があります。

__stretchsrc かつ __constraintsrc な point が属する prim が
下記を満たす時、四面体を追加します

  • 四面体(Tetrahedron)である
  • 4頂点で構成されている
  • ↑の頂点が全て __constraintsrc に属する

追加した四面体のprimに対して、下記を設定します

  • __stretchconstraints (group)
  • restlength (四面体の体積) * Rest Length Scale (Stretch の Rest Length Scale の値)
  • type (ここでは tetvolume )
  • Stiffness (Stretch の Stiffiness の値)
  • Damping Ratio (Stretch の Damping Ratio の値)

四面体の体積を求める computeTetVolumeRestLength について、
補足図を用意しました

参考

examist.jp

Attach To Geometry

ドキュメントより

指定したポイントが3番目の入力のジオメトリに取り付けられます。 これらのポイントには、 Attach Frame での最近接ポイント番号が格納され、それらを結び付けるDistance拘束を作成します。

やや段階が多いですが、バリエーション対応のためです

create_target_constraints ノード

__stretchsrc な point に sphere を追加し諸々設定します

共通設定はこれです
- restvector (それぞれで得られる targetpos)

Use Closest Location on Primitive / Constrain to Closest Point が共に有効なとき

xyzdist で今見てる point から一番近い primitive を取得します
見つかれば、下記を設定します

  • target_prim (xyzdist からもらった 一番近い prim)
  • target_uv ( ↑と同じタイミングで取得したuv情報)

Constrain to Closest Point のみ有効のとき or 共に無効のとき

  • Constrain to Closest Point が有効 : nearpoint で一番近い point を取得
  • 共に無効 : Attachするジオメトリの__attachsrc な point の中から、
    対応する index の point を見つけようとする

見つかれば、下記を設定します

  • target_pt (nearpoint で見つけた一番近い point)
  • dist (今見てる point と targetpos との距離)

set_target_attribs ノード

これらを primitive に設定します

  • type (ここでは attach)
  • targetpath (指定されていればそれで、なかったらCollisionのジオメトリパスをつくる)
  • stiffness (Stretch の Stiffiness の値)
  • damping Ratio (Stretch の Damping Ratio の値)
  • restlength * restscale (Stretch の Rest Scale をかける)

velocity blend が有効なとき

Velocity Blend が ScaledByAttribute ときに指定した Attribute で scaling します
accumScaleValues で難しそうに見えますが、Promotion Method が Average なら
そのまま掛け算されるだけです

Tangent Stiffness が有効なとき

元のGeometryのprimが3点以上からなるポリゴンのとき、
type: attachnormal として さらに sphere を追加します

ほぼ値引き継ぎですが、一部異なります

  • restlength : 0 (Restlength is always zero to constraint directly to line to closest point.)
  • restvector : attachする Geometry 上にある頂点座標
  • restdir : 前段で生成した sphere の position から restvector へ向けての vector を @target_prim 上に射影したもの
  • stiffness (Tangent Stiffiness の値 * 10n)
  • damping Ratio (Stretch の Damping Ratio の値)

restdir

Sliding Rate が有効なとき

prim に attribute を追加します

  • Sliding Rate
  • Target Group

Scale by Attribute のときは下記も追加します

  • Sliding Attribute
  • Promotion Method

Tips

Xform とは

Transformation の意だそうです (知らなかった)

Enumerate

Group内 index を作れたりするべんりなやつ

www.sidefx.com

xyzdist

ポイントからサーフェスジオメトリ上の一番近い位置までの距離を調べます。 originから、指定したジオメトリ上の指定したプリミティブグループ内の一番近い位置までの距離を調べて、その一番近い位置におけるプリミティブ番号とUV座標を出力引数に書き出します。

www.sidefx.com

support.borndigital.co.jp

vex にて @ から始まる変数

string @target_path = ""; のような書き方をたまに見かけます
特に深い意味はないのかな... と思っていたら、
下記のようなコードを見つけ混乱しました

string @target_path = "";
int @target_prim = -1;
vector @target_uv = 0;
...
vector orig = primuv(t@argetpath, "P", @target_prim, @target_uv);

Houdini での用語や名前が分からないですが、どうやら
すでに attribute として設定されていたらその値を、なければ右辺で初期化
という用途のようです

少し書き下すとこんな感じです
prim に target_path というattribute があったりなかったりする例を想定しています

string target_path = "";
if (hasattrib(0, "primitive", "target_path")) {
    target_path = prim(0, "target_path", @primnum);
}

まとめ

少しずつ数学が出てきてまた勉強し直さなきゃ...という感じになってきました
この本が手元にあるので、読んだりしようと思います

実例で学ぶゲーム3D数学 | Fletcher Dunn, Ian Parberry, 松田 晃一 |本 | 通販 | Amazon

何かあれば Twitter までお気軽にどうぞ~ twitter.com

[Houdini] Vellum Constraints を読んでみた その3

概要

こちらの続きです

shop-0761.hatenablog.com

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

読んでいく

Distance Along Edges

ドキュメントより

表示ジオメトリ内の各エッジを、そのエッジ長を維持するDistance拘束に変換します。

__stretchsrc かつ __constraintsrc な point に対して、polylineで結び
下記を設定しています (add した polyline は prim です)

  • __stretchconstraints (group)
  • restlength (polyline の線分の長さ) * Rest Length Scale (Stretch の Rest Length Scale の値)
  • type (ここでは distance )
  • Stiffness (Stretch の Stiffiness の値)
  • Damping Ratio (Stretch の Damping Ratio の値)

__stretchconstraintsrestlength に関しては、pbd_constraints.h 内で設定しています
今後出てくる type の処理も同様に行われていそうです

String

ドキュメントより

処理の軽いヘアー拘束を生成します。 この拘束は、エッジ上の距離とエッジ間の角度を維持します。 しかし、捻じれ拘束がないので、エッジが自由にスピンしてしまいます。

とねじれ拘束がないようなので、用途によっては注意が必要です

Distance Along Edges をもとに更に加工します

見た目は Distance Along Edges と同じですが、
type : angle 分の polyline が増えています

__bendsrc かつ __constraintsrc な point に対して、

注目している点(midpt)と隣接点2つ(startpt, endpt)からなる2直線の内積(degree) が
Bend の Max Branch Angle より小さいとき

(computeAngleRestLength の図)

polylineで3点を結び下記を設定しています

  • __bendconstraints(group)
  • restlength (startpt->midpt, midpt -> endpt のベクトルの内積 range: -π ~ π) * Rest Length Scale (Stretch の Rest Length Scale の値)
  • type (ここでは angle )
  • Stiffness (Bend の Stiffiness の値)
  • Damping Ratio (Bend の Damping Ratio の値)

Bend Across Triangles

__bendsrc な point に対して、属している prim を取得します
各 primが下記を満たしていれば、処理を行います

  • 3頂点からなる prim である
  • ↑の point が全て __constraintsrc に属している
  • half edge が有効である
  • 面が閉じている

ドキュメントより、これを計算するようです

三角形の各ペア(入力が四角形以上であれば、暗黙的な三角形のペア)がその2つの三角形間の初期の二面角を維持する拘束を生成します。


二面角(にめんかく、英: dihedral angle)は、2つの平面(またはその部分集合)がなす角度である)

ja.wikipedia.org

少し複雑だったので、createDihedralConstraint で用いられている
computeDihedralRestLength を図にしてみました
この面の角度を維持するように restlength が計算されているようです

上記図の pt0~pt3 を polyline で結び下記を設定しています

  • __stretchconstraints (group)
  • restlength (二面角の大きさ range: -π ~ π) * Rest Length Scale (Stretch の Rest Length Scale の値)
  • type (ここでは distance )
  • Stiffness (Stretch の Stiffiness の値)
  • Damping Ratio (Stretch の Damping Ratio の値)

Pin to Target

ドキュメントより

指定したポイントが、ターゲットジオメトリ内の呼応するポイントにピン留めされます。 Vellum Solverのターゲットジオメトリは、通常では1番目の入力なので、そのアニメーションに一致しますが、これを上書きすることができます。

特に何もせずそのまま

Tips

ハーフエッジ

ハーフエッジについてあんまり良くわかってなかったので、
こちらを読みました、面白かったです

筑波大の三谷研の資料です

https://mitani.cs.tsukuba.ac.jp/lecture/jikken/polygon_operation.pdf

twitter.com

houdini などで出てくる hedge は ヘッジではなく、 half edge の略称みたいです

まとめ

ようやく気になっていた拘束の実態について触れられるようになってきました
ただ、ハーフエッジについて勉強していたり、コードを図に起こしたりで
ちょっとあっさり目になってしまいました...

何かあれば Twitter までお気軽にどうぞ~ twitter.com

[Houdini] Vellum Constraints を読んでみた その2

概要

こちらの続きです

shop-0761.hatenablog.com

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

読んでいく

Collision Geometry の出力

内部で計算に使っているものの、
入力されたジオメトリはそのまま出力されていました

そのため、Vellum Pack 時には Collision Geometry の Input が不要になります

Tips

neighbours (VEX)

個人的にあまり見たことなかったのでメモ
隣接する point を取得するのに使う

www.sidefx.com

nomoreretake.net

任意文字列のattributeを使うとき

haspointattribを使って判定します
attirbute の指定が文字列なのでできる技ですね

float scale = 1.0;
string attrib = chs("scaleattrib");
if (haspointattrib(0, attrib)){
    scale *= point(0, attrib, @ptnum);
}

パラメータの Disable / Hide

こんな感じで記述することができるようです

書き方はこちら

www.sidefx.com

nomoreretake.net

@opinput1 とは

VEX Expression で @opinput1_pscale を使っているところを見つけました
調べてみると、

Wrangleノードの別のインプットからデータを読み込むのに point(@OpInput2, “P”, @ptnum) 等、 point() や prim() 関数を使ってアクセスできますが、@opinput1_P 等と簡潔に書くことができます。

houdinifx.jp

ExtractTransform ノード

あまり見ないノードだったのでメモ

www.sidefx.com

ドキュメントのサンプルファイルより

これにあるように動かしてからpackより、packしてから動かすほうが効率的っぽい

primitiveSplit ノード

www.sidefx.com

いつもはfacetノード + Unique points でバラバラにすることが多かったです

ただし、このノードは 19.5 から deprecated になっており、
代わりに Point Split ノードが推奨されています

www.sidefx.com

computeOrientRodlengths

Houdiniがインストールされているフォルダ($HFS)内のincludeフォルダを基準に
相対パスでincludeできるようです

素直にインストールしていれば下記あたりです
Windows: C:\Program Files\Side Effects Software\Houdini {バージョン}\houdini\vex\include

computeOrientRodlengthsは pbd_constraints.h 内に定義されています

void
computeOrientRodlengths(const int geo; const int primnum; const string srcgrp;
                        const int outgeo)
{
    // Ignore anything but open polylines.
    if (primintrinsic(geo, "typename", primnum) != "Poly" ||
        primintrinsic(geo, "closed", primnum) == 1)
        return;
    // Only test group if it's not all points.
    int hasgrp = npointsgroup(geo, srcgrp) < npoints(geo);
    // Check if the points have an incoming orient attribute. If os, we assume
    // that it provides a stable basis in which to calculate our rod-aligned orients.
    int hasporient = haspointattrib(geo, "orient");
    vector from = {0, 0, 1};
    // Iterate over pts in vertex order.
    int pts[] = primpoints(geo, primnum);
    int npts = len(pts);
    vector4 orients[];
    float rodlens[];
    resize(orients, npts - 1);
    resize(rodlens, npts - 1);

    int lastpt = pts[npts - 1];
    int loop = 0;
    for(int i=0; i < npts - 1; i++)
    {
        vector d = point(geo, "P", pts[i + 1]) - point(geo, "P", pts[i]);
        vector to = normalize(d);
        if (hasporient)
        {
            // Transform vectors back to rest orientation.
            vector4 porient = point(geo, "orient", pts[i]);
            to = qrotate(qinvert(porient), to);
        }
        vector4 dq = dihedral(from, to);
        if (i == 0)
            orients[i] = dq;
        else
            orients[i] = qmultiply(dq, orients[i-1]);
        rodlens[i] = length(d);
        from = to;
        // Check if this is a loop.
        loop |= (pts[i] == lastpt);
    }

    for(int i=0; i < npts - 1; i++)
    {
        if (hasporient)
        {
            // Rotate new orientation back to current world orientation.
            vector4 porient = point(geo, "orient", pts[i]);
            orients[i] = qmultiply(porient, orients[i]);
        }

        // Make sure to do the above rotation in the orients array
        // before possibly skipping this point based on group membership,
        // otherwise if we then grab the rotation for the last point from
        // the previous vertex, it could be incorrect if the previous
        // vertex wasn't in srcgrp. (Exiting too early caused bug 97655.)
        if (hasgrp && !inpointgroup(geo, srcgrp, pts[i]))
            continue;

        // Set new orientation, possibly overwriting input orientation.
        setpointattrib(geoself(), "orient", pts[i], orients[i]);

        float inertia = point(geo, "inertia", pts[i]);
        // Don't overwrite pinned inertia
        if (inertia == 0.0)
            continue;
        setpointattrib(geoself(), "inertia", pts[i], rodlens[i]);
    }
    // Set inertia and orient for last point if not already seen as part of a loop.
    if (npts > 1 && inpointgroup(geo, srcgrp, lastpt) && !loop)
    {
        float inertia = point(geo, "inertia", lastpt);
        // Don't overwrite pinned inertia
        if (inertia != 0.0)
            setpointattrib(geoself(), "inertia", lastpt, rodlens[npts - 2]);
        // Copy previous orient so final bend/twist rest relative orient is
        // identity, which reduces flipping when final vertex orientation is
        // otherwise unconstrained.
        setpointattrib(geoself(), "orient", lastpt, orients[npts - 2]);
    }
}

ざっくりメインのとこだけ切り出すとこんなかんじ

int pts[] = primpoints(geo, primnum);
for(int i=0; i < npts - 1; i++){
    vector d = point(geo, "P", pts[i + 1]) - point(geo, "P", pts[i]);
    rodlens[i] = length(d);
}
for(int i=0; i < npts - 1; i++){
    setpointattrib(geoself(), "inertia", pts[i], rodlens[i]);
}

剛体の慣性モーメント

球の剛体の慣性モーメントっぽい式をVEX内に見かけたので、
このシリーズを見ておきました

【大学物理】剛体の力学入門①(特徴と魅力)/全6回【力学】 - YouTube

Group の構文

Groupを指定するときに正規表現的なものが使えます
0-nprims(-1):2 のような見慣れない記述方法が出てきて
少し困っていたらドキュメントを見つけました

www.sidefx.com

先述の表記は0を含む偶数のprimを対象としているようです

まとめ

ようやく constraint type の違いによる分岐にさしかかってきました...
ここまではまだアップなので、怯まず読み進めたいと思います

何かあれば Twitter までお気軽にどうぞ~ twitter.com

[Houdini] Vellum Constraints を読んでみた その1

概要

普段漫然と便利だな~~と思って仕組みを知らずに使っている
各ノードの中身を読んでみようというのをやってみます

今回は Vellum Constraints の Vellum Cloth をベースに見ていきます

--- 2022/12/07 追記 ---
一通り読み終わりました
メモを残した hipファイルは こちら

サンプルが足りてないので追って追加したいです...

--- 追記おわり ---

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

読んでいく

めちゃでかい...

たぶん全部を追うと大変なので、ポイントになりそうなとこだけピックアップしながら
紹介していこうと思います

Layer

Vellum Solverの Layer Shock パラメータは、布を何層にも重ねる時に、各層の軽さを制御します。デフォルトでは、下層にある布は上層にある布よりも4倍重くなります。Vellum Constraintsノードの Layer パラメータを使って、layerアトリビュートを設定することができます。

vellum cloth より

TODO: 気になるのであとで追いかける

compute_varying_mass

各頂点がどのくらいの重量かを計算するパートがあったので軽く紹介します
分かりやすいPoly分の一部を抜粋してます

int prims[] = pointprims(0, @ptnum);
foreach(int prim; prims)
{
    ...
    if (type == 1) // polys
    {
        if (primintrinsic(0, "closed", prim))  // polygons
            append(polys, prim);
        ...
    }
}
float measure = 0;
...
else if (len(polys))
{
    foreach(int p; polys)
    {
        int npts = len(primpoints(0, p));
        float area = prim(1, "area", p);
        measure += area / npts;
    }
}
...
float density = chf("density");
@__computedmass = density * measure;

(事前に measure した面積(area) / prim に含まれる頂点数) を 頂点が含まれる面の数で割っています

この辺をまとめた公式ドキュメントを見つけたので貼っておきます

www.sidefx.com

Tips

というより、読んでる最中に気になったものを書いておきます

参照先の見方が分からない

こういうどこかの値を参照しているのだけど、君どこ...というときがありますが、
Edit Expression で中身を確認することができます

Attribute がUI上どこにあるのか分からない

虫眼鏡マークから検索窓が出ます

Edit Parameter Interface でも一覧が表示できます
Hideされているパラメータの場合は虫眼鏡マークからの検索では引っかからないので、
こちらで検索して探してみるとよいかもしれません

文字列比較の expression

strcmp を使っていました

!strcmp(chs("../constrainttype"), "pin")

これは通常の文字列比較に加え、ASCIIコード順による判定も可能なようです
Expression なので chs("../constrainttype") != "pin" のようには書けないっぽい

Spare Input

下記のように Geometryへ -1 でアクセスしている箇所がありました

npointsgroup(-1, "__pinsrc")

これは Spare Input と呼ばれる機能で、インプットを増やせます
VEX や Expression でアクセスするときは、-1, -2 ... と減る方向に index が変わります

参考 nomoreretake.net cgworld.jp 【ゼロから始めるHoudini】 10 - 処理の効率を考えよう - YouTube

Intrinsic(組み込み)アトリビュート

www.sidefx.com

@intrinsic:typeid==1 というexpressionを見つけたので、内訳を調べました
今回は Poly 判定をしているようです

windows→ shell から ginfo コマンドが使えます

>ginfo -P
Primitive Type: Null
Primitive Type: Poly
  Family mask: 0x00000001
Primitive Type: NURBCurve
  Family mask: 0x00000003
Primitive Type: BezierCurve
  Family mask: 0x00000003
Primitive Type: Mesh
  Family mask: 0x00000004
Primitive Type: NURBMesh
  Family mask: 0x0000000c
Primitive Type: BezierMesh
  Family mask: 0x0000000c
Primitive Type: PasteSurf
Primitive Type: Circle
  Family mask: 0x00000010
Primitive Type: Sphere
  Family mask: 0x00000010
Primitive Type: Tube
  Family mask: 0x00000010
Primitive Type: Part
Primitive Type: MetaBall
  Family mask: 0x00000020
Primitive Type: MetaSQuad
  Family mask: 0x00000020
Primitive Type: TriFan
Primitive Type: TriStrip
Primitive Type: TriBezier
Primitive Type: Volume
Primitive Type: Tetrahedron
  Family mask: 0x00000040
Primitive Type: PolySoup
Primitive Type: VDB
Primitive Type: PackedGeometry
Primitive Type: PackedDisk
Primitive Type: PackedFragment
Primitive Type: PackedAgent
Primitive Type: PackedDiskSequence
Primitive Type: AlembicRef
Primitive Type: PackedUSD

参考

www.sidefx.com

まとめ

読み進めるにあたり、結構基礎っぽい内容が多くなってしまいました
次回はもう少し内容に入れる...はず

手元ではこんな感じでコメントを書きながら読んでいます
ようやくswitch_mass_method まで来ました...

Vellum Constraints が一段落したらhipファイルを公開予定です

何かあれば Twitter までどうぞ~

twitter.com

[Houdini]Redshift のトラブルシューティング例

概要

手元で遭遇した Redshift 周辺のトラブルに関してまとめておきます
随時更新予定です (これもあるよ!という報告もお待ちしています)

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

その前に

Houdini で Redshift を使ってレンダリングする方法が(自分が把握してる限り)
2通りあります

一方では問題なくても、もう一方ではダメというケースは往々にして存在しうるので、 手元の環境やプロジェクトに応じて対処する必要があります...

  • ROP or ROP network
  • LOP or LOP network (Solaris)

Volume がレンダリングされない (LOP のみ)

詳細はこちら shop-0761.hatenablog.com

原因不明だったので、
手元では ROP network を使うワークフローも用意して使い分けています

VRAMが(あるはずなのに)足りないと表示されてしまう

現状 ROP の Viewport IPR を実行時にのみ確認しています
(再現できたらスクショを貼ります...)

おそらく Viewport IPR を押下後、すぐ再度押下してレンダリングを止める
これを繰り返しているうちに発生しているような気がします

Houdini再起動で解決します

Geometry/Render で指定した Material が反映されない

これは Redshift に限ったことではないと思いますが一応

  1. Primitive Attribute に shop_materialpath がある
  2. Geometry/Render で Material を指定している

このとき1の方が優先されるようです
そのため、2を使いたい場合は最後に attribute delete 等で削除してあげるとよいです

Tips

Redshift の GPU使用率を制限する (LOP)

Render Settings ノードで設定可能です

設定箇所はちょいちょいUIが変わっているみたいですが、
だいたいSystemっぽいとこにあります

ちょっと古い版 Render Settings だとこのあたりです

タスクマネージャーと見比べたときに効いているのか...?とやや不安になりますが、
何度かPCごとクラッシュさせながら試した感じだとちゃんと動いていそうでした

手元のPCだと80%ぐらいが限界かな~と思っています
これ以上攻めるとブラウザやチャットツール類もほぼ動かなくなってしまうので...

レンダリング速度がなんかいつもより遅い気がする (LOP)

たま~~にありました
普段1frame 2分くらいで終わるものが、倍になっていたり...

これも対処療法的ですが、

  • レンダリングを始める前に hip ファイルを開き直す
  • 他にRedshift を一度でも掴んだ Houdini ファイルが起動しているなら閉じておく or 開き直す

とすると、改善されました
おそらくどこかのプロセスがRedshiftを掴んだままになってるのかな...?
Mantra でも似たような目に遭ったので、アプリ再起動は正義...

おわりに

場当たり的に対処するしかなくて最初の頃は結構大変でした...

何かあれば Twitter までご連絡ください~ twitter.com

[Houdini] Redshift 環境を Houdini パッケージでセットアップする

はじめに

自分はよくRedshift でレンダリングしているのですが、
バージョンが上がるたびに手作業で houdini.env を編集していて
面倒だなぁと思っていました

調べてみると Houdini パッケージ ( .jsonファイル) を用いて、
houdini.env とは別に管理することができる方法を知ったので紹介します

環境

OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)

Houdini パッケージとは

作業者が複数人いる場合、都度 houdini.env の編集を伴うとエラーが起きがちなので、
こういった設定ファイルを分離して管理できるよというものです

簡単なエクスプレッションが使えるので、OSやバージョンによる分岐なども可能です

詳細は公式ドキュメントを参照してください

手順

1. jsonを作成する

下記 jsonRedshift.json として用意します
(名前はわかり易ければ何でもよいです)

各パスはそれぞれの環境に合わせて変更してください
初期設定のままインストールしていれば、同じ位置にあるかと思います

{
    "env": [
        {
            "PATH": "C:/ProgramData/Redshift/bin"
        },
        {
            "PXR_PLUGINPATH_NAME": "C:/ProgramData/Redshift/Plugins/Solaris/${HOUDINI_VERSION}"
        }
    ],
    "path": "C:/ProgramData/Redshift/Plugins/Houdini/${HOUDINI_VERSION}"
}
2. packages 以下に保存する

これを HOUDINI_USER_PREF_DIR 以下にある packages フォルダに格納します

デフォルトの場合は、下記に存在するようです1

  • Windows: C:\Users{ユーザー名}\Documents\houdini{バージョン名}
  • Mac: Macintosh HD/ユーザ/{ユーザー名}/ライブラリ/Preferences/houdini/{バージョン名}
  • Linux: /home/{ユーザー名}/houdini{バージョン名}

手元の環境だとこんな感じです
すでに SideFXLabs19.0.json がありました

3. 以前の houdini.env の設定を削除する

houdini.env にて Redshift の設定していたものがあれば削除しておきましょう
具体的にはこのあたりです

バージョンは適宜読み替えてください

PATH = "C:\ProgramData\Redshift\bin;$PATH"
HOUDINI_PATH ="C:\ProgramData\Redshift\Plugins\Houdini\19.0.622;&"
PXR_PLUGINPATH_NAME = "C:\ProgramData\Redshift\Plugins\Solaris\19.0.622;&"

これで設定は終了です 動くはず...

参考

こちらの動画を参考にしています
手元だと このままではエラーになってしまって読み込めなかったので、
"method": "append" を外しています

サルにもわかる Houdini: setting up multiple 3rd party renderers

Redshift for Houdiniプラグインインストール – Born Digital サポート

まとめ

これでHoudiniのマイナーバージョンアップも気兼ねなく行えるようになりました

何かあれば Twitter までご連絡ください~

twitter.com

【Houdini】Font ノードで穴の開いたアルファベット対策

概要

Houdini で Font ノードを使っていると、囲われたところに面が出来てしまい
Z-fighting が起きてしまうことがあります

Hole Faces にチェックを入れていればいくらか回避できますが、
いつも上手くいくわけではないようです

今回はその対策をしてみます

環境

Windows 10
Houdini 19.0.455

手順

全体はこんな感じです

分かりやすくするため、Hole Faces のチェックは外しておきます

detect_inverse_face

forward ベクトルを指定できるようにしていますが、
特に何もなければ (0, 0, 1) でよいです (Z+ 方向に文字が向いているため)

float nDotF = dot(v@N, chv("forward"));
// -0.99 は適当です 
// 内積が -1 == 反対を向いた面 なので、少し誤差を許容しています
int isInverse = nDotF <= -0.99 ? 1 : 0;
setprimgroup(geoself(), "inversed_face", @primnum, isInverse);

Split と Reverse

inversed_face で分けます

右側(Non-Selected Geometry)は反対を向いているので、
ひっくり返してあげるとこうなります

boolean

最後に Surface 同士で boolean してあげればおしまいです

余談

この方法はアルファベットだと上手くいく...と思います
問題になるのは漢字です

eg) 回 の場合

Before

After (今回のノードで処理後)

これをなんとかしようと foreach で回しながら... とかやったんですが、
結局は Hole Faces にチェックを入れると解決しました

さいごに

アルファベットの B だけ怪しい...ので、狙い撃ちで対策してもいいかもしれません
この記事のアイディアは 杉村さんのworkshop に影響を受けています
よければそちらもご確認ください~!

何かあれば Twitter までどうぞ~