計算機序論2(2011年度)実習5週目(2011/11/21)

計算機序論2, 授業科目, www.kameda-lab.org 2011/11/21d

リンク

OpenGL(ver.2.1)の各関数(小文字のglの2文字で始まる関数)の説明
OpenGLのProgramming Guide Book (ver1.1, 通称赤本)


10(続). モデルデータの読み込みと表示


10.4 法線ベクトルの付与

パッチごとに法線ベクトルを正しく与えないと、CGは正確には表示されません。
単純な図形ならともかく、大きくなるとこれは致命傷になります。

法線ベクトルはパッチが決まっていれば定まります。
それゆえに、本節では(演習4とは違って)ファイルからデータをic2_PATCH構造体に読み込む時点で法線ベクトルを求めます。
このために、ic2_PATCH構造体で法線ベクトルを格納できるように拡張します。
OpenGLでは1つの頂点を与える度に法線ベクトル情報を付与できます。
このとき、glEnable(GL_NORMALIZE)を指定しておくと、法線ベクトルを正規化しておく必要がありません。
このため、ここでは法線ベクトルとして外積の計算結果を直接採用します。

110-4-NormalVector.c
110-3からの差分


10.5 法線ベクトルの表示

幾何的な計算があっているかどうかを確認するにはやはり表示してみるに限ります。
・パッチの重心を起点にする。
・法線方向に線分を描く。
・法線の表示の長さはパッチの面積(ないしその平方根)に比例させる。
・線分を見やすくするために、法線線分の表示時にはLightinの効果を一時的に切る。

110-5-ShowNormal.c
110-4からの差分


10.6 光源の一時的操作

せっかく法線を正しく与えても、Diffuse光源が主力の現状況では、MODELVIEW行列を幾ら変化させてもほとんどCGに変化がありません。
(ところでそれはなぜでしょうかね?)

そこで、7.6節や7.7節で行ったMODELVIEW行列の操作を駆使して、「光源のみを一時的に操作」できるようにします。
・ある時点での物体固有座標系からカメラ世界座標系への変換を行うMODELVIEW行列をロックする。
・以降の操作は、光源に対しては適用するものの、物体表示には先ほどロックしたMODELVIEW行列を用いる。
・ロックを解除したときは、ロック時点での状況に復帰させる。

110-6-MoveLight.c
110-5からの差分


11. 透視投影


11.1 透視投影

8.1節(暗示的には3.3節)からここまでは直交投影を用いていました。
本節ではいよいよ透視投影を設定します。
これにより、特に奥行きのある物体の見かけが良くなります。

透視投影を決定する本質的なパラメータは撮像面に対する焦点距離の大きさです。
ここでは撮像面には初期設定の縦横400画素[pixel]を想定して話をします。
このときは、焦点距離の単位も画素[pixel]になります。
水平画角35°になるような焦点距離は、以下の計算で与えられます。

tan(35.0[deg] / 2) = (400[pixel] / 2) / f[pixel]
f = 634.319[pixel]

実際のCG描画には、これ以外にも撮像範囲を与える必要があります。
カメラ世界座標系の原点におかれたカメラの先のどの範囲までを描画するかZ値で指定します。
カメラは(0,0,-1)の方向を向いているので、例えば z=-0.1 〜 z=-100.0 の範囲を指定するときは(0.1〜100.0)となります。
この範囲指定には正値であればどのような値も設定できますが、あまりに範囲が大きいとCG描画時の精度が落ちます。

111-1-Perspective.c
110-6からの差分

プログラムは、'P'を押す度に直交投影と透視投影を切り替えられます。
初期状態は直交投影です。


11.2 適切な距離

11.1節のプログラムで実際に描画してみると、よくわからないCGになるかもしれません。
これは間違いではありません。
では見ている私(あなた)は何を見過ごしてしまったのでしょう?

透視投影に切り替えた後、'j'キーをしばらく押しているとようやく様子がわかります。
見過ごしてしまった要因が何かわかりましたか?


12. 簡易アニメーション

滑らかに動くアニメーションを実現するプログラムを作成するには計算機序論2の時間は短いので、ここでは紙芝居風アニメーションを実現します。


12.1 操作の記録

