Document

Ⅲ-
2.4 隠面処理
物体位置の前後関係に応じてもっと近い可視面のみ表示する
zバッファ法の原理:
各画素の画面位置(x,y)に対応する画素の値を記憶するメ
モリAとは別に,
書き込む物体の奥行きを距離を記憶させる2次元メモリBを
用意し,
物体ごとに各位置の画素の値を書き出す際に,メモリBを参
照して
同じ位置にすでに書き込まれた画素の奥行き距離より近い
場合のみ,メモリAに書き出す.
書き改められた場合のみ,新たな奥行き距離をメモリBにも
書き出す.
1
Ⅲ-
2
背景
(距離:z =∞ )
図形1(距離:a)
y
z
メモリA
x
図形2(距離:b)P:blue
メモリB
メモリA
メモリB
メモリA
P:b
(z,z,b,b,z,)
メモリB
P:0
スクリーン P:z
Zバッファ
(全てz=∞)
(1)
P:red
スクリーン
(2)
P:a
Zバッファ
(z...,a,a,z...)
P:red
スクリーン
(3)
P:a
Zバッファ
(z,a,a,b,b,z,)
Ⅲ-
Zバッファによる隠面処理の設定方法
1)Zbufferの利用の宣言
glutInitDisplayMode(GLUT_RGBA |GLUT_DEPTH);
2)Zbufferを初期化
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3)隠面処理の有効範囲の指定
glEnable(GL_DEPTH_TEST);
・・・
glDisable(GL_DEPTH_TEST);
3
Ⅲ-
Zバッファによる隠面処理の実行結果
実行!
c2-2.cをコピーして実行する.
Zbufferを設定しない場合
練習問題2-2を実行.
Zbufferを設定した場合
4
Ⅲ練習問題2-2:
1)プログラムc2-2.cに対してZバッファ法による隠面処理を追加して図2.8(b)の
結果が得られることを確認する(プログラム名はp2-2.cとする).
Zバッファの宣言は40行,zバッファの初期化は11行に対して行なう.
隠面処理の有効範囲は16-22行
解答例
P32.課題2.5ヒント
長方形の描画のための座標の移動.
glTranslatef(0.5,0.0,0.5);
glRotatef(-60.0,0.0,1.0,0.0);
5
Ⅲ-
3.
モデリング
複数の基本立体を組み合わせて複雑な画像を形成するモ
デリング手法について学ぶ.
OpenGLでは通常の絵を書く感覚とは異なり,「書くべき位
置や向きに書き手が移動・回転してその場で基本図形を書
く」のが基本スタンス.
・描画コマンドはローカル座標系に対し定義されるので,
例えば立方形を並べて2つ書く場合,1つ目(原点中心)
の記述が終わったら,座標系を右にずらせた後,同じ
記述で2つ目を書く(その後,座標系をもとに戻す)
・回転させたものを書く場合は,座標系を回転させて描き
その後座標系を戻す
6
Ⅲ-
y
3.1. 座標系
スクリーン座標系
y
y
z
x
z
y
ローカル
座標系
x
x
z
x
ビュー座標系
z
ワールド座標系
7
Ⅲ-
8
3.2.1. ロケットのモデリング
円柱を表示する関数
y
void myWireCylinder(float r, float h, int n);
原点を中心に,半径r, 高さh, 分割数nのフ
レームワイヤの円柱を描く
2.0
r
2.0
x
2.0
h
z
n=6
1.0
3段ロケットの構成
n=24
この関数はmyShape.hに記述されているので,
プログラムの先頭でinclude “myShape.h”と
記述する
Ⅲ-
円錐を表示する関数
void glutWireCone(float r, float h, int n1, int n2);
底面の半径r,高さh,半径方向の分割数n1,高さ方向の分割数n2のワイヤ
フレームの円錐を生成する
円錐の底面はxy平面(z=0),
頂点はz軸上(0,0,h)にある
(手前を向いていることに注意)
n2
h
r
r
n1
この関数では任意のワールド座標を指定
する形式になっていない
事前に着目する座標に原点をずらす⇒glTranslate3f
円錐は,手前に向かっているので,y軸方向に向かせるには
90度回転させる必要がある⇒glRotatef
9
Ⅲ- 10
3.2.2 ロケットのプログラミングp36:
実行!
c3-1.cをコピーして実行する.
実行結果
Ⅲ- 11
3.2.3 座標系の保存と復元
glTranslatefやglRotatefを実行と逆変換(例えば90度回転させ
てから-90度回転させてもとに戻す)
⇒繰り返すと計算が煩雑かつ実数計算による誤差が増える
変換実行前の座標系を保存しておいて,復元呼び出しを行なう.
glPushMatrix( );現在の座標系のコピーをスタックに押し込む
glPopMatrix( );スタックから座標系をとりだし,現在の座標系に
置き換える(回転などを加えた1つ前の状態に戻る)
括弧などと同じように,必ずプログラムの中ではペアで使わないと表示がおかしくなる.
(Linuxで,>pushd /any/directory
>…
>popd とすると元のディレクトリに戻るようなもの)
Ⅲ- 12
考え方:
OpenGLで例えば円錐を描くコマンドは,半径と高さの指定
だけであり,ワールド座標系の位置(x,y,z)や方向は指定できない.
void glutWireCone(float r, float h, int n1, int n2);
つまり書き手は常に自分の手前の決まった向きに円錐を書くイ
メージ.
したがって,ワールド座標系(x,y,z)の位置に90度傾いた円錐を
描く場合は書き手が(x,y,z)に移動し,さらに90度向きを変えてか
ら書く動作をあちこちで行う.
このため,書きに行く前に元の位置を覚えておき,書いたら戻る
動作を繰り返す処理をPushMatrix,PopMatrixで実現する.
Ⅲ- 13
3.2.4 ロケットに1段目を加えるp39:
実行!
c3-2.cをコピーして実行する.
実行結果
Ⅲ- 14
3.3 変換行列スタック
教科書にはいろいろ式が書かれているが...
変換の種類は2つ.
1)物体の位置・回転などを指定するために座標系を操作する
ための変換⇒幾何変換.
2)上記の操作で物体が配置された後,それをどのように眺め
るか(表示させるか)を決めるための変換⇒投影変換
幾何変換の行列スタック:glMatrixMode( GL_MODELVIEW);
投影変換の行列スタック:glMatrixMode( GL_PROJECTION);
glMatrixMode(GL_PROJECTION); /*投影変換行列スタックを操作対象とする*/
glLoadIdentity(); /*行列スタックをクリア*/
gluPerspective(30.0,aspect,1.0,50.0);
glMatrixMode(GL_MODELVIEW); /*幾何変換行列スタックを操作対象する*/
変換行列スタックと描画の状態図:3段ロケット
Ⅲ- 15
練習問題:
1)C3-2に羽を1つとりつける.
p3-1.c 解答例
ヒント:
羽は立方体を引き伸ばして作成する.
立方体:
glutWireCube(double size);
この描画命令の前に,スケール変換命令を入れる
glScalef(float x,float y,float z)(各方向への引き
伸ばし)
羽の位置指定はさらにこの前に
glTranslatefで指定する.
2)噴射口をとりつける
p3-2.c 解答例
噴射口は円錐を用いる.