Java3Dには何の不満も無いのだが、Mac OS Xには初めからGLUTが入っていることを知ったので、ちょっと、OpenGLも試しておくことにした。
・ソースコード
polygon_sphere_test1.c
Mac OS X 10.7.5で成功したコマンド
gcc -framework OpenGL -framework GLUT polygon_sphere_test1.cFreeBSD 7.3 + libGL7.4.4 + libglut-7.4.4 で成功したコマンド
gcc -g polygon_sphere_test1.c `pkg-config --cflags --libs glut`
・実行画面
球面の1/8を均等な三角形に分ける方法で球のポリゴンを作成したものである。
マウスでドラッグすると球がその方向に回転し、ボタンを離すと逆方向に少し回転して止まる。
Sキーで、ワイヤーフレーム表示と塗り潰し表示が切り替わる。
回転軸の合成と、ポリゴンの頂点座標の算出に用いる球面線形補間(Slerp: Spherical linear interpolation)には、クォータニオンを使っている。クォータニオンの演算やSlerp等については、参考になる多数のwebページがあるので、説明を省く。GLUTやGLUにはクォータニオンに関する関数が見つからなかったので、適当に作った。特殊なことはしていないと思う。
ドラッグによる回転は、クリックした位置に半径1のトラックボールが接しているような感じに、トラックボールの中心からクリック位置へのベクトル(x,y,-1)とドラッグ先のベクトル(x',y',-1)との外積を回転軸として行っている。カーソル位置に表示されている球面上の座標を求めるのと比べるとかなり手抜きな方法であるが、まあまあそれらしく動いているので良しとする。
描画の度に全ポリゴンの頂点座標を再計算してVertex3dコマンドで転送しており、とても効率が悪い。VAOやVBOを使って頂点データを保存しておくか、せめてGenLists, NewList(GL_COMPILE)を使ってコンパイルしておきたかったが、1つのシンプルな実装例として、一旦公開することにした。
なお、Mac OS X 10.7(Lion)はOpenGL 3.2をサポートしているようなのだが、GLUTがサポートしていないので、GLUTを使うとOpenGL 2.1のAPIしか使えないようだ。
ちなみに、FreeBSD 7.3 + libGL7.4.4 + libglut-7.4.4 の構成で使えるOpenGL APIのバージョンも2.1である。同じソースコードがマルチプラットフォームで動くことは良いことである。だからGLUTは捨てられない。
ちなみに、GLUTにもglutWireSphere()やglutSolidSphere()という球を描画するI/Fがあるが、地球の緯度/経度線で区切られるような、扱い易いが大きさが均一でない四角形のポリゴンで球が作成される。
各頂点の法線ベクトルを三角形の法線でなく頂点座標そのものにすればもっとツルツルになる(下図)ことに後で気付いたが、せっかくのドラッグによる回転がわかりづらくなるので、上の多面体仕様のままにしておく。
これにするには、
glNormal3d((a.x + b.x + c.x)/3,こういう所を全て
(a.y + b.y + c.y)/3,
(a.z + b.z + c.z)/3);
glVertex3d(a.x, a.y, a.z);
glVertex3d(b.x, b.y, b.z);
glVertex3d(c.x, c.y, c.z);
glNormal3d(a.x, a.y, a.z);こうにする。
glVertex3d(a.x, a.y, a.z);
glNormal3d(b.x, b.y, b.z);
glVertex3d(b.x, b.y, b.z);
glNormal3d(c.x, c.y, c.z);
glVertex3d(c.x, c.y, c.z);
コメント