簡易アニメーションの方針として、全てのキー入力を記録して、それを再現するという方針が考えられます。
・キー入力を覚えておくために、IC2_KEYINPUTという構造体を導入します。
・1つのIC2_KEYINPUTでは1つのキー入力を記録します。
・IC2_KEYINPUTのリンクトリストでは、FIFOに並べて記憶します。
・記録の開始には'S'キーを、記録の終了には'E'キーを使います。
・記録の開始に当たっては、過去のリンクトリストに使っていたメモリを解放し、PROJECTION行列とMODELVIEW行列を初期化します。
・念のため、'A'キーで現在の操作記録を標準出力に表示します。

簡易アニメーションの実現に合わせて、投影方法の選択キーを'P'から'O'と'P'に変更します。
・'O'で直交投影を設定。
・'P'で透視投影を設定。

112-0-Structures.c(実質的に111-1-Perspective.cと同じ)
111-1から112-0への差分
112-1-Memory.c
112-0から112-1への差分
※12節から構造体を集める場所を変更しました(分割コンパイルをしやすくするため)。


12.2 操作の再現

長い間かかりましたが、ようやく再生機能です。
OpenGLのglutSetTimer()を用います。
・操作間隔は一定(playinterval [ms])になります。
・操作記録を、'G'キーで再現させます。
・「何もしない」という操作を'z'キーで実現します。

今まで単一ファイルソースでは避けてきましたが、本節ではじめて function prototype 宣言を使っています。

112-2-Replay.c
112-1からの差分


12.3 操作の保存と読込

・操作記録を、'W'キーでアニメーションファイル(IC2_animation.txt)に保存させます。
・操作記録を、'R'キーでアニメーションファイル(IC2_animation.txt)から読み込めるようにします。
・アニメーションファイルはテキストなので、エディタで確認することもできます。
・アニメーションファイルでは # で始まる行、空行はモデルファイルと同様無視します。

112-3-AnimationFile.c
112-2からの差分


12.4 アニメーションの記録

操作を全て描画するのはメーキングを見ているようなもので、あまりいい気分ではないかもしれません。
そこで、自分が思ったフレーミングのみ描画していくようにします。
・アニメーションフレームの確定を指示する'F'キーを用意します。
・アニメーションファイル内では'F'キー記録時に改行します。


12.5 キーリスト

【投影の切り替え】
O : 直交投影へ切り替え(初期状態は直交投影)(12節以降)
P : 透視投影へ切り替え(12節以降)
P : 直交投影、透視投影の切り替え(初期状態は直交投影, 11節まで)

【移動】(移動はdelta_tごと)
h : 物体座標系でのX軸負方向移動
l : 物体座標系でのX軸正方向移動
n : 物体座標系でのY軸負方向移動
u : 物体座標系でのY軸正方向移動
j : 物体座標系でのZ軸負方向移動
k : 物体座標系でのZ軸正方向移動

【回転】(回転はdelta_rごと)
x : 物体座標系でのX軸回り負回転
w : 物体座標系でのX軸回り正回転
a : 物体座標系でのY軸回り負回転
f : 物体座標系でのY軸回り正回転
s : 物体座標系でのZ軸回り負回転
d : 物体座標系でのZ軸回り正回転

【拡大縮小】(5%刻み)
v : 物体座標系での縮小
b : 物体座標系での拡大

【リセット】
R : MODELVIEW蓄積行列の初期化

【アニメーション制御】
z : 単位時間経過
< : 単位時間の10%短縮
> : 単位時間の10%延長
F : アニメーションフレームの確定

【メタコマンド】(アニメーションでは記録されない)
q : プログラムの終了
Q : プログラムの終了
ESC : プログラムの終了
p : 現在のMODELVIEW行列, PROJECTION行列の表示
T : ティーポットの描画・非描画の切り替え(初期:非描画)

N : 法線ベクトルの描画・非描画の切り替え(初期:非描画)
L : 光源の伊知地的移動の有効化・無効化(初期:無効)
S : アニメーション記録の開始
E : アニメーション記録の終了
A : アニメーション記録の表示
G : アニメーションの描画
W : アニメーションのファイル保存
I : アニメーションのファイル読込


課題5. 2011/11/28出題分

課題はいずれも2011/11/28,13:30 (JST)提出締切である。


kameda[at]iit.tsukuba.ac.jp, 2011.