はじめに
これは POV-Rayによる数学お絵かき入門 Advent Calendar 2017 の7日目の記事です.
これまでに説明したように, POV-Rayでは次のようにオブジェクトを宣言できるのでした.
#declare obj1=box{<0,0,0>,<1,1,1>}
しかし, obj1
の色を後から変更したい/色を変えて複数並べたい場合の方法はまだ記述していませんでした.
今日はこの事について書きます.
公式ドキュメントでは以下が近いです.
http://www.povray.org/documentation/3.7.0/r3_4.html#r3_4_5
http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_1_12
object
これを実現するためにはobject
を使います.
#declare obj1=box{<0,0,0>,<1,1,1>}
object{
obj1
pigment{rgb<1,0,0>}
}
このようにobject
は{}
内の引数としてオブジェクトを取り, 省略可能な引数としてpigment
なども与えられます.
object
は何度重ねても問題ありませんが, 次のように書けばpigment
が上書きされます.
pigment
を上書きさせないためにはunion
を使います. (後述)
#declare obj1=box{<0,0,0>,<1,1,1>}
object{
object{
obj1
pigment{rgb<1,0,0>}
}
pigment{rgb<0,1,0>}
}
transformation
POV-Rayにはオブジェクトの移動や変形に関する命令も用意されています.
こちらもobject
を使います.
scale
原点中心の拡大縮小にはscale
を使います.
scale
の挿入位置はpigment
と基本的には同じで, 次のように書きます.
object{
OBJECT
scale <VECTOR>
}
ここで<VECTOR>
には3次元のベクトルが入り, それぞれの成分が$x, y, z$方向の伸縮に対応します.
以前述べたようにPOV-Rayではベクトルの代わりに数値を入れる事も可能でしたから, その場合は単なる原点中心の相似拡大縮小となります.
具体例
次の例では, 座表軸の向きが分り易いように3つのcylinder
を配置しています.
#declare obj2=box{<.1,.1,-.1>,<.9,.9,-.9>}
object{
obj2
pigment{rgb<1,0,0>}
}
object{
obj2
scale 1.5
pigment{rgb<0,1,0>}
}
cylinder{<0,0,0>,<1,0,0>,0.1 pigment{rgb<1,0,0>}}
cylinder{<0,0,0>,<0,1,0>,0.1 pigment{rgb<0,1,0>}}
cylinder{<0,0,0>,<0,0,1>,0.1 pigment{rgb<0,0,1>}}
translate
平行移動のための命令がtranslate
です.
構文は上記sacle
と同様で, <VECTOR>
で指定したベクトルで平行移動します.
具体例
#declare obj2=box{<.1,.1,-.1>,<.9,.9,-.9>}
object{
obj2
pigment{rgb<1,0,0>}
}
object{
obj2
translate <0,0,1>
pigment{rgb<0,1,0>}
}
cylinder{<0,0,0>,<1,0,0>,0.1 pigment{rgb<1,0,0>}}
cylinder{<0,0,0>,<0,1,0>,0.1 pigment{rgb<0,1,0>}}
cylinder{<0,0,0>,<0,0,1>,0.1 pigment{rgb<0,0,1>}}
rotate
$x,y,z$軸周りの回転を表す命令がrotate
です.
構文もやはり上記と同様なのですが,
- 角度が度数法で指定されること
- $SO(3)$が非可換であること
に注意が必要です.
具体例
まずは簡単な例を述べましょう.
#declare obj2=box{<.1,.1,-.1>,<.9,.9,-.9>}
object{
obj2
pigment{rgb<1,0,0>}
}
object{
obj2
rotate <45,0,0>
pigment{rgb<0,1,0>}
}
cylinder{<0,0,0>,<1,0,0>,0.1 pigment{rgb<1,0,0>}}
cylinder{<0,0,0>,<0,1,0>,0.1 pigment{rgb<0,1,0>}}
cylinder{<0,0,0>,<0,0,1>,0.1 pigment{rgb<0,0,1>}}
このように, 変形後のオブジェクト(緑色)が$x$軸(赤色)周りに$45^\circ$回転しています.
さて, 前に少し触れましたが, POV-Rayではデフォルトで左手系なので, 少し紛らわしい例になっていました.
右手系に変更する話は次回とします.
SO(3)の非可換性
<VECTOR>
で指定したベクトルを回転軸としてオブジェクトが回転される訳ではありません.
次の2つのrotate
の例はPOV-Rayでは等価に解釈されます.
object{
OBJECT
rotate <a,b,c>
}
object{
OBJECT
rotate <a,0,0>
rotate <0,b,0>
rotate <0,0,c>
}
つまり, POV-Rayでは$x$軸の回転→$y$軸の回転→$z$軸の回転と順に行います.
そのため, コードの可読性を考えればrotate
を使う際には標準基底の定数倍を指定する方が良いです.
また, POV-Rayではx
, y
, z
がそれぞれ<1,0,0>
, <0,1,0>
, <0,0,1>
を表す組み込み定数として扱われるため, 次にようにも書けます.
object{
OBJECT
rotate a*x
rotate b*y
rotate c*z
}
matrix
以上ではscale
, translate
, rotate
の3つの変形を扱いましたが, これらを含む最も一般的な変形(アフィン変換)がmatrix
です.
数式で書けば
\begin{align}
\begin{pmatrix}
x' \\
y' \\
z'
\end{pmatrix}
=
\begin{pmatrix}
a_1 &b_1 &c_1 \\
a_2 &b_2 &c_2 \\
a_3 &b_3 &c_3 \\
\end{pmatrix}
\begin{pmatrix}
x' \\
y' \\
z'
\end{pmatrix}
+
\begin{pmatrix}
d_1 \\
d_2 \\
d_3
\end{pmatrix}
\end{align}
を表す変形で, POV-Rayでは次のように書きます.
object{
OBJECT
matrix <a1, a2, a3,
b1, b2, b3,
c1, c2, c3,
d1, d2, d3>
}
union
複数のオブジェクトをまとめて
- 色の変更
- 移動, 変形
をするためにはunion
を使います.
union
は複数のオブジェクトをまとめて扱うための命令で, 次のように書きます.
union{
OBJECT1
OBJECT2
..
OBJECTn
}
具体例
#declare obj1=box{<0,0,0>,<1,1,1>}
union{
object{obj1 pigment{rgb<0,1,0>}}
object{obj1 pigment{rgb<0,0,1>} translate <0.2,0.2,-0.2>}
object{obj1 translate <-0.2,-0.2,0.2>}
pigment{rgb<1,0,0>}
}
この例ではunion
で3つのオブジェクトを1つにまとめてpigment
で着色しています.
union
の内側で予め色が指定されている場合は外側のpigment{rgb<1,0,0>}
で色は変更されませんが, 色が未定義となっている3つ目のオブジェクトには赤色が着色されています.
pigment
と同様に変形の指定をここで行う事も可能です.