前回は, 複数の単純形状物体の組み合わせによる複雑・固定形状の作成方法を学んだ.
今回は,さらに進めて, 類似・可変形状(同種ではあるが個体や状況によって変化する形状)について 効率的な定義方法を学ぼう. そして,アニメーションを自動生成してみよう.
前回学んだ通り,#declare を利用することで, モデリングの作業を効率化できる:
#declare 物体名 = CSG演算 { ... } object { 物体名 変換 }
例えば,自動車を効率的に作る場合:
CSG演算 { object { ... } object { ... } object { ... } ... translate 前左 } CSG演算 { object { ... } object { ... } object { ... } ... translate 前右 } CSG演算 { object { ... } object { ... } object { ... } ... translate 後左 } CSG演算 { object { ... } object { ... } object { ... } ... translate 後右 }
#declare タイヤ = CSG演算 { object { ... } object { ... } object { ... } ... } object { タイヤ translate 前左 } object { タイヤ translate 前右 } object { タイヤ translate 後左 } object { タイヤ translate 後右 }
このように,類似形状の物体を複数個使う場合には, #declare を使えば,CSG 演算の記述回数が減り, 作業を素早く楽に進めることができるようになる.
ただし,#declare が有効に使えるのは, 物体同士の形状の違いが全体的に均等な場合(相似形)に限られる. (要するに,少品種大量生産しか向いていない.) 形状の違いが部分的に不均等な場合には使えない.
失敗例として,前回の鉄アレイと灰皿を流用して, 大きさの異なるものを作ってみよう:
シーンファイル dumbbell.pov:(ダウンロード)
... // 鉄アレイの定義 #declare Dumbbell = merge { ... } // 鉄アレイの配置 object { Dumbbell // 標準の鉄アレイ pigment { color Brown } } object { Dumbbell scale 0.5 // 軽い鉄アレイ? translate -2.0*z pigment { color Navy } } ...
一見,成功しているように見えるかもしれないが, よく観察してみよう.
シーンファイル ashtray.pov:(ダウンロード)
... // 灰皿の定義 #declare AshTray = difference { ... } // 灰皿の配置 object { AshTray // 標準の灰皿 translate -2.5*x pigment { color Silver } } object { AshTray scale 3*y // 深い灰皿? translate 2.5*x pigment { color Gold } } ...
上の例と同様,よく観察してみよう.
これらのように,全体的な変形だけでは,不自然なことになってしまう場合がある. しかし,改めて別形状(重さの異なる鉄アレイや深さの異なる灰皿など)として 定義し直すことも面倒である.
モノづくりの効率化を考える場合,勤勉は邪魔になる. 面倒を感じて,楽に済ます方法を考えよう. 不常識・非真面目に取り組もう.
どちらも不適切だ.
一方,非真面目な人々は,複雑な問題を単純な方法で解決しようとする. 簡単ではないが,成功すれば,ローコスト・ハイバリューですね.
物体形状が部分的に異なる場合 (ある部分だけは異なるが,他の部分は同じ場合... 要するにバリエーション展開の場合)には, #declare ではなく, #macro を使うと非常に便利である:
#macro 物体名(引数, ...) CSG演算 { ... 引数 ... } #end object { 物体名(引数, ...) }
#macro では, 一般的なプログラミング言語(Cや Java 等)の関数定義と同様に, 変化する部分を引数(変数など)によって制御することがポイントである.
変数の名前は,何でもよいが,予約語(特殊変数名や命令語)と重複すると NG. POV-Ray では,多くの予約語があるので, トラブル防止のために,変数名をすべて大文字にするのがよい. (すべて大文字からなる予約語はないので安心.)
#declare と #macro の書き方の違いとして, 「=」や「#end」の有無にも注意が必要.
では,ashtray.pov を元にして,次のように書き変えてみよう:
... // 灰皿のマクロ定義(深さ HEIGHT) #macro AshTray(HEIGHT) difference { difference { object { Disk_Y scale <2.0, 0.5, 2.0> } // 本体 object { Disk_Y scale <1.8, 0.5, 1.8> translate <0.0, 0.2, 0.0> } // 内側 scale HEIGHT*y // 本体の高さを可変に(全体的な形状が可変) } merge { object { Disk_X scale <3.0, 0.2, 0.2> } // 切込 object { Disk_Z scale <0.2, 0.2, 3.0> } // 切込 translate HEIGHT*0.5*y // 切込の位置を可変に(部分的な形状は不変) } } #end // 灰皿の配置 object { AshTray(1) // 標準の灰皿 translate -2.5*x pigment { color Silver } } object { AshTray(3) // 深い灰皿 translate 2.5*x pigment { color Gold } } ...
説明するまでもないだろうが..., 変数 HEIGHT が 1 や 3 に置き換えられて, 2個の AshTray が描かれることになる.
この通り,本体の寸法だけが異なり, 切込部の形状は同じであることがわかる.
POV-Ray では,一般的なプログラミング言語と同様に,変数や計算式も利用できる. これは,物体の大きさや配置などを調整する際に便利である.
例えば,変数に計算結果を代入するには:
#declare 変数 = 計算式;
この「計算式」には, 四則演算{ +, -, *, / }の他, 一般的な数学関数{ sin( ), cos( ), sqrt( ), 等 } も利用できる. 詳しくは, マニュアル 1「言語の基本」を参照せよ.
なお,このように #declare された変数は, それ以降,そのシーンファイル全体に通用する. もし,マクロ内だけで通用する変数が欲しければ, #declare の代わりに, マクロ定義の内部で #local を使えばよい. より詳しくは,次回説明予定.
変数を利用したカップの定義例:(#declare版)
... #declare H = 1.5; // 高さ #declare R = 1.0; // 外径 #declare T = 0.1; // 厚み #declare RI = R - T; // 内径 #declare Cup = difference { object { Disk_Y scale <R, H, R> } object { Disk_Y scale <RI, H, RI> translate y*T } } object { Cup pigment { ... } translate { ... } } ...
変数を利用したカップの定義例:(#merge版)
... #macro Cup(H, R, T) #local RI = R - T; // 内径 difference { object { Disk_Y scale <R, H, R> } object { Disk_Y scale <RI, H, RI> translate y*T } } #end object { Cup(1.5, 1.0, 0.1) pigment { ... } translate { ... } } ...
寸法等について,数値そのものを使うより,変数として名前を付けておけば, CSG演算の意味が分かり易く,形状の仕上がりが予想し易くなる. 要するに生産性が向上する.
特別な変数 clock を使うと, 簡単にパラパラアニメ用の連番画像ファイル群を生成できる. この変数の値は,レンダリング時に,0.0 〜 1.0 の間で自動的に変化する. ソースコード記述例:
object { ... rotate clock*360*y // 0度〜360度の間で回転 }
レンダリング例:
$ ls anim.pov $ povray +KFI0 +KFF20 anim.pov # 0〜20 コマの画像を生成 $ ls *.png anim00.png anim01.png anim02.png ... anim20.png
なお,povray コマンドの オプション +KFI および +KFF は, Key Frame(パラパラアニメの各コマ)の Initial(最初)および Final(最後)という意味であり, パラメータとしてフレーム番号を指定する. フレーム番号とクロック値の関係については, 教科書 ch.10 や マニュアル 15「アニメーション」を参照せよ.
動画ファイル作成例:
$ convert -delay 10 anim*.png anim.gif # PNG画像列からGIFアニメを生成 $ animate anim.gif # GIFアニメを再生 # または $ animate -delay 10 anim*.png # PNG画像列をアニメとして再生
なお,convert および animate コマンドの オプション -delay の後の数値は, フレーム間の遅延時間(単位:cs = センチ秒 = 1/100 秒)である.
![]() |
![]() |
また,上図左(回る灰皿たち)のように循環的な (clock=0.0 の画像と clock=1.0 の画像とが等しくなるような) アニメーションを生成するには, povray コマンドにオプション +KC も指定すること. これは Cyclic(循環的)を意味し,数値パラメータを伴わない. もし,これを指定しないと,同じ内容のフレーム(最後と最初)が2コマ連続し, その時間だけアニメが一瞬止まったかのように見えることになってしまう.
さらに,フレーム数を変えて再びレンダリングする場合には, レンダリングの前に,すべての画像ファイルを消しておくこと:
$ rm -f anim*.png # PNGファイルを削除.-f は「強制的(forcedly),問答無用」に削除の意味.要注意.
これを怠ると,アニメ化の際,フレーム順序が乱れてしまうだろう.
#macro および #declare を駆使して, 類似形状or可変形状の物体を効率的に定義せよ. もし余裕があれば,さらにそれをアニメ化せよ.
物体の例:
階層的な定義による作品例:
適度に複雑な形状をもち, かつバリエーション展開が可能な物体を独自に設計し, #macro で定義せよ. そして,その物体の複数(2個以上)のバリエーションを並べてレンダリングせよ.
(もし余裕があれば,アニメーションも作成せよ.)
担当教員へレポートを送信せよ: