はじめに
これは POV-Rayによる数学お絵かき入門 Advent Calendar 2017 の9日目の記事です.
今日の記事ではPOV-Rayでアニメーションを作る方法を述べます.
最初の例
POV-Rayではアニメーションを作るための変数clock
が用意されています.
この変数を使うためにはコマンドライン引数に+KFFn
を与えます. (nには自然数が入ります)
コマンドライン引数はpovray.iniに書けば良い(第3回)のでしたから, 例えば次のように書いてみましょう.
Width=400
Height=300
Antialias=On
+KFF11
このように設定してpovファイルをレンダリングすると, 11枚の連番画像が生成されます.
この連番画像の過程で変化しているパラメータがclock
であり, デフォルトで$0$から$1$までに線形に変化します.
今回の例では連番最初でのclock
の値は0.0
であり, 順に0.1
ずつ増えて連番最後では1.0
の値になっています.
ここで具体例を1つ上げます.
次のコードをレンダリングすると連番画像が得られます.
camera{
location <4,2,4>
look_at <0,0,0>
}
light_source{
<2,3,4>
color rgb<1,1,1>
}
background{rgb<1,1,1>}
sphere{<0,0,clock>,0.2}
次節で連番画像からgifアニメーションに変換方法を述べます.
gifアニメーションの作り方
gifアニメーションへの変換はImageMagicで出来ます.
今回の例ではコマンドラインで次のように入力します.
convert -delay 10 clock1*.png movie.gif
出力画像は次です.
Windowsであればgiamを使えばGUIで作成する事も可能です.
frame_number
ここでclock
と同程度重要なframe_number
, initial_frame
, final_frame
を次に紹介します.
-
frame_number
: 連番画像毎に変わる変数. -
initial_frame
: 連番最初の番号. デフォルトで1
. -
final_frame
: 連番最後の番号.KFFn
で指定したn
.
clock
はデフォルトでは(frame_number-1)/(final_frame-initial_frame)
に等しいです.
frame_number
の有用性は第15回に予定している2重振り子の作例が分り易いと思います.
他のパラメータやアニメーションのコマンドラインオプションに関する情報は以下にあります.
http://www.povray.org/documentation/3.7.0/r3_2.html#r3_2_1
http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_1_5
easing tips
easingとは物体の動きを自然に見せるの手法の事です.
例えば次のサイトが参考になると思います.
http://easings.net/ja
POV-Rayで作るアニメーションでは, 複数の動きを如何にして滑らかに繋ぐかが問題になります.
例えば以下の例では, パラメータに$\sin$を与えて滑らかに繋いでいます.
上の例のような単なる往復に関しては$\sin$で十分でしたが, 次のような複雑な動きを伴う場合にはそう上手く行きません.
(ちなみに, 上画像は$\sum k^3$の可視化です: http://hyrodium.tumblr.com/post/94237657514)
以下では大体の状況で使える便利な関数を紹介します.
\begin{align}
f(x)&=\begin{cases}e^{-\frac{1}{x}} &(x>0) \\0&(x\le 0)\end{cases} \\
g(x)&=\frac{f\left(\frac{2}{\sqrt{3}}x\right)}{f\left(\frac{2}{\sqrt{3}}x\right)+f\left(\frac{2}{\sqrt{3}}(1-x)\right)} \\
h_{(a,b)}(x)&=g\left(\frac{x-a}{b-a}\right)
\end{align}
これらの関数は次の性質があります.
- $f\in C^\infty(\mathbb{R})$が成り立つ.
- $g\in C^\infty(\mathbb{R})$は区間$[0,1]$で単調増加, $(-\infty, 0]$で常に$0$, $[1,+\infty)$で常に$1$を返す.
- $h_{(a,b)}\in C^\infty(\mathbb{R})$は区間$[a,b]$で単調増加, $(-\infty, a]$で常に$0$, $[b,+\infty)$で常に$1$を返す.
Desmosで描いたグラフは次です.
https://www.desmos.com/calculator/6aymjmlpot
関数$g$での$\frac{2}{\sqrt{3}}$は変曲点で滑らかに繋ぐための係数です.
これをPOV-Rayのmacroで書けば次のようになります.
#macro smootha(a)
#if(a>0)
#local b=exp(-1/a);
#else
#local b=0;
#end
b
#end
#macro usmooth(a,b,s)
smootha((2/sqrt(3))*((s-a)/(b-a)))/(smootha((2/sqrt(3))*((s-a)/(b-a)))+smootha((2/sqrt(3))*(1-(s-a)/(b-a))))
#end
このusmooth
が上で定義した$h$に相当します.
関数$h$は区間$(a,b)$で単調増加でかつ, $a,b$において定数関数と滑らかに繋がっているため都合が良いという訳です.
具体例
上から順に
- 等速運動
- 単振動 (正弦関数 $\sin$)
usmooth
のアニメーションです.
この出力のためのコードは次です.
camera{
orthographic
location <0,0,10>
right -3*x
up 1.5*y
sky y
look_at <0,0,0>
}
light_source{
<0,0,10>
color rgb<1,1,1>
parallel
point_at 0
}
background{rgb<1,1,1>}
#macro smootha(a)
#if(a>0)
#local b=exp(-1/a);
#else
#local b=0;
#end
b
#end
#macro usmooth(a,b,s)
smootha((2/sqrt(3))*((s-a)/(b-a)))/(smootha((2/sqrt(3))*((s-a)/(b-a)))+smootha((2/sqrt(3))*(1-(s-a)/(b-a))))
#end
#declare Time=2*clock;
sphere{<2*abs(Time-1)-1,0.5,0>,0.2}
sphere{<cos(pi*Time),0,0>,0.2}
sphere{<1-2*usmooth(0,1,Time)+2*usmooth(1,2,Time),-0.5,0>,0.2}