2008年3月25日火曜日

C++: OpenGLで正十二面体を回転させる

このブログ記事をはてなブックマークに追加

どう書く?orgにポリゴン表示のお題があるのだが、なんとなく時機を逸してしまった感があるのでここで。でも投稿を見た限り、どれもOpenGL使ってないなぁ。真っ先に挙がると思っていたのだが。

ここでは、OpenGL(GL/GLU/GLUT)を使って正十二面体を回転させている。ちょっと変更するだけで、マウス操作を加えたり、タイマー関数を利用したりできる。言語は敢えてC++で。GLUT使うなら本当はCの方がシックリ来るけど。コンパイルはWindowsだろうが、Linuxだろうが問題ないはず。

以下、ソースコード。

#include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> class Rotate3D { private: static GLdouble m_matrix[16]; static double m_spin; static void Draw(); static void Rotate(GLdouble, GLdouble, GLdouble); static void Display(); static void SpinDisplay(); static void Reshape(int, int); public: Rotate3D() { } virtual ~Rotate3D() { } void Init(); }; GLdouble Rotate3D::m_matrix[16]; double Rotate3D::m_spin = 0.0; void Rotate3D::Draw(void) { glColor3d(0.5, 0.5, 0.5); glutSolidDodecahedron(); } void Rotate3D::Rotate(GLdouble x, GLdouble y, GLdouble z) { glTranslated(0.0, 0.0, -10.0); glRotated(x, 1.0, 0.0, 0.0); glRotated(y, 0.0, 1.0, 0.0); glRotated(z, 0.0, 0.0, 1.0); glTranslated(0.0, 0.0, 10.0); } void Rotate3D::Display(void) { glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); Rotate(m_spin, m_spin, m_spin); glMultMatrixd(m_matrix); Draw(); glGetDoublev(GL_MODELVIEW_MATRIX, m_matrix); glutSwapBuffers(); } void Rotate3D::SpinDisplay(void) { m_spin = 0.1; glutPostRedisplay(); } void Rotate3D::Reshape(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 100.0); } void Rotate3D::Init(void) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(300, 300); glutInitWindowPosition(100, 100); glutCreateWindow("Rotate3D"); glViewport(0, 0, 300, 300); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glLoadIdentity(); gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glGetDoublev(GL_MODELVIEW_MATRIX, m_matrix); glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutIdleFunc(SpinDisplay); } int main() { Rotate3D rotate3d; rotate3d.Init(); glutMainLoop(); return 0; }

2 コメント:

匿名 さんのコメント...

ソースを見させてもらったのですが,initの役割がかなり多いですね. もういっそのことglutMainloop()もいれたほうがいいようなww glutDisplayFunc()とか分けたほうがよくないでしょうか?

nox さんのコメント...

コメントありがとうございます。

実は、最初はglutDisplayFunc以下はmain関数にあり、次にglutMainLoopを含めすべてInitに移し、最後にglutMainLoopだけmain関数に戻しました。短いプログラムなので難しいところですが、コールバック関数の登録を含め最初に初期化したい部分をInitに入れることにしました。