Ⅲ- 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 解答例 噴射口は円錐を用いる.
© Copyright 2024 ExpyDoc