2. 座標系と変形


2. 座標系と変形

3次元空間で物体などを配置する場合、まず最初に理解しなければならないのは座標系である。 また、物体やテクスチャなどの変形にも座標系は密接に関わる。 このセクションではPOV-Rayの座標系と変形について説明する。


2.1 座標系

物体、光源、カメラは、3次元座標系を用いて配置する。 3次元座標系には左手座標系と右手座標系がある。 左手座標系では+xを右方向とすると、+yが高さ方向、+zが画面の奥行方向となり(図2.1a)、右手座標系では+xを右方向とすると、+yが奥行方向、+zが高さ方向となる(図2.1b)。 また、回転方向は親指を軸の+方向としたときに他の指が巻きつく方向になるが、これも右手系と左手系では逆向きになる(図2.1c、図2.1d)。

POV-Rayのデフォルト座標系は左手系である。 過去においてはCG分野では左手座標系が使われてきたが、現在では右手系が標準となっている。このマニュアルでも、特に記述がない限りすべて右手座標系を標準として説明する。

図2.1a 左手座標系 図2.1b 右手座標系

図2.1c 左手系の正の回転方向 図2.1d 右手系の正の回転方向

左手座標系から右手座標系に変換するためには、カメラ・ステートメントの中で

right{-1.33, 0, 0}

を指定すればよい。 詳細は「5.1 座標系の変換」を参照せよ。

座標系内の位置は、通常3成分ベクトルによって指定する。 3つの成分はそれぞれ x、y、zの値に相当する。 例えば、ベクトル<1,2,3>は、原点<0,0,0>から右に1、奥に2、上に3の位置となる。

ベクトルは位置を表すだけではない。 サイズの指示や移動・回転、また物体に適用するテクスチャ修正などにも使用する。
2.2 変形

通常POV-Rayでは変形として、scale、rotate、translateを使用する。 これらは物体やテクスチャを拡大・縮小、回転、移動させる。 また、matrixを使って複雑な変形を一度に指定することもできる。

2.2-1 拡大・縮小(scale)

scaleは物体やテクスチャをスケール(拡大・縮小)するために使用する。

< scale の構文>

scale <VECTOR>
scale 拡大・縮小を指定するキーワード
< VECTOR > x, y, zそれぞれの方向にどれだけスケールするかを指定するベクトル。各成分には実数値を指定する。1より小さい値は縮小、1より大きい値は拡大することを意味する。 0を指定した成分には1が適用される。

scaleは対象物のサイズに比例する(その対象物がすでにscaleを使ってサイズを変えられていれば、その新しいサイズに比例する)。 複数の scale を使うこともできる。

※ スケールは常に原点<0, 0, 0>から対象物までの距離に比例して行われる。 原点以外の位置でスケールを行うと物体の位置も変わってしまうので注意が必要である(図2.2-1)。

図2.2-1 スケールは原点からの距離に比例する
上図の例)

          box{<0.5,0.5,0.5>,<1.5,1.5,1.5> scale 3}



                          ↓



          box{<1.5,1.5,1.5>,<4.5,4.5,4.5>}

※scale 3はscale<3,3,3>に変換される。

2.2-2 回転(rotate)

rotate は物体やテクスチャを回転させるために使用する。

< rotate の構文>

rotate <VECTOR>
rotate 回転を指定するキーワード
<VECTOR> 回転量を指定するベクトル。 各成分にはx、y、z各軸まわりでの回転角(°)を実数値で指定する。※ 回転方向については「2.1 座標系」を参照

回転は常に軸まわりで行われるため、対象物が回転軸から離れていると結果の位置が予測しにくくなる。 また通常回転は、(x軸まわり)→(y軸まわり)→(z軸まわり)の順で行われるが、x、y、zが同じ角度であっても、回転する順序によって結果の位置が変わることもある。 例えば、" Text_R " という物体を回転させる場合、

       object {

         Text_R

         rotate <60,30,-90>   // x軸まわりに60°、y軸まわりに30°、z軸まわりに-90°回転

       }



と



       object {

         Text_R

         rotate z*-90   // z軸まわりに-90°回転

         rotate y*30    // y軸まわりに 30°回転

         rotate x*60    // x軸まわりに 60°回転

       }

では下図のように結果の位置が異なる(両図とも奥のRが元の位置)。

rotate <60, 30, -90> rotate z*-90 rotate y*30 rotate x*60
図2.2-2 回転の順番による違い

以上のことから、複雑な回転を指定する場合は次の手順で行うべきである。

1. 対象物を原点<0,0,0>に置く。
2. わかりやすい順序で、各軸ごとに分けて回転させる。

2.2-3 移動(translate)

translateは、物体やテクスチャを移動させるために使用する。

< translate の構文>

translate <VECTOR>
translate 移動を指定するキーワード
<VECTOR> 対象物がどれだけ移動するかを指定するベクトル。 各成分にはx、y、z各軸方向の移動量(移動先の座標ではない)を実数値で指定する。

図2.2-3 物体の移動
上図の例)

          sphere { <-3,-2,-1>>, 1

            pigment { White }

            translate <6,3,4>

          }

この例の場合、<-3,-2,-1>に置かれた球をtranslate <6, 3, 4> によって<-3+6, -2+3, -1+4>つまり <3, 1, 3> に移動することになる。

また、次のように各軸ごとに移動を指定することもできる。 1つの軸方向だけに移動させたい場合はこちらの方が便利である。

例)

          sphere { <0,0,0>, 1

            pigment { White }

            translate 6*x        // +x軸方向だけに6移動する。

          }

2.2-4 行列(matrix)

matrixは、物体やテクスチャに変形行列を指定することによって、複雑な変形を一度に行うために使用する。

< matrix の構文>


 matrix <m00, m01, m02,

         m10, m11, m12,

         m20, m21, m22,

         m30, m31, m32 >

matrix 変形行列を指定するキーワード
m00〜m32 4 x 4の行列式の各成分を実数表現で指定する。
※4列目は<0,0,0,1>に設定されている。

matrixを使った場合、点P : P=<px, py, pz>は次の式によって点Q : Q=<qx, qy, qz>に変換される。

qx = m00 * px + m10 * py + m20 * pz + m30
qy = m01 * px + m11 * py + m21 * pz + m31
qz = m02 * px + m12 * py + m22 * pz + m32

次の例の変形行列によって<2,1,2>に置かれた半径1の球が、図2.2-4(右)のように変形する。

例)

          object {

            sphere{<2,1,2>,1

            matrix <1, 1, 0,

                    0, 1, 0,

                    1, 0, 1,

                    0, 0, 0>

          }

変形前 変形後
図2.2-4 変形行列(matrix)による変形


2.3 変形の順序

複数の変形を組みあわせる場合は変形の順序に気をつけなければならない。 変形は原則としてscale → rotate → translateの順で行うべきである。 対象物は各軸まわりで回転し、原点からの距離に比例してスケールされるため、順序を間違えると全く予期しない位置に移動してしまうことがある。 特にrotateとtranslate、またはscaleとtaranslateを組みあわせる場合は注意すべきである。

rotateとtranslateを使う場合

図2.3a rotateとtranslateの順序による違い

手前左:元の位置、右下奥:例1の結果の位置、中央奥:例2の結果の位置

原点に置かれたText_Rという物体(図2.3aの左手前)を、y軸まわりに90°回転させて座標<1,2,3>に移動させる場合、次の例1のように指定するのは間違いである。

例1)

          object{Text_R

            translate<1,2,3>   // 先に移動

            rotate y*90

          }

これでは図のように全く違う位置に移動してしまう(図の右下奥で床に埋まっているR)。 正しい指定は次の例2である。

例2)

          object{Text_R

            rotate y*90    // 先に回転

            translate<1,2,3>

          }

scaleとtranslateを使う場合

原点に置かれたText_Rという物体(図2.3bの左下)を、2倍に拡大して座標<1,-2,1>に移動させる場合、例3のように指定するのは間違いである。

図2.3b scaleとtranslateの順序による違い

左下:元の位置、中央:例2の結果の位置、右上:例1の結果の位置

