Transcript ppt

コンピューターグラフィックスS
第10回 OpenGL演習(1)
システム創成情報工学科 尾下 真樹
今回の内容
• 前回の残り
– サンプルプログラムの解説
• OpenGL演習(1)
– 簡単なアニメーションの追加
OpenGL演習
• OpenGLの使い方を講義で説明
• 資料に従って、各自、プログラムを拡張
– 講義で学習した内容を、実際に作成して確認
– 一部のプログラムは、穴埋めになっている
演習資料(3種類)
• 演習資料(OpenGL演習)
– この資料に従って、プログラムを拡張していく
– 次回以降の分の説明は、逐次追加する
• コンパイル方法の説明資料
– コンパイル方法の詳しい説明
– CL端末や自宅での方法も一応説明
• OpenGL関数 簡易リファレンス
– OpenGLの関数を簡単に説明した資料
コンパイル方法
• ターミナルから、gcc(GNU C コンパイラ)を、
以下のようなコマンドで実行し、コンパイル
gcc opengl_sample.c -L/usr/X11R6/lib -lglut -lGLU
-lGL –lXmu -lm -o opengl_sample
– opengl_sample.c ・・・ 入力のソースファイル名
– opengl_sample ・・・ 出力の実行形式ファイル名
• 実行方法(出力ファイル名をターミナルから入力)
opengl_sample
コンパイルエラーが出たとき
• ソースファイルにエラーがあるときには、エ
ラーの原因や、エラーのある行が表示される
ので、それらの情報をもとに、プログラムを
修正する
– Javaのプログラムでコンパイルエラーが出たとき
と同じ要領
– エラーメッセージをよく読むことが重要
• サンプルプログラムは、何も修正しなければ、
コンパイルエラーは出ない
簡単なアニメーションの追加
修正箇所
1. 回転角度を表す変数を追加(先頭)
2. 変数を変化させる処理を追加(idle()関数)
3. 描画処理(変換行列の設定)を追加
(display()関数)
4. 描画処理(裏向きのポリゴンの描画)を追
加(display()関数)
サンプルプログラムの構成(復習)
ユーザ・プログラム
main()関数
initEnvironment()関数
初期化処理
display()関数
描画
mouse()関数
motion()関数
マウス処理
idle()関数
アニメーション処理
main()関数
終了処理
GLUT
glutMainLoop()
入力待ち処理
ポリゴンの回転の変換行列
• 1枚のポリゴンを y軸を中心として回転させる
1

0
0

0
0  1
0
0

1 0 0  0 cos  camera_pitch   sin  camera_pitch 
0 1 15  0 sin  camera_pitch  cos  camera_pitch 

0 0 1 
0
0
 0
0 0
ワールド座標系→カメラ座標系
0  1

0  0
0  0

1 
 0
0 0 0   cos  theta_cycle 

1 0 1
0
0 1 0    sin  theta_cycle 

0 0 1  
0
0 sin  theta_cycle  0 

1
1
0
1 cos  theta_cycle  0 

0
0
1 
 x   x 
   
 y   y 
 z   z 
   
1  1 
モデル座標系→ワールド座標系
– 変換行列に y軸周りの回転を追加することで実現
y
(0,1,0)
theta_cycle
z
x
ポリゴンの回転のための変数
• 変数定義(先頭)、変数の変化(idle()関数)
// アニメーションのための変数
float theta_cycle = 0.0;
void idle( void )
{
// theta_cycle を 0~360 まで繰り返し変化させる
// (360まで来たら0に戻る)
theta_cycle += 1.0;
if ( theta_cycle > 360 )
theta_cycle -= 360;
// 再描画の指示を出す(描画関数が呼ばれる)
glutPostRedisplay();
}
ポリゴンの回転の追加
• 変換行列の設定(display()関数)
// 変換行列を設定(ワールド座標系→カメラ座標系)
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, - 15.0 );
glRotatef( - camera_pitch, 1.0, 0.0, 0.0 );
// 地面を描画(ワールド座標系で頂点位置を指定)
・・・・・・
// 変換行列を設定(モデル座標系→カメラ座標系)
glTranslatef( 0.0, 1.0, 0.0 );
glRotatef( theta_cycle, 0.0, 1.0, 0.0 );
// ポリゴンを描画(モデル座標系で頂点位置を指定)
裏面のポリゴンの描画
• 裏面が描画されない(背面消去のため)ので、
裏向きのポリゴンの描画を追加
glBegin( GL_TRIANGLES );
glColor3f( 0.0, 0.0, 1.0 );
glNormal3f( 0.0, 0.0, 1.0 );
glVertex3f(-1.0, 1.0, 0.0 );
glVertex3f( 0.0,-1.0, 0.0 );
glVertex3f( 1.0, 0.5, 0.0 );
glColor3f( 1.0, 0.0, 0.0 );
glNormal3f( ???, ???, ??? );
glVertex3f(-1.0, 1.0, 0.0 );
glVertex3f( ???, ???, ??? );
glVertex3f( ???, ???, ??? );
glEnd();
伏せ字になっている部分に
は、適切な値を記述する
裏面のポリゴンの描画
• 法線、頂点の順序を反対にする必要がある
– 法線の向き(頂点の色計算に使用)
– 頂点の順序(面の向き判定 → 背面除去に使用)
• デフォルトでは、反時計回りになる方を表と判定
1
1
3
2
表
2
裏
3
修正箇所のまとめ
1. 回転角度を表す変数を追加(先頭)
2. 変数を変化させる処理を追加(idle()関数)
3. 描画処理(変換行列の設定)を追加
(display()関数)
4. 描画処理(裏向きのポリゴンの描画)を追
加(display()関数)
演習
• 演習1
– 資料の2章の内容
– ここまでのプログラム(簡単なアニメーション)を
サンプルプログラムに追加
• 演習2
– 演習問題
– 描画設定の変更による描画結果の違いを確認
演習問題
• 演習問題1
– Zバッファと背面除去の有無の変更
• 演習問題2
– 射影変換行列の変更
以降の演習は次回
次回説明
演習資料は用意されているので、先をやり
たい人は、自分で進めておいて構わない
前回の演習問題の解説
問題
• 下記のようなシーンがある時、モデル座標系からカメラ座標
系への変換行列を求めよ
– 物体は原点にあり、モデル座標系とワールド座標系は一致している。
– カメラは、ワールド座標系から見て水平方向に-90度回転(ワール
ド座標系のY軸を中心として90度回転)、上下方向に-45 度回転
(カメラ座標系のX軸を中心として-45度回転)した状態にある。
また、カメラは原点を向いており、両者の間の距離は10である。
z
x
y
10
y
x
z z
解答
1

