カーブでランプを制御したい
ランプの作成もプロシージャルにできたらいいなと思い試しました。
このGIFではSweepのScale RampにSOPカーブの形を渡しています。UIのRampが動いてくれるわけではないのでわかりにくいのですが。
試した手順
- SOPでカーブを作る
- リサンプルでリニアカーブにする
- Detail Wrangleでポイントの位置を取得する
-
ramp_packでランプデータを文字列にする - detailアトリビュートにランプデータを持たせる
- スペアインプットでランプパラメータにデータを渡す
ただし、rampを使いたいのはだいたいwrangleでなので、その場合はもっと簡単なようです。
上記の4.までは同じで、5.6.の代わりに、
7. ramp_lookupでランプデータを使用する
です。
以下詳細を書いておきます。
1. SOPでカーブを作る
カーブノードでカーブを作ります。NurbsでもBezierでもいいです。
ただし、ランプにするカーブなのでランプとして無理な形にはしないようにします。
2. リサンプルでリニアカーブにする
カーブをリサンプルします。
3. Detail Wrangleでポイントの位置を取得する
今回はX軸を横軸、Y軸を縦軸とすることにします。
ポイントの位置を1つずつ取得しkeys, valuesというfloatの配列に格納します。ついでにbasisという文字列の配列にも"linear"という値を格納します。
string basis[];
float keys[];
float values[];
for(int i = 0; i < @numpt; i++){
vector p = point(0, "P", i);
push(basis, "linear");
push(keys, p.x);
push(values, p.y);
}
4. ramp_pack 関数でランプデータを文字列にする
ramp_pack関数に今作った3つの配列を渡し文字列のランプデータを作ります。
string s = ramp_pack(basis, keys, values);
5. detail アトリビュートにランプデータを持たせる
辞書型の変数を作成し、scalerampというキーに今作った文字列のランプデータを持たせます。scalerampはこの後使いたいSweepのランプパラメータ名です。(パラメータ名はマウスオーバーして確かめます。)
その変数でparmsという名前のアトリビュートを作成します。
dict d;
d["scaleramp"] = s;
d@parms = d;
6. スペアインプットでパラメータを渡す
Sweepノードにスペアインプットを追加し、上のwrangleのパスをセットします。
spare_parminputindexという名前の整数パラメータを追加し、-1をセットします。
これで、最初の動画のように、カーブによってランプが駆動します。
7. ramp_lookup でランプデータを使用する
Sweepなどのランプに渡す場合は上記のようにしますが、wrangleで使うパターンも書いておきます。
上記、4.までは同じで、5.6.の代わりに、文字列のランプデータをramp_lookup関数に渡します。chrampのように使えます。(引数の順番は逆です)
dict parms = detail(1, "parms");
string s = parms["scaleramp"];
float f = ramp_lookup(f@curveu, s);
(あとで気づきましたが、ramp_lookupはbasis, keys, values配列を渡せるので、4.のramp_packすらいらなそうですね。)
float f = ramp_lookup(f@curveu, basis, keys, values);
これで終わりなのですが、試してうまくいかなかったことなどを書いておきます。
Nurbs カーブをそのまま使いたかった
本当は、Nurbsカーブをリサンプルせずにb-splineランプカーブにしたかったのですが、Nurbsとb-splineでは形が違うのでできませんでした。カーブのポイントのウェイトなどをいじれば同じ形にすることはできるのでしょうか? わからなかったので諦めました。
ベジェカーブ
b-splineが無理なら、bezierを使おうかと思いましたが、これも違う理由でできませんでした。ランプのベジェカーブは接線の点が、次の接線を追い越すようなカーブを描けますが、それをramp_packすると格納したkeys, valuesの順番が変わってしまいました。keysでソートされているように見えます。これをramp_lookupで使うと元の形とは変わってしまいます。
よってベジェも諦めました。
RGBランプ
これはスペアインプットで渡すことができませんでした。
ただ、ramp_packしてramp_lookupすることはできたのでwrangleでは使えそうです。
ランプUIから値の取得
ramp_packに渡すデータを調べたいのでランプUIから値を取得したかったのですが、wrangleではできないのでpythonで取得しました。
node = hou.pwd()
ramp_parm = node.parm("colorramp")
ramp = ramp_parm.eval()
print(ramp.basis())
print(ramp.keys())
print(ramp.values())
おわり
一応、カーブでランプを操作することはできたと思いますが、まだ実際何かを作るのに使ったことはありません。実際使ってみたら何か不都合があるかもしれませんし、ただ面倒くさいだけかもしれません。
ランプは手軽に使えるのがいいところなので、こんな面倒くさいことはやらないかもしれないですね。