POV-Rayでのobjectと変形

# はじめに
これは [POV-Rayによる数学お絵かき入門 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/povray4math) の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`を使います.

```Povray
#declare obj1=box{<0,0,0>,<1,1,1>}
object{
	obj1
	pigment{rgb<1,0,0>}
}
```

![](https://i.imgur.com/Mcmz7Hx.png)

このように`object`は`{}`内の引数としてオブジェクトを取り, 省略可能な引数として`pigment`なども与えられます.

`object`は何度重ねても問題ありませんが, 次のように書けば`pigment`が上書きされます.
`pigment`を上書きさせないためには`union`を使います. (後述)

```Povray
#declare obj1=box{<0,0,0>,<1,1,1>}
object{
	object{
		obj1
		pigment{rgb<1,0,0>}
	}
	pigment{rgb<0,1,0>}
}
```

![](https://i.imgur.com/VfRzP6d.png)

# transformation
POV-Rayにはオブジェクトの移動や変形に関する命令も用意されています.
こちらも`object`を使います.

## scale
原点中心の拡大縮小には`scale`を使います.
`scale`の挿入位置は`pigment`と基本的には同じで, 次のように書きます.

```Povray
object{
	OBJECT
	scale <VECTOR>
}
```

ここで`<VECTOR>`には3次元のベクトルが入り, それぞれの成分が$x, y, z$方向の伸縮に対応します.
[以前述べたように](https://qiita.com/Hyrodium/items/7fb5d257e292eb81b64e#%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E3%81%AE%E8%A7%A3%E9%87%88)POV-Rayではベクトルの代わりに数値を入れる事も可能でしたから, その場合は単なる原点中心の相似拡大縮小となります.

### 具体例
次の例では, 座表軸の向きが分り易いように3つの`cylinder`を配置しています.

```Povray
#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>}}
```

![](https://i.imgur.com/XrkHbOX.png)


## translate
平行移動のための命令が`translate`です.
構文は上記`sacle`と同様で, `<VECTOR>`で指定したベクトルで平行移動します.

### 具体例
```Povray
#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>}}
```

![](https://i.imgur.com/3Me9mhP.png)

## rotate
$x,y,z$軸周りの回転を表す命令が`rotate`です.
構文もやはり上記と同様なのですが,

* 角度が度数法で指定されること
* $SO(3)$が非可換であること

に注意が必要です.

### 具体例
まずは簡単な例を述べましょう.

```Povray
#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>}}
```

![](https://i.imgur.com/BAx6RyX.png)

このように, 変形後のオブジェクト(緑色)が$x$軸(赤色)周りに$45^\circ$回転しています.

さて, [前に少し触れましたが](https://qiita.com/Hyrodium/items/bc5d6f5234af548d6a49#%E8%A7%A3%E8%AA%AC-1), POV-Rayではデフォルトで左手系なので, 少し紛らわしい例になっていました.
右手系に変更する話は次回とします.

### SO(3)の非可換性
`<VECTOR>`で指定したベクトルを回転軸としてオブジェクトが回転される訳ではありません.

次の2つの`rotate`の例はPOV-Rayでは等価に解釈されます.

```Povray
object{
	OBJECT
	rotate <a,b,c>
}
```

```Povray
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>`を表す組み込み定数として扱われるため, 次にようにも書けます.

```Povray
object{
	OBJECT
	rotate a*x
	rotate b*y
	rotate c*z
}
```

## matrix
以上では`scale`, `translate`, `rotate`の3つの変形を扱いましたが, これらを含む最も一般的な変形([アフィン変換](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%95%E3%82%A3%E3%83%B3%E5%86%99%E5%83%8F))が`matrix`です.
数式で書けば

```math
\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では次のように書きます.

```Povray
object{
	OBJECT
	matrix <a1, a2, a3,
	b1, b2, b3,
	c1, c2, c3,
	d1, d2, d3>
}
```

# union
複数のオブジェクトをまとめて

* 色の変更
* 移動, 変形

をするためには`union`を使います.
`union`は複数のオブジェクトをまとめて扱うための命令で, 次のように書きます.

```Povray
union{
	OBJECT1
	OBJECT2
	..
	OBJECTn
}
```

## 具体例
```Povray
#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>}
}
```

![](https://i.imgur.com/KgUj3qL.png)

この例では`union`で3つのオブジェクトを1つにまとめて`pigment`で着色しています.
`union`の内側で予め色が指定されている場合は外側の`pigment{rgb<1,0,0>}`で色は変更されませんが, 色が未定義となっている3つ目のオブジェクトには赤色が着色されています.

`pigment`と同様に変形の指定をここで行う事も可能です.