例3)

          object{Text_R

            translate <1,-2,1>   // 先に移動

            scale 2

          }

スケールは対象物の原点からの距離に比例するため、translate <1,-2,1>に比例して物体を拡大し、図のように別の位置に移動させてしまう(図の右上のR)。 正しい指定は次の例4である。

例4)

          object{Text_R

            scale 2    // 先に拡大

            translate<1,-2,1>

          }

scaleとrotateを使う場合

対象物が原点にあればスケールと回転の順序によってその位置が変わることはないが、次の例のように不均一なスケールを行う場合は、その順序によって形状が変化する。


例5)



 object{Text_R

   rotate <30,-90,60>   // 先に回転           

   scale <2,3,1>

 }



 回転を先にした場合


例6)



 object{Text_R

   scale <2,3,1>   // 先にスケール           

   rotate <30,-90,60>

 }

 スケールを先にした場合

図2.3c rotateとscaleの順序による違い

以上のことから、複数の変形を適用する場合は、

(1) まず物体を原点<0,0,0>に置き、
(2) scale → rotate → translate

の順で原則として行うとよい。


2.4 変形識別子

変形識別子を使ってシーン・ファイルを読みやすくすることができる。 また、パラメータとして使用することもでき、1つの宣言の変形を変えることによって、その宣言に関連する多くの変形を一度に変えることができる。

識別子は次のようにtransformのキーワードを使って宣言する。

#declare IDENTIFIER = transform { TRANSFORMATION... }

IDENTIFIER は 40文字以下の名前であり、TRANSFORMATION... は1つ以上のtranslate、rotate、scale、matrix、または前に宣言された変形識別子である。

変形識別子の呼び出しは、キーワードtransformの後に識別子を直接記述すればよい(括弧で囲む必要はない)。

例)

          #declare MyTrans = transform{rotate x*90 scale 1.5 translate <0,2,3>}



          object {

            MyObject             // 物体識別子MyObject

            transform MyTrans    // 変形 MyTrans の適用

          }

多くの要素をもつ複雑なCSG物体では、translate、rotate、scale、matrixを個別に指定するとシーンの解析に時間がかかるため、同じ変形を使う場合は識別子として宣言して使用したほうがよい(これは解析のみに影響し、レンダリングには影響しない)。


2.5 テクスチャと物体の変形

テクスチャを貼り付けた物体を変形させると、そのテクスチャは物体の形状と一緒に変形する。 しかし、テクスチャを貼り付ける前に物体を変形させると、そのテクスチャは変形せず物体の形状だけが変形する。 また、テクスチャ・ステートメントの中で変形を行った場合はテクスチャだけが変形し、物体そのものは変形しない。


左から順に、元の球、球全体の拡大、球形だけ拡大、テクスチャだけ拡大

図2.5 変形の指定位置による違い

例)

         #declare Check =

            texture{ pigment{checker White, color rgb<0.5,0.7,0.5> scale 0.5}

                     finish{phong 1 reflection 0.1}

             }



          sphere { 0, 1

            texture { Check }

            scale 3           // 全体を拡大

          }



          sphere { 0, 1

            scale 3           // 球だけを拡大

            texture { Check }

          }



          sphere { 0, 1

            texture {

              Check

              scale 3         // テクスチャだけを拡大

            }

          }

変形はカラー・パターンとノーマル・パターンに個別に指定することができる。

※ ノーマル・パターンをスケールする場合は、凹凸の広さと間隔にしか影響しない(見 かけ上の凹凸の高さや深さは変化しない)。 ⇒「12.2 ノーマル」参照。

例)

          box { <0, 0, 0>, <1, 1, 1>

            texture {

              pigment {

                checker Red, White

                scale 0.25      // カラー・パターンだけをスケールする。

              }

              normal {

                bumps 0.3       // 見かけの凹凸の高さの指定。

                scale 0.2       // 凹凸の直径と間隔だけをスケールする(高さとカラー・パ

              }                 // ターンには全く影響しない)。

              rotate y*45       // テクスチャ全体を回転させる(物体そのものは回転しない)。

            }

          }