【事前学習】 前回までの内容を再確認しておきましょう。
座標変換(空間)
Coordinate Transformation
本章では行列による座標変換(空間)について学ぶ。
一次変換
変換後の値が変換前の値の重み付き和となっている。原点を中心とする拡大縮小、座標軸対称、原点対象、原点周りの回転などの変換を表すことができる。原点を一次変換した結果は必ず原点となる。
$\begin{eqnarray}
\left\{
\begin{array}{l}
x' = a x + b y + c z\\
y' = d x + e y + f z\\
z' = g x + h y + i z
\end{array}
\right.
\end{eqnarray}$
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}a &b &c\\d &e &f\\g &h &i\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
※ $(1,0,0)$ が $(a,d,g)$ に、$(0,1,0)$ が $(b,e,h)$ に、$(0,0,1)$ が $(c,f,i)$ に写像される。
行列の変換式では3次元ベクトルをすべて縦に見る。
$x$ 方向に2倍拡大
$
\begin{eqnarray}
\left\{
\begin{array}{l}
x'=2 x\\
y' = y\\
z' = z
\end{array}
\right.
\end{eqnarray}
$
$
\begin{eqnarray}
\left\{
\begin{array}{l}
x'=2x +0y +0z\\
y'=0x +1y +0z\\
z'=0x +0y +1z\\
\end{array}
\right.
\end{eqnarray}
$
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}2 &0&0\\0 &1&0\\0&0&1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
※ $(1,0,0)$ が $(2,0,0)$、$(0,1,0)$ が $(0,1,0)$、$(0,0,1)$ が $(0,0,1)$ に写像される。
$yz$ 平面対称
$
\begin{eqnarray}
\left\{
\begin{array}{l}
x'=-x\\
y' = y\\
z' = z
\end{array}
\right.
\end{eqnarray}
$
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}-1 &0&0\\0 &1&0\\0&0&1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
※ $(1,0,0)$ が $(-1,0,0)$、$(0,1,0)$ が $(0,1,0)$、$(0,0,1)$ が $(0,0,1)$ に写像される。
$x$ 軸回転(右ねじの進む方向が正)
$
\begin{eqnarray}
\left\{
\begin{array}{l}
x'=x+0y+0z\\
y'=0x+\cos\theta\ y - \sin\theta\ z\\
z' =0x+\sin\theta\ y + \cos\theta\ z
\end{array}
\right.
\end{eqnarray}
$
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}1&0&0\\0&\cos\theta &-\sin\theta\\0&\sin\theta &\cos\theta\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
※ $(1,0,0)$ が $(1,0,0)$、$(0,1,0)$ が $(0, \cos\theta,\sin\theta\ )$ 、$(0,0,1)$ が $(0, -\sin\theta,\cos\theta\ )$ に写像される。
$y$ 軸回転
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}\cos\theta&0&\sin\theta\\0&1&0\\-\sin\theta &0&\cos\theta\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
$z$ 軸回転
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}\cos\theta &-\sin\theta&0\\\sin\theta &\cos\theta&0\\0&0&1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
任意軸回転(ロドリゲスの回転公式)
$\begin{pmatrix}u^{2}_{x}(1 - \cos\theta) + \cos\theta & u_{x}u_{y}(1 - \cos\theta) - u_{z}\sin\theta & u_{z}u_{x}(1 - \cos\theta) + u_{y}\sin\theta \\ u_{x}u_{y}(1 - \cos\theta) + u_{z}\sin\theta & u^{2}_{y}(1 - \cos\theta) + \cos\theta & u_{y}u_{z}(1 - \cos\theta) - u_{x}\sin\theta \\ u_{z}u_{x}(1 - \cos\theta) - u_{y}\sin\theta & u_{y}u_{z}(1 - \cos\theta) + u_{x}\sin\theta & u^{2}_{z}(1 - \cos\theta) + \cos\theta\end{pmatrix}$
※ 回転軸の単位ベクトル $(u_x,u_y,u_z)$。ただし回転軸は原点を通る。
(任意軸回転はクォータニオンによる表現方法もある。)
アフィン変換
一次変換に平行移動 $(j,k,l)$ を加えたもの。これにより原点が固定される一次変換以外の変換が実現できるようになる。
$
\begin{eqnarray}
\left\{
\begin{array}{l}
x'=ax+by+cz+j\\
y'=dx+ey+fz+k\\
z'=gx+hy+iz+l
\end{array}
\right.
\end{eqnarray}
$
$\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}a&b&c\\d&e&f\\g&h&i\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}+\begin{pmatrix}j\\k\\l\end{pmatrix}$
アフィン変換の同次座標表現
複数のアフィン変換の合成を行列の積で表せるようにしたもの
$\begin{pmatrix}x'\\y'\\z'\\1\end{pmatrix}=\begin{pmatrix}a&b&c&j\\d&e&f&k\\g&h&i&l\\0&0&0&1\end{pmatrix}\begin{pmatrix}x\\y\\z\\1\end{pmatrix}$
Lesson
- 空間の任意の点 $(x, y, z)$ を $(2x, 3y, -4z)$ に写像する一次変換行列を示せ。
- 空間の任意の点を $x$ 軸に対して対称となる点に写像する一次変換行列を示せ。
- 空間の任意の点を $xz$ 平面に対して対称となる点に写像する一次変換行列を示せ。
- 空間の任意の点を原点に対して対称となる点に写像する一次変換行列を示せ。
- 空間の任意の点を平面 $y=x$ に対して対称となる点に写像する一次変換行列を示せ。
- 空間の任意の点を $x$ 軸まわりに右ねじの進む方向に $30^\circ$ 回転した点に写像する一次変換行列を示せ。
- 空間の任意の点を $y$ 軸まわりに右ねじの進む方向に $45^\circ$ 回転した後、$x$ 軸に対して対称となる点に写像する一次変換行列を示せ。
Answer
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}2 &0 &0\\0 &3 &0\\0 &0 &-4\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}1 &0 &0\\0 &-1 &0\\0 &0 &-1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}1 &0 &0\\0 &-1 &0\\0 &0 &1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}-1 &0 &0\\0 &-1 &0\\0 &0 &-1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}0 &1 &0\\1 &0 &0\\0 &0 &1\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}1 &0 &0\\0 &\frac{\sqrt 3}{2} &-\frac{1}{2}\\0 &\frac{1}{2} &\frac{\sqrt 3}{2}\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
- $\begin{pmatrix}x'\\y'\\z'\end{pmatrix}=\begin{pmatrix}\frac{1}{\sqrt 2} &0 &\frac{1}{\sqrt 2}\\0 &-1 &0\\\frac{1}{\sqrt 2} &0 &-\frac{1}{\sqrt 2}\end{pmatrix}\begin{pmatrix}x\\y\\z\end{pmatrix}$
Extra Lesson
three.js editor を使って、3Dの図形を表示してみましょう。
- ポットの中心が原点に来るように平行移動してみましょう。Utah Teapot
- $z$ 軸の負の方向へ1平行移動してみましょう。
- $x$ 軸まわりに90° 回転したあと、$y$ 軸の正の方向へ1平行移動してみましょう。
- $y$ 軸の正の方向へ1平行移動したあと、$x$ 軸まわりに90° 回転してみましょう。
(親にダミーの Group を設置する)
H21後期2級 第2問
three.js editorの操作方法
視点移動
- SCENEタブでSceneをダブルクリックすると原点中心になる
- SCENEタブでオブジェクトをダブルクリックするとそのオブジェクトが中心に来て拡大される
- 左ボタンでマウスドラッグするとビューを画面の中心周りに回転できる
- 右ボタンでマウスドラッグするとビューを平行移動できる
オブジェクトの生成、変形
- Edit/Addでオブジェクト、ライト、カメラを追加できる
- SCENEタブで生成、変形したいオブジェクトを選べる
- Edit/Cloneで選ばれているオブジェクトを複製できる
- Edit/Deleteで選ばれているオブジェクトを消去できる
- OBJECTタブで名前Name、中心の位置Position、回転Rotation、拡大縮小Scaleを変更できる
- MATERIALタブで色などオブジェクトの材質を変更できる
データの保存
- File/Publishで、ウェブコンテンツとしてzipファイルで出力できる
- File/Export Sceneでシーン全体をJSON形式で保存、File/ImportでJSON形式のシーンを読み込みできる(SCRIPTは保存されないので注意!)
視点移動機能付の環境構築
- Add/Directional Light で光源を追加(2個追加して2方向から照らすのもよい)
- Scene に以下のコードをアタッチ
//ベクトルの成分 Lesson 3D 1. 3) const A=new THREE.Vector3(1, -4, 7); const B=new THREE.Vector3(7 , 2, 5); vector(A, B, 0.05); const C=new THREE.Vector3((A.x+B.x*2)/3, (A.y+B.y*2)/3, (A.z+B.z*2)/3); sphere(C, 0.5, 0xff0000); const distance=30; //原点からの距離 //以下は変更しないでください scene.add( new THREE.AxesHelper(100) );//座標軸 function sphere(position, radius, color=0xffffff){ const sphere = new THREE.Mesh( new THREE.SphereGeometry(radius,32,16), new THREE.MeshPhongMaterial({ color:color, specular:0x444444, shininess:30, emissive:color&0x333333 }) ); sphere.position.copy(position); scene.add(sphere); } function vector(start, end, radius, color=0xffffff){ const v=(new THREE.Vector3).subVectors(end,start); const l=v.length(); const material = new THREE.MeshPhongMaterial({ color:color, specular:0x444444, shininess:30, emissive:color&0x333333 }); const rotation = new THREE.Euler( Math.atan2(v.z,Math.sqrt(v.x*v.x+v.y*v.y)), 0, -Math.atan2(v.x,v.y), "ZXY" ); const cone=new THREE.Mesh( new THREE.ConeGeometry(radius*2, radius*6, 32), material ); cone.position.copy(new THREE.Vector3).addVectors( start, v.clone().multiplyScalar((l-0.15)/l) ); cone.rotation.copy(rotation); scene.add(cone); const cylinder=new THREE.Mesh( new THREE.CylinderGeometry(radius,radius,l-0.3,32), material ); cylinder.position.copy(new THREE.Vector3).addVectors( start, v.clone().multiplyScalar(0.5*(l-0.3)/l) ); cylinder.rotation.copy(rotation); scene.add(cylinder); } function line(position1, position2, color=0xfffff){ const line = []; line.push(position1); line.push(position2); scene.add(new THREE.Line( new THREE.BufferGeometry().setFromPoints(line), new THREE.LineBasicMaterial({color:color}) )); } function pointermove(event){ const longitude=(event.offsetX/window.innerWidth-0.5)*6.28; const latitude=(event.offsetY/window.innerHeight-0.5)*3; camera.position.set( Math.cos(longitude)*Math.cos(latitude), Math.sin(latitude), Math.sin(longitude)*Math.cos(latitude) ).multiplyScalar(distance); camera.lookAt( scene.position ); }
【事後学習】 本日学んだ内容を再確認しておきましょう。