LoginSignup
38
22

More than 3 years have passed since last update.

HoudiniのWrangleで平面を球、円錐に変形

Last updated at Posted at 2017-04-22

概要

untitled_1.gif

HoudiniのWrangleで平面を球や円錐に変形して、エフェクト用のメッシュを作成します。頂点の位置を計算で直接変更しているだけなので他の3Dソフトやコードでも使えると思います。もとの平面は0<x<1, 0<z<1のものを使います。Gridを使用し、Sizeを1*1にし、Transformでx,zを+0.5して、0<x<1, 0<z<1の平面を用意します。
rapture_20170422220548.png

※例ではわかりやすくするため間にUVQuickShadeを挟んでいます。
※書いていたときのミス防止のため、助長に変数を使っています(in, outなど)

Node.png

球面座標上に平面を投影します。Wikipedia-極座標系
Sphere.png

vector in = @P;
float r = 1.0;
vector out;

float angle1 = lerp(0.0, 2.0 * $PI, in.z);
float angle2 = lerp(0.0, $PI, in.x);

out.x = r * cos(angle1) * sin(angle2);
out.z = r * sin(angle1) * sin(angle2);
out.y = r * cos(angle2);

@P = out;

上端と下端を切り取った球

SphereLack_ (2).png

vector in = @P;
float r = 1.0;
vector out;

float angle1 = lerp(-$PI, $PI, in.z) ;
float angle2 = lerp(0.3 * $PI, (1.0-0.3) * $PI, in.x);

out.x = r * cos(angle1) * sin(angle2);
out.z = r * sin(angle1) * sin(angle2);
out.y = r * cos(angle2);

@P = out;

チューブ

円柱座標に平面を投影します。Wikipedia-極座標系
Tube_.png

vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;

ねじれたチューブ

TubeTwist.png

vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;
float rotate_rate = -0.2;
angle += 2.0 * $PI * rotate_rate * in.z;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;

頂点が下寄りのチューブ

TubeUnder.png

vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * pow(in.z, 2.0);
out.z = r * sin(angle);
@P = out;

コーン

heightで全体の高さ、rのlerp関数のminで下端、maxで上端の半径を指定
Cone.png

vector in = @P;

float angle = lerp(0.0, 2.0 * $PI, in.x);
float height = 0.3;
float r = lerp(0.75, 1.0, in.z);

vector result;
result.x = r * cos(angle);
result.y = height * in.z;
result.z = r * sin(angle);

@P = result;

パラボラアンテナ

height式内のpowの係数、r式内のpowの係数により、形状の調整、頂点位置の調整ができます。
ConeQua_.png

vector in = @P;

float rad = 2.0 * $PI * in.x;
float height = 1.0 * pow(in.z, 2.0 );
float r = 1.0 * pow(in.z, 1);

vector out;
out.x = r * cos(rad);
out.y = height;
out.z = r * sin(rad);

@P = out;

ブラックホール形状

ConeQuadVerse.png

vector in = @P;
float r = 1.0;
vector out;

float angle1 = lerp(-$PI, $PI, in.z) ;
float angle2 = lerp(0.0 * $PI, 0.5 * $PI, in.x);

out.x = r * cos(angle1) * (1.0 - sin(angle2));
out.z = r * sin(angle1) * (1.0 - sin(angle2));
out.y = r * (1.0 - cos(angle2));

@P = out;

リング

rのlerp内のminで内半径、maxで外半径を指定。
Ring_.png

vector in = @P;

float angle = lerp(2.0 * $PI, 0.0, in.x);

float r = lerp(0.5, 1.0, 1.0 * in.z);

vector out;
out.x = r * cos(angle);
out.z = r * sin(angle);
out.y = 0.0;
@P = out;

 

波打ったリング

RingWave_.png

vector in = @P;
vector out;

float rad = lerp(2.0 * $PI, 0.0, in.x);
int num = 6; // 波の数
float wave_height = 0.2; // 波の高さ

float r = lerp(0.8, 1.0, 1.0 * in.z) + lerp(0.0, 0.05, sin(rad));
out.x = r * cos(rad);
out.z = r * sin(rad);
out.y = wave_height * sin(rad * num);

@P = out;

トーラス(ドーナツの形状)

