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

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

リンク

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


8. 直交投影


8.1 OpenGLにおける直交投影の明示的指定

これまでの(6節,7節までの)プログラムでは、結果的に投影方法として直交投影の形になっていました。
しかし、これは正式なOpenGLの投影(空間の撮像面への射影)ではありませんでした。

本節からは、OpenGLによる直交投影の指定を明示的にプログラム上で行うようにします。
glOrtho()関数を用いて、PROJECTION行列スタックトップに直交投影を実現する4x4の行列を設定します。
OpenGLによる投影指定の特徴として、クリッピング空間(撮影面に描画する空間の範囲)を指定することが挙げられます。

【定式化】
pcamp = Portho M Plocal
pcamp = Portho Pcamera
ここで Portho は直交投影を実現する4x4の行列。
pcamp は撮像面(camera plane)中の座標を表現する実質2次元の位置ベクトル。 ただし、斉次表現を用いているので、実際には3次元ベクトルで表現する。

108-1-Ortho.c
106-6からの差分

ic2_showMATRIX()という関数で、その時点のMODELVIEW行列スタックトップと、PROJECTIOn行列スタックトップとの状態を表示できます。
ここで注意するべきなのは3行3列目の要素が-1になっていることです。

これによって、以後の説明では、3次元世界はすべて右手系になり、カメラ方向は(0,0,-1)になります。
OpenGLの直交投影に関しては、クリッピング近接面をz=-1, 遠方面z=1とし、左右と上下を-1.0から1.0までの範囲とすると、
glOrtho(-1, 1, -1, 1, -1, 1)
となります。
(厳密にはカメラの位置は(0,0,0)なので、クリッピング空間を-1.0〜1.0にするとカメラがその中に存在することになって、気分的にはすっきりしません。)
(とはいえ、クリッピング面のZ値に負の値を入れることはOpenGLライブラリ上では認められている行為です。)

右手系になることの余波として、カメラから見て遠いほうがZ値がマイナスの大きな値のほうに相当するようになることと、回転における回転方向の正負反転が挙げられます。

【余談】この投影の時点で強引に3次元世界を左手系に戻すことも可能です。
ただし、この場合は、望むPROJECTION行列を(OpenGLライブラリの関数によって用意させるのではなく)自分で計算する用意する必要があります。
右手系を左手系にする単純な実現方式として、どのような方法が考えられるでしょうか?


8.2 ウィンドウサイズ変更による影響の無効化

これまでは、OpenGLのウィンドウは正方形の形で表示されていました。
また、それをサイズ変更すると、自由に引き伸ばしたりすることができました。
これはこれで便利ですが,正確なCG描画を考える上では理解の妨げになりかねません。
そこで、ここから、ウィンドウサイズ変更を無効化できるようにプログラムを書き換えていきます。

108-2-Viewpoint.c
108-1からの差分

glutReshapeFunc()を使ってウィンドウサイズ変更を検知します。

また、ここからは、callbackによる割り込み作業をしたあと、本体glutMainLoop()に戻ってからすぐに再描画をしてもらえるよう、glutPostDisplay()という関数を使って旗を立てておきます。


8.3 真ん中に来てほしい‥

先の108-2-Viewpoint.cは、glutReshapeFunc()で明示的に作業を指示するようにすることで、これまでglutライブラリが勝手にやってくれていたサイズ変更にともなう引き延ばし等をさせなくするだけでした。
openGLでの最終描画(2次元が像を作る作業)では、左下が原点になります。そのために、左下に張り付いた状態になってしまいました。

いまいちなので、これを中央に設定します。
ここでは、投影行列をレンダリング開始時に正しく設定するようにします。
これに伴って、今後はカメラのセットアップを毎フレーム行うようにします。

108-3-ViewpointCentering.c
108-2からの差分


9. モデルデータの読み込み


9.1 モデルファイルのデータフォーマット

1行あたり(1ポリゴンあたり)のフォーマット
X0 Y0 Z0 X1 Y1 Z1 X2 Y2 Z2 R G B

・要素の間は1つ以上のスペース
・3頂点を0,1,2の順に(右ネジに)なぞったときに反時計回りに見える側を表とする(右ネジの先端側が表)
・RGBは0.0〜1.0の範囲
・空行、スペースのみの行は無視
・先頭が#で始まる行はコメント行として無視

ここでまず用意するモデルとしては、いままでのTeapotが概ね+/- 1.0ぐらいの大きさだったので、それぐらいの大きさのものにしておきましょう。

こちらのモデルリストに皆さんのモデル(課題3A-1)を掲載しました。


9.2 指定ファイルのオープン

まずはファイルを読み込むプログラムを作らないと話になりません。
2.2節のプログラムをベースにします。
後で8節のプログラムに取り込むので、ファイルを読み込む部分は関数化しておく必要があります。

109-2-OpenFile.c
102-2からの差分


9.3 行毎の読み込み

モデルファイルは、1行ずつに構造が沸かれているので、読み込みも1行ずつ行います。
このために、fgets()関数を用います。
また、各行が有効なモデル行かどうかの確認もします。

109-3-ReadLine.c
109-2からの差分


9.4 モデルの読み込み

ic2PATCH構造体のlinked listにモデルデータを構築します。
ic2PATCH構造体のlinked listはfirstmodelptrで示されるアドレスから開始されます。
ic2PATCH構造体にはic2POINT構造体3つとic2COLOR構造体1つが含まれます。

109-4-ReadModel.c
109-3からの差分


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

いよいよ(やっと)モデルを読み込んで表示までをしてみましょう。
(本当はこの前にソース分割をしておきたかったのですが、ソース表示の都合等で単一ファイルのままです‥)
(あまり普通の人に推奨するコードの書き方ではありません‥)


10.1 ファイルの統合

108-3-ViewpointCentering.c109-4-ReadModel.cとをベースにします。
後者のほうから、関数部分を全て前者に移植します。

110-1-MergedSource.c
109-4からの差分


10.2 既定義物体のOn/Off

移植には成功しましたか?
でも何も変わりませんね?
もしかしたらもとから描いているTeapotが邪魔をしているのかもしれません。
この際なので、表示したり非表示にしたりできるようにしましょう。

110-2-MergedSource.c
110-1からの差分


10.3 モデルの読み込みと表示

考えてみれば、読み込んだ表示をするようなプログラミングをまだしてないので、Teapotを消したところで意味ないですね(気づいてた?)。
読み込んだ物体モデルをとにもかくにも表示させるようにしましょう。

110-3-ModelShow.c
110-2からの差分


10.4 法線ベクトルの付与

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

発展課題かな‥


モデルリスト

こちらに皆さんのモデル(課題3A-1)も掲載しました。


課題4. 2011/11/21出題分

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

残念ながら今年度受講生は例年に比べて課題提出の遅延者が多い。
・ 締切前提出のエントリも公式締切時刻後もトラブル対策の為に暫時開けておく。
・ TAの作業量軽減を図るため、moodle上に遅延提出用エントリを設ける。
・ この遅刻提出用エントリは遅延を許容するものではない(減点方法は例年通り実施)。
・ 締切前エントリ、遅刻提出用エントリに同時に出した場合は遅刻扱いで大幅減点になるので不用意に遅刻提出エントリに提出しないこと。
・ 遅刻提出用のエントリは、最後に提出した時間と内容のみが有効になる。時間が経てばそれだけ減点が大きくなるので、不用意に何度も提出しないこと。
・ 遅刻提出用のエントリもある程度経った時点で閉鎖する。以降は公式問い合わせメールアドレスに添付の形で送ること。


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