はじめに
これは 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と同様に変形の指定をここで行う事も可能です.





