今回はエクスプレッションを利用して元になるカーブを動かすと、コイルも同様に動くようにしてみよう。
これによって元カーブをアニメーションさせることによってコイルも自動的にアニメーションさせることができる。
エクスプレッションの式が複雑なので注意すること。
global proc makeSpiral7()
{
int $i;
float $numLoops = 10;
string $curv = `curve -d 3 -p 0 0 0 -p 3.0 0 -4.0 -p 7.0 0 -7.0
-p 13.0 0 -5.0 -p 17.0 0 -2.0 -p 19.0 0 0.0
-k 0 -k 0 -k 0 -k 1 -k 2 -k 3 -k 3 -k 3`;
int $numCvs = $numLoops * 4;
string $crv = `curve -degree 3 -p 0 0 0 -k 0 -k 0 -k 0`;
float $min = getAttr ( $curv + ".min" );
float $max = getAttr ( $curv + ".max" );
for( $i = 0; $i < $numCvs; $i++ )
{
curve -append -p ((float)$i) 0 0 $crv ;
}
for( $i = 0; $i <= $numCvs; $i++ )
{
float $p = (float)$i/$numCvs;
float $angle = $p * $numLoops * 6.28;
float $uoff = sin( $angle );
float $voff = cos( $angle );
if( $i == 0 || $i == $numCvs )
{
$uoff = 0;
$voff = 0;
}
$p = $min + ($max - $min) * $p;
string $poc = `pointOnCurve -constructionHistory 1 -parameter $p $curv`;
string $expcom = ( "$nnx = " + $poc + ".nnx;\n"
+ "$nny = " + $poc + ".nny;\n"
+ "$nnz = " + $poc + ".nnz;\n"
+ "vector $nv = << $nnx, $nny, $nnz >>;\n"
+ "$ntx = " + $poc + ".ntx;\n"
+ "$nty = " + $poc + ".nty;\n"
+ "$ntz = " + $poc + ".ntz;\n"
+ "vector $tv = << $ntx, $nty, $ntz >>;\n"
+ "vector $npv = `cross $nv $tv`;\n"
+ "$px = " + $poc + ".px;\n"
+ "$py = " + $poc + ".py;\n"
+ "$pz = " + $poc + ".pz;\n"
+ "vector $pv = << $px, $py, $pz >>;\n"
+ "$vec = $pv + " + $uoff + " * $npv + " + $voff + " * $nv;\n"
+ $crv + ".cp[" + $i + "].xv = $vec.x;\n"
+ $crv + ".cp[" + $i + "].yv = $vec.y;\n"
+ $crv + ".cp[" + $i + "].zv = $vec.z;\n" );
expression -s $expcom;
}
}
int $numLoops = 10;
ループする回数を決める変数。
string $curv = `curve -d 3 -p 0 0 0 -p 3.0 0 -4.0 -p 7.0 0 -7.0
-p 13.0 0 -5.0 -p 17.0 0 -2.0 -p 19.0 0 0.0
-k 0 -k 0 -k 0 -k 1 -k 2 -k 3 -k 3 -k 3`;
コイルの形を決めるためのカーブ。
int $numCvs = $numLoops * 4;
カーブのコントロールポイントの個数を決めている。
string $crv = `curve -degree 3 -p 0 0 0 -k 0 -k 0 -k 0`;
NURBSカーブを作って、その名前を$crvに代入している。
float $min = getAttr ( $curv + ".min" );
カーブのパラメータの最小値。
float $max = getAttr ( $curv + ".max" );
カーブのパラメータの最大値。
for( $i = 0; $i < $numCvs; $i++ )
{
curve -append -p ((float)$i) 0 0 $crv ;
}
このスクリプトではエクスプレッションを使ってコイルを作るのであらかじめ必要な個数のコントロールポイントを作っておく。
for( $i = 0; $i <= $numCvs; $i++ )
$iを0 から$numCvsまで$numCvs + 1 回分ループを実行する。
float $p = (float)$i/$numCvs;
カーブの全体を1.0として$i番目のコントロールポイントのパラメータを求める。
float $angle = $p * $numLoops * 6.28;
コントロールポイントを計算するために現在の角度を計算している。
float $uoff = sin( $angle );
コントロールポイントの計算のための値をsin関数によって求める。
float $voff = cos( $angle );
コントロールポイントの計算のための値をcos関数によって求める。
if( $i == 0 || $i == $numCvs )
{
$uoff = 0;
$voff = 0;
}
$iが0または$numCvsに等しい時(最初と最後)は特別にY,Z座標は0.0にする。
$p = $min + ($max - $min) * $p;
パラメータの最小値・最大値によって$pを計算し直す。
string $poc = `pointOnCurve -constructionHistory 1 -parameter $p $curv`;
カーブ$curvにおけるパラメータ$pの位置の情報を得るコマンド。
(pointOnCurveInfo ノードを返す)
string $expcom = ( "$nnx = " + $poc + ".nnx;\n"
+ "$nny = " + $poc + ".nny;\n"
+ "$nnz = " + $poc + ".nnz;\n"
+ "vector $nv = << $nnx, $nny, $nnz >>;\n"
+ "$ntx = " + $poc + ".ntx;\n"
+ "$nty = " + $poc + ".nty;\n"
+ "$ntz = " + $poc + ".ntz;\n"
+ "vector $tv = << $ntx, $nty, $ntz >>;\n"
+ "vector $npv = `cross $nv $tv`;\n"
+ "$px = " + $poc + ".px;\n"
+ "$py = " + $poc + ".py;\n"
+ "$pz = " + $poc + ".pz;\n"
+ "vector $pv = << $px, $py, $pz >>;\n"
+ "$vec = $pv + " + $uoff + " * $npv + " + $voff + " * $nv;\n"
+ $crv + ".cp[" + $i + "].xv = $vec.x;\n"
+ $crv + ".cp[" + $i + "].yv = $vec.y;\n"
+ $crv + ".cp[" + $i + "].zv = $vec.z;\n" );
エクスプレッションの式を組み立てている。
"$nnx = " + $poc + ".nnx;\n"
"$nny = " + $poc + ".nny;\n"
"$nnz = " + $poc + ".nnz;\n"
カーブ上の点の法線を求める。
(パラメータ$pの位置)
"vector $nv = << $nnx, $nny, $nnz >>;\n"
法線のベクトルを作る。
"$ntx = " + $poc + ".ntx;\n"
"$nty = " + $poc + ".nty;\n"
"$ntz = " + $poc + ".ntz;\n"
カーブ上の点の接線を求める。
(パラメータ$pの位置)
"vector $tv = << $ntx, $nty, $ntz >>;\n"
接線のベクトルを作る。
"vector $npv = `cross $nv $tv`;\n"
法線と接線の外積を求める。
"$px = " + $poc + ".px;\n"
"$py = " + $poc + ".py;\n"
"$pz = " + $poc + ".pz;\n"
カーブ上の点の座標を求める。
(パラメータ$pの位置)
"vector $pv = << $px, $py, $pz >>;\n"
座標のベクトルを作る。
"$vec = $pv + " + $uoff + " * $npv + " + $voff + " * $nv;\n"
コイルのコントロールポイントの位置を表すベクトルを計算。
$crv + ".cp[" + $i + "].xv = $vec.x;\n"
$crv + ".cp[" + $i + "].yv = $vec.y;\n"
$crv + ".cp[" + $i + "].zv = $vec.z;\n" );
コイルのカーブにおける$i番目のコントロールポイントの座標に$vecの値を代入する。
expression -s $expcom;
$expcomに入っている式によってエクスプレッションを定義する。