0
0

0
0  1
0
0

1 0 0  0 cos  45   sin  45 
0 1 10  0 sin  45  cos  45 

0 0 1  0
0
0
0 0
0   cos  90 

0
0
0    sin  90 

1
0
0 sin  90  0 

1
0
0
0 cos  90  0 

0
0
1
一番最後に平行移動をかければ良いことに注目
z
x
カメラを原点から10離すというのは、カメラ座標系
で見て、カメラを後ろに10動かすということなので、
カメラ座標系(回転後)に平行移動を適用
y
10
y
x
z z
解説(1/2)
• 回転変換をかけた段階でカメラの向きが決定
0
0
1

 0 cos  45   sin  45 
 0 sin  45  cos  45 

0
0
0
0   cos  90 

0
0
0    sin  90 

1
0
y
z
y
x
x
z z
0 sin  90  0 

1
0
0
0 cos  90  0 

0
0
1
解説(2/2)
• Z方向に-10平行移動することで、カメラを
原点から距離10離すことになる
1

0
0

0
0  1
0
0

1 0 0  0 cos  45   sin  45 
0 1 10  0 sin  45  cos  45 

0 0 1  0
0
0
0 0
z
x
y
0   cos  90 

0
0
0    sin  90 

1
0
0 sin  90  0 

1
0
0
0 cos  90  0 

0
0
1
カメラの正面方向は、-Z方向であるため
10
y
x
z z
誤答例1
• 符号が反対
1

0
0

0
0   cos  90 

0
0
0    sin  90 

1
0
0  1
0
0

1 0 0  0 cos  45   sin  45 
0 1 10  0 sin  45  cos  45 

0 0 1  0
0
0
0 0
(0,0,0)に変換行列を適用すると(0,0,10)に
なるので、明らかにおかしいと分かるはず
y
x
z z
z 10
y
0 sin  90  0 

1
0
0
0 cos  90  0 

0
0
1
誤答例2
• 平行移動の順番が違う
0
0
1

 0 cos  45   sin  45 
 0 sin  45  cos  45 

0
0
0
0   cos  90 

0
0
0    sin  90 

1
0
0 sin  90  0   1

1
0
00
0 cos  90  0   0

0
0
10
0 

1 0 0 
0 1 10 

0 0 1 
0 0
カメラが、ワールド座標系で(0,0,10)
の位置に来てしまう
y
x
z
z z
y
(0,0,10)
平行移動の適用位置(復習)
• 平行移動を適用する順番により、結果は変
る
カメラ
座標での
平行移動
0
 
0
 10 
 
ワールド
→カメラ
の回転
モデル→
ワールド
の回転
ワールド
座標での
平行移動
y
y
(-8,4,1)
モデル
座標での
平行移動
y
x
(12,0,2)
z
x
z
z
x
 x   x 
   
 y   y 
 z   z 
   
1  1 
別解
• ワールド座標系でのカメラの位置を計算して
右からかけても同じ変換行列になる
0
0
1

 0 cos  45   sin  45 
 0 sin  45  cos  45 

0
0
0
z
x
0   cos  90 

0
0
0    sin  90 

1
0
y
0 sin  90  0  1

1
0
0  0
0 cos  90  0  0

0
0
1  0
10sin  90  cos  45  

1 0
10sin  45 

0 1 10 cos  90  cos  45  

0 0
1

0 0
この場合、カメラ位置の計算は面倒なので、正解
のやり方で解けるようになっていた方が良い
10
y
x
z z