Skip to content

Instantly share code, notes, and snippets.

@ww24

ww24/glut.cpp Secret

Last active August 29, 2015 14:15
Show Gist options
  • Save ww24/f4a85e91a6563962d8ed to your computer and use it in GitHub Desktop.
Save ww24/f4a85e91a6563962d8ed to your computer and use it in GitHub Desktop.
GLUT Sample Code
#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;
}
@ww24
Copy link
Author

ww24 commented Feb 8, 2015

Build

cc glut.cpp -o glut -framework GLUT -framework OpenGL -Wno-deprecated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment