OpenGLのプログラムを作っている時にもどかしいのは原理的には全くもって簡単なのだが、ちょっとした勘違いが複数個所にあって、なかなか思うような描画が得られなかったりする。中でも気持ち上とくに重たいのは視体積の制御ではないだろうか。視体積はそれそのものの形状が描画されるわけではない上、ちょっと間違うと画面に何も出ないといった事態に陥りやすい。
また、視体積は描画のみでなく、ピッキング処理や、その結果の情報を活用した各種モデル作成処理を記述する際にも必要となる。アメリカなんかでよく「視体積を征する者はOpenGLアプリ作成を征す」とよく言われたりするのもこのためだ。(←うそに決まってんだから本気にするな)
今回は、最小限の4つ〜6つのパラメータを指定してやるだけで、そこそこ普通の正射影および透視投影の視体積を宣言してくれる便利関数を発明したぞ。
#include <gl.h> static void pocEasyViewVolume( bool is_ortho, const float aspect_ratio,// 画面アスペクト const float height_pers,// z=near_clip_pers位置での視体積高さ const float near_clip_pers, const float height_ortho,// z=near_clip_ortho位置での視体積高さ const float near_clip_ortho, const float far_clip_common ) { // 簡単ビューボリューム作成 if( !is_ortho ){ const float w = aspect_ratio * height_pers; glFrustum( -w, w, -height_pers, height_pers, near_clip_pers, far_clip_common ); }else{ const float w = aspect_ratio * height_ortho; glOrtho( -w, w, -height_ortho, height_ortho, near_clip_ortho, far_clip_common ); } return; }
では早速使い方を見ていこう。何せこれさえあれば、透視投影だろうが正射影だろうが、たったの一行で視体積の作成・GL宣言とその情報が取得できてしまうからもう助かるなんてもんじゃないぞ。
glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glViewport( 0, 0, w, h ); pocEasyViewVolume( 0, w/h, 0.25, 0.5, 0.5, 0.5, 9900.0 ); glFlush();
- 一番最初の引数は、正射影かどうかを指定する。!0を指定すれば正射影ボリュームを、0を指定すれば透視投影ボリュームを作成する。
- 次はボリュームのアスペクト比、つまり、幅を高さで割った値を指定する。
- 透視投影のボリュームのz=NC位置における高さ成分。
- 透視投影のNearClip値。
- 正射影のボリュームのz=NC位置における高さ成分。
- 正射影のNearClip値。
- 透視投影、正射影で共有の、FarClipの値。
結局何だろう、glFrustum()やglOrtho()という関数にいちいち視体積の情報を指定するやり方や、しかもそれらを正射影か透視投影かで使い分けていたことがどうもちょっと間が抜けているように感じていたのだけど、これがそのことへの自分なりの解決策なのかも知れない。
勿論、今回のやつは正面を見据える形の視体積に限定される話だ。X軸、Y軸それぞれについて対象な場合だけだ。そしてそうではない視体積を定義したい場合も沢山あるわけだけれども、やはり正面を見据える形の視体積が3Dのカメラとしては最もポピュラーであり、今回のはその場合における視体積定義の抽象化を高めてみた話なのである。