[Houdini] Vellum Constraints を読んでみた その4
概要
こちらの続きです
環境
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
について、
補足図を用意しました
参考
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 を作れたりするべんりなやつ
xyzdist
ポイントからサーフェスジオメトリ上の一番近い位置までの距離を調べます。 originから、指定したジオメトリ上の指定したプリミティブグループ内の一番近い位置までの距離を調べて、その一番近い位置におけるプリミティブ番号とUV座標を出力引数に書き出します。
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
概要
こちらの続きです
環境
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 の値)
__stretchconstraints
と restlength
に関しては、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つの平面(またはその部分集合)がなす角度である)
少し複雑だったので、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
houdini などで出てくる hedge
は ヘッジではなく、 half edge
の略称みたいです
まとめ
ようやく気になっていた拘束の実態について触れられるようになってきました
ただ、ハーフエッジについて勉強していたり、コードを図に起こしたりで
ちょっとあっさり目になってしまいました...
何かあれば Twitter までお気軽にどうぞ~ twitter.com
[Houdini] Vellum Constraints を読んでみた その2
概要
こちらの続きです
環境
OS: Windows 10
Houdini: 19.0.622
Redshift: redshift_v3.0.62 (たぶん)
読んでいく
Collision Geometry の出力
内部で計算に使っているものの、
入力されたジオメトリはそのまま出力されていました
そのため、Vellum Pack 時には Collision Geometry の Input が不要になります
Tips
neighbours (VEX)
個人的にあまり見たことなかったのでメモ
隣接する point を取得するのに使う
任意文字列のattributeを使うとき
haspointattribを使って判定します
attirbute の指定が文字列なのでできる技ですね
float scale = 1.0; string attrib = chs("scaleattrib"); if (haspointattrib(0, attrib)){ scale *= point(0, attrib, @ptnum); }
パラメータの Disable / Hide
こんな感じで記述することができるようです
書き方はこちら
@opinput1 とは
VEX Expression で @opinput1_pscale
を使っているところを見つけました
調べてみると、
Wrangleノードの別のインプットからデータを読み込むのに point(@OpInput2, “P”, @ptnum) 等、 point() や prim() 関数を使ってアクセスできますが、@opinput1_P 等と簡潔に書くことができます。
ExtractTransform ノード
あまり見ないノードだったのでメモ
ドキュメントのサンプルファイルより
これにあるように動かしてからpackより、packしてから動かすほうが効率的っぽい
primitiveSplit ノード
いつもはfacetノード + Unique points でバラバラにすることが多かったです
ただし、このノードは 19.5 から deprecated になっており、
代わりに Point Split ノードが推奨されています
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
のような見慣れない記述方法が出てきて
少し困っていたらドキュメントを見つけました
先述の表記は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 に含まれる頂点数) を 頂点が含まれる面の数で割っています
この辺をまとめた公式ドキュメントを見つけたので貼っておきます
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(組み込み)アトリビュート
@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
参考
まとめ
読み進めるにあたり、結構基礎っぽい内容が多くなってしまいました
次回はもう少し内容に入れる...はず
手元ではこんな感じでコメントを書きながら読んでいます
ようやくswitch_mass_method
まで来ました...
Vellum Constraints が一段落したらhipファイルを公開予定です
何かあれば Twitter までどうぞ~
[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 に限ったことではないと思いますが一応
- Primitive Attribute に
shop_materialpath
がある - 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を作成する
下記 json を Redshift.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 までご連絡ください~
【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 までどうぞ~
漢字難しいな🤔
— てんちょー / 筑野(ちくの)えり💕🍱 (@shop_0761) 2022年6月4日