実は昔houdiniで「rampで高さを制御したline上に階段を作成する」otlを
作ろうと試みたのですが、その時はうまいこといきませんでした。
なぜかというと、lineの角度が90度を越えた際に、踊り場を作る必要があったからです。
踊り場って言ってもそんなの簡単じゃないか?
と最初は思ったのですが、これが難しい。
なぜなら、
とあった場合、90度なのか270度か判定しなければならいためです。
270度ならば、あまり問題はありません。
しかし90度であれば踊り場を作るために、lineの角から踊り場の領域を遡って確保しなければなりません。
で見れば簡単そうだが、実際は・・・
この平行部分がなかなか作れない!
僕は当初内積を使えば角度がわかるので、それで判断できると考えていたのですが、
内積の返り値はスカラーの0~180度でしか判定できません。
「無理だ…」
ということで、そのときはlineを階段の中央とみなした作成方法を行いました。
しかしこれは…あまりうまくいきませんでした。
結局このやり方では正方形以外の踊り場が作成できないのです。
必ず四角形の踊り場が来るのであれば、対応はできます。しかし、斜めのコーナーが来た時点でこのやり方は破綻します。
そして1年後、たまたま「外積」を勉強し直す機会がありました。
外積は右回りは正、左回りは負の特性を持ちます。(yの方向に注意!!)
ということは、負のときの内積を360から引けば、0~360の判定が可能になる!!
やった!
Wrangleサンプル
実行させる前にdivideでRemove Shared Edgeと
sort(By Vertex Order)をしてください。
#include <voplib.h> vector N_A; vector N_B; vector crossprod; int nb1ptnum; int nb2ptnum; float product; float dotprod; float trig; float deg; if(@ptnum==0){ nb1ptnum = (npoints(0)-1); nb2ptnum = 1; }else if(@ptnum==(npoints(0)-1)){ nb1ptnum = @ptnum-1; nb2ptnum = 0; }else{ nb1ptnum = @ptnum-1; nb2ptnum = @ptnum+1; } N_A=point(@OpInput1,"P",@ptnum)-point(@OpInput1,"P",nb1ptnum); N_B=point(@OpInput1,"P",@ptnum)-point(@OpInput1,"P",nb2ptnum); crossprod = vop_cross(normalize(N_A), normalize(N_B)); dotprod = vop_dot(normalize(N_A), normalize(N_B)); trig = vop_acos(dotprod); deg = vop_degrees(trig); if(crossprod.y > 0){ f@degree360=360-deg; }else{ f@degree360=deg; }
0~360度が取れることはわかりました。では踊り場はどうやって作ればいいでしょうか?
方法は2種類あります。(あくまで僕のやり方なので導師の人は別の方法でやるかも・・・)
180度以上のコーナー:
1つの頂点からそれぞれの2本ベクトルに垂直な線を取り出す
その垂直な線をノーマライズして内角の1/2からだいたい√2ぐらいの長さでベクトルを出す。(90度の場合)
あとはその3点で三角形を2つ作成してマージすると踊り場が作成されます。
180度以下のコーナー:
(1)
上の方法だと頂点からでる2つのベクトルと隣り合う2つのベクトルとの間に角度によってメッシュの重なり(もしくは隙間)が生じてしまいます。これはよくないので
(2)
それぞれ頂点から垂直に出していたベクトルの方向を、頂点から内角の1/2に伸びたベクトルの先に変更します。これで三角形が2つ作られました。
(3)
そしてここにできた隙間を埋めてやります。
1:赤の頂点を紫の頂点に(1つめの三角形)
2:青の頂点を紫の頂点に(2つめの三角形)
(4)
計4つの3角形を作ります。これである程度の(90度以外の)角度に対応することができます。
ただし0~90度のときは、赤と青の根元が重なる可能性があるのでfuseで微調整をします(結局力技)。
問題点としてはUVがきれいにならない可能性があることと、
角度によってはいびつな突起が生じる可能性があることです。
どうだったでしょう。内積と外積。とても便利ですね!
(hipファイルは・・・ネットワークが汚いので整理したらアップします。)