一つのスクリプトだけでも作れますが、分けた見やすいので2つのWrangleに分けて書きました。この2つを連続でつなげてください。
一つ目のスクリプトのrがチューブの太さ、xに足した値d(今回は0.5)が全体の半径になります。

Torus_.png

vector in = @P;
float r = 0.1;
float rad = 2.0 * $PI * in.x;
float d = 0.5;

vector out;
out.x = r * cos(rad) + d;
out.y = r * sin(rad);
out.z = in.z;
@P = out;
vector in = @P;
float r = in.x;
float rad = in.z * $PI * 2.0;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;

内側が欠けたトーラス

TorusLack_.png

vector in = @P;
float r = 0.1;
float rad = lerp(-0.5 * $PI, 0.5 * $PI, in.x);

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = @P.z;
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;

トーラス上にリボン

TorusTwist (2).png

vector in = @P;

float r = 0.2; //トーラスの太さ(0 <r < 0.5)
float rad = 0.5 * $PI * in.x ;

float rotate_num = 8.0;
rad += rotate_num * 2.0 * $PI * @P.z;

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = @P.z;
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;

ねじれたトーラス(ドーナツの形状)

twist_numでねじれ数を指定可能。

TorusTwist_.png

vector in = @P;
float r = 0.03;
float rad = 2.0 * $PI * in.x ;
float twist_num = 3.0; //ねじれ数
rad += twist_num * 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad) + 0.5;
out.y = r * sin(rad);
out.z = in.z;
@P = out;
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;

Slash_.png

vector in = @P;
float r = 0.1;
float height_rate = cos(lerp(-0.5 * $PI, 0.5 * $PI, in.z));
float rad = 1.0 * $PI * (in.x-0.5) * height_rate;

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = in.z;
vector in = @P;
float r = in.x;
float rad = 1.0 * $PI * in.z;

@P.x = r * cos(rad);
@P.y = in.y;
@P.z = r * sin(rad);

スライダーで値を調整

これ以降のスクリプトは、chfを用いて係数をスライダーで変更可能にしています。
chfを含んだスクリプトを書いた後、以下のボタンを押すとスクリプト下に値を変更可能なスライダーが現れます。
rapture_20170819144614.png

また、全ての係数の初期値が0なので、正しく設定しないと何も表示されないので注意してください。

係数によってチューブにもリングにもできる形状

rapture_20170819145458.png

  • 係数例
    rapture_20170819145512.png
vector in = @P;
float rotate_num = chf("rotate_num");
float height = chf("height");
float radius_bottom = chf("radius_bottom");
float radius_top = chf("radius_top");
float radius = lerp(radius_bottom, radius_top, pow(in.z, chf("height_pow_rate")));
float angle = 2.0 * $PI * in.x
+ 2.0 * $PI * rotate_num * in.z;

vector out;
out.x = radius * cos(angle);
out.z = radius * sin(angle);
out.y = height * in.z;
@P = out;

螺旋リボン

rapture_20170819145008.png

  • 係数例
    rapture_20170819145344.png
vector in = @P;
in.x = lerp(chf("in_start"), chf("in_end"), in.x);
float radius = lerp(chf("radius_bottom"), chf("raidus_top"), in.x) 
+ chf("radius_z_rate") * in.z
+ chf("n_height") * sin($PI * in.z)
;
float angle = 2.0 * $PI * in.x * chf("rotate_num");

vector out;
out.x = radius * cos(angle);
out.z = radius * sin(angle);
out.y = in.z * chf("zrate") + in.x * chf("xrate");
@P = out;

エフェクト用メッシュとして使うために

上記スクリプトでは書いていませんが、エフェクト用メッシュとして使う時は、各頂点のAlphaアトリビュートに適当な値を書き込んで出力してから使っています。(リングでは端に行くほど透明になる、チューブで上に行くほど透明になるなど)
FBXを出力する際にAlphaアトリビュートを書き込むには、間にColorを挟む必要があります。(不具合?)
TubeAlpha.png

vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;
@Alpha = 1.0 - pow(@P.y, 0.5);

rapture_20170422221549.png

関連機能

SideFX LabsのCylinder Generator, Sphere Generator, Disc Generatorを使うことによって、UV付きのエフェクト用メッシュを作成することができます。
チュートリアル動画
SideFX Labs ツールリスト

38
22
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
22