-
-
Save ww24/f4a85e91a6563962d8ed to your computer and use it in GitHub Desktop.
GLUT Sample Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <math.h> | |
#include <GLUT/glut.h> | |
// ワールド変換行列 | |
double wm[] = { | |
1, 0, 0, 0, // x1, x2, x3, 0 | |
0, 1, 0, 0, // y1, y2, y3, 0 | |
0, 0, 1, 0, // z1, z2, z3, 0 | |
0, 0, 0, 1 // x, y, z, 1 | |
}; | |
double rad = 0; | |
// ビュー変換行列 | |
double vm_y[] = { | |
1, 0, 0, 0, // x1, x2, x3, 0 | |
0, 1, 0, 0, // y1, y2, y3, 0 | |
0, 0, 1, 0, // z1, z2, z3, 0 | |
0, 0, 0, 1 // x, y, z, 1 | |
}; | |
double vm_x[] = { | |
1, 0, 0, 0, // x1, x2, x3, 0 | |
0, 1, 0, 0, // y1, y2, y3, 0 | |
0, 0, 1, 0, // z1, z2, z3, 0 | |
0, 0, 0, 1 // x, y, z, 1 | |
}; | |
struct size { | |
int w; | |
int h; | |
}; | |
size window = {0, 0}; | |
struct pos2d { | |
double x; | |
double y; | |
}; | |
// マウス座標 | |
pos2d mouse_pos = {0, 0}; | |
double y_rad = 0; | |
double x_rad = 0; | |
// -------------------------------------------------- | |
// アイドル状態に実行する関数 | |
// ・描画処理やマウス処理など、他の処理がとりあえず終了し、次の処理が実行可能となった時に呼ばれる。 | |
// ・例えば、時間を少しだけ進めて、キャラクターの状態(位置・向きなど)を変更したりする。 | |
void idle() | |
{ | |
// y 軸に対して毎度 1 度ずつ右ねじ回転 | |
rad += M_PI / 180; | |
if (rad > M_PI * 2) { | |
rad = 0; | |
} | |
wm[0] = cos(rad); | |
wm[2] = -sin(rad); | |
wm[8] = sin(rad); | |
wm[10] = cos(rad); | |
glutPostRedisplay(); // ウィンドウに再描画命令を送る(ポストする) | |
} | |
// -------------------------------------------------- | |
// 描画関数 | |
// ・OpenGLの命令を使って、画面に描画を行うための関数。 | |
// ・この関数は直接呼ばない(方が良い)。glutPostRedisplay 関数を実行すれば、手の空いているときに自動で呼ばれる。 | |
void display() | |
{ | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // カラーバッファと深度バッファをクリアする | |
// ここから、描画命令 | |
glMatrixMode(GL_MODELVIEW); // モデルビュー行列のモードに変更 | |
glPushMatrix(); // 現在のモデルビュー行列のコピーをスタックに保存する | |
glLineWidth(1); | |
glDisable(GL_LIGHTING); | |
for (int i = 0; i < 3; i++) { | |
int length = 100; | |
glColor4d((i == 0), (i == 1), (i == 2), 1.0); | |
glBegin(GL_LINES); | |
glVertex3d(0, 0, 0); | |
glVertex3d((i == 0) * length, (i == 1) * length, (i == 2) * length); | |
glEnd(); | |
} | |
glEnable(GL_LIGHTING); | |
glPushMatrix(); | |
glMultMatrixd(wm); | |
// 三角錐の描画 | |
glBegin(GL_TRIANGLE_STRIP); | |
glVertex3d(0, 0, 0); glNormal3d(0, 0, -1); | |
glVertex3d(4, 0, 0); glNormal3d(0, 0, -1); | |
glVertex3d(0, 0, 3); glNormal3d(0, 0, -1); | |
glVertex3d(0, 2, 0); glNormal3d(0, 0, -1); | |
glVertex3d(0, 0, 0); glNormal3d(0, 0, -1); | |
glVertex3d(4, 0, 0); glNormal3d(0, 0, -1); | |
glEnd(); | |
glPopMatrix(); | |
glPopMatrix(); // 現在のモデルビュー行列を捨て、スタック先頭の行列を現在の行列とする | |
glutSwapBuffers(); // バッファを交換し、描画結果をウィンドウに表示する | |
} | |
// -------------------------------------------------- | |
// ウィンドウの大きさが変化したときに呼ばれる関数 | |
// 引数: ウィンドウ幅 w, ウィンドウ高さ h | |
// | |
// ・ウィンドウの最小化/最大化、フレームを掴んでウィンドウサイズを変化したときに呼ばれる。 | |
// ・射影変換行列の変更(主にカメラのアスペクト比)、ビューポートの変更などを行うと良い。 | |
// ・フレームを掴んで動かしている場合、ちょっと動かすごとに毎回呼ばれるので注意! | |
void resize(int w, int h) | |
{ | |
window.w = w; | |
window.h = h; | |
printf( "Window Size: %d %d\n", w, h ); | |
printf( "Window Size: %d %d\n", glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) ); | |
// ビューポートをウィンドウ全体に指定する | |
glViewport( 0, 0, w, h ); | |
// 透視投影(プロジェクション)行列を設定する | |
glMatrixMode(GL_PROJECTION); // 透視投影行列のモードに変更 | |
glLoadIdentity(); // 現在の透視投影行列を初期化 | |
gluPerspective( 30.0, (double)w/h, 0.1, 100.0); // GLUの関数でカメラの視錐台を設定(引数は、視野角、アスペクト比、カメラ手前側距離、カメラ奥側距離) | |
// モデルビュー行列の視点のみ設定しておく | |
glMatrixMode(GL_MODELVIEW); // モデルビュー行列のモードに変更 | |
glLoadIdentity(); // 現在のモデルビュー行列を初期化 | |
glMultMatrixd(vm_y); | |
glMultMatrixd(vm_x); | |
gluLookAt(-20, 30, -20, 0, 0, 0, 0, 1, 0); // GLUの関数でカメラの位置と方向を設定(引数は、カメラ位置(3)、カメラを向ける対象物位置(3)、カメラの上向きベクトル(3)) | |
} | |
// -------------------------------------------------- | |
// キーを押したときに反応する関数 | |
// 引数: キーコード key, キーが押されたときのマウスのx座標 x, y座標 y | |
// ・もしキーが押されたことによって状態が変化したなら、最後に glutPostRedisplay 関数を呼んでおくと良い。 | |
void keyboard(unsigned char key, int x, int y) | |
{ | |
printf( "Key Code : %d, Position : %d %d\n", key, x, y ); | |
// switch文を用いたキー処理の例(switch-caseを使う場合、breakの書き忘れに注意) | |
double size = 1.0; | |
switch(key) { | |
case 'a': | |
// x 軸正方向へ移動 | |
wm[12] += size; | |
break; | |
case 'd': | |
// x 軸負方向へ移動 | |
wm[12] -= size; | |
break; | |
case 'w': | |
// z 軸正方向へ移動 | |
wm[14] += size; | |
break; | |
case 's': | |
// z 軸負方向へ移動 | |
wm[14] -= size; | |
break; | |
default: | |
printf( "\tKey: Other -> %c\n", key ); | |
} | |
glutPostRedisplay(); | |
} | |
// -------------------------------------------------- | |
// マウスボタンを押した/放したときの関数 | |
// 引数: 押されたマウスボタン button, そのボタンの状態 state, 押された位置のx座標 x, y座標 y | |
// ・マウスボタンは、左クリック:0, 中クリック:1, 右クリック:2。 | |
// ・ボタンの状態は、クリックしたとき:0, 指を放したとき:1。 感覚と少し違うので注意! | |
void mousePressed(int button, int state, int x, int y) | |
{ | |
printf( "Mouse Button: %d, State: %d, Position %d %d\n", button, state, x, y ); | |
// mouse down 時 | |
if (! state) { | |
// 座標を記録しておく | |
mouse_pos.x = x; | |
mouse_pos.y = y; | |
} | |
} | |
// -------------------------------------------------- | |
// マウスをドラッグしているときの関数 | |
// 引数: ドラッグした先のマウスポインタの位置のx座標 x, y座標 y | |
// ・少しドラッグするたびに、毎回実行される。 | |
// ・重い処理をしているときなどは、1ピクセルのドラッグごとに実行されない場合もあるので注意! | |
void mouseDragged(int x, int y) | |
{ | |
printf( "Mouse Drag Position %d %d\n", x, y ); | |
pos2d diff = {mouse_pos.x - x, mouse_pos.y - y}; | |
mouse_pos.x = x; | |
mouse_pos.y = y; | |
y_rad += diff.x / window.w * M_PI / 5; | |
x_rad += diff.y / window.h * M_PI / 5; | |
// y 軸回転 | |
vm_y[0] = cos(y_rad); | |
vm_y[2] = -sin(y_rad); | |
vm_y[8] = sin(y_rad); | |
vm_y[10] = cos(y_rad); | |
// x 軸回転 | |
vm_x[5] = cos(x_rad); | |
vm_x[6] = sin(x_rad); | |
vm_x[9] = -sin(x_rad); | |
vm_x[10] = cos(x_rad); | |
// 視点の再計算 | |
resize(window.w, window.h); | |
glutPostRedisplay(); // ウィンドウに再描画命令を送る(ポストする) | |
} | |
// -------------------------------------------------- | |
// 描画の初期化関数 | |
// 引数: main 関数の引数と同じ(引数の数 argc, 引数の文字列配列 *argv[]) | |
// ・glutInit 関数で main 関数と同じ引数が必要。 | |
inline void initGLUT(int argc, char *argv[]) | |
{ | |
glutInitWindowPosition(100, 100); // ウィンドウの初期位置を指定する | |
glutInitWindowSize(400, 400); // ウィンドウの初期サイズを指定する | |
glutInit(&argc, argv); // ウィンドウの初期化を行う(この関数を実行して以降、OpenGL の命令を使用可能) | |
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // RGBA、ダブルバッファ、デプスバッファを使用するモード | |
int mainHandle = glutCreateWindow("課題02"); // タイトルを設定して新しいウィンドウを作成し、そのウィンドウ番号を取得する | |
glutSetWindow(mainHandle); // カレントウィンドウ(OpenGL の命令を適用するウィンドウ)に設定する | |
// プログラム実行中、マウス操作・キー操作・アイドル状態などで実行される関数の設定 | |
glutDisplayFunc(display); // ディスプレイに表示するための描画関数を設定 | |
glutReshapeFunc(resize); // ウィンドウサイズが変わったときの関数を設定 | |
// glutKeyboardFunc(keyboard); // キーが押されたときに実行する関数を設定 | |
glutKeyboardFunc(keyboard); | |
glutMouseFunc(mousePressed); // マウスがクリックされたときの関数を指定 | |
glutMotionFunc(mouseDragged); // マウスがドラッグされたときの関数を指定 | |
glutIdleFunc(idle); // アイドル状態で実行する関数を指定 | |
glClearColor(0.7, 1.0, 1.0, 0.0); // 背景をクリアするときの色(引数は 0.0〜1.0 の float 型 R, G, B, A) | |
glEnable(GL_CULL_FACE); // カリング(描画判定無視)を設定 | |
glEnable(GL_DEPTH_TEST); // デプスバッファの使用を開始 | |
glCullFace(GL_BACK); // 裏面を描画しない設定 | |
glEnable(GL_LIGHTING); // ライティング(光源からの光によって、描画するものに陰影を付ける)を使用する設定 | |
float ambientColor[] = { 0.1, 0.1, 0.1, 1.0 }; // アンビエント光(環境光)の色 | |
float diffuseColor[] = { 0.8, 0.8, 0.8, 1.0 }; // ディフューズ光(拡散光)の色 | |
float specularColor[] = { 0.5, 0.5, 0.5, 1.0 }; // スペキュラー光(反射光)の色 | |
float emissionColor[] = { 0.1, 0.1, 0.1, 1.0 }; // エミッション光(自己照明光)の色 | |
float position[] = { 100.0, 100.0, 400.0, 1.0 }; // 光源の位置 | |
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor); // ライトの0番にアンビエント光を設定 | |
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor); // ライトの0番にディフューズ光を設定 | |
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor); // ライトの0番にスペキュラー光を設定 | |
glLightfv(GL_LIGHT0, GL_EMISSION, emissionColor); // ライトの0番にエミッション光を設定 | |
glLightfv(GL_LIGHT0, GL_POSITION, position); // ライトの0番の位置を設定 | |
glLightf (GL_LIGHT0, GL_SHININESS, 255.0); // ライトの0番に反射の強さを設定 | |
glEnable(GL_LIGHT0); // ライトの0番を使用する設定 | |
float dColor[] = { 1.0, 0.1, 0.1, 1.0 }; // マテリアルの拡散光 | |
glMaterialfv(GL_FRONT, GL_DIFFUSE, dColor); // マテリアルの拡散光を設定(表面に設定) | |
glutMainLoop(); // ウィンドウの実行ループを開始 | |
} | |
int main(int argc, char *argv[]) | |
{ | |
initGLUT(argc, argv); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Build
cc glut.cpp -o glut -framework GLUT -framework OpenGL -Wno-deprecated