振動子のアニメーション (OpenGL + VisualC++)
各点(20×20)に初期変位(Ax,Ay,Az)を与え、sin(ωt)で振動している様子。 初期値はランダムで与えているので、特に物理的意味はなし。
プログラム
////////////////////////////////////////////////////////////////////////// // 仮想物理実験室(ver 1.0) ////////////////////////////////////////////////////////////////////////// #include <math.h> #include <fstream> #include <sstream> #include <iostream> #include <direct.h> #include <time.h> #include <GL/glut.h> #include <GL/gl_material.h> #include <GL/gl_screenshot.h> using namespace std; double PI = acos(-1.0); ////////////////////////////////////////////////////////////////////////// // 変数の定義 ////////////////////////////////////////////////////////////////////////// #define _BITMAP 0 //アニメーション作成用ビットマップの保存 0:しない 1:する //-------------------------------------------------------- // 仮想物理実験室変数の定義 //-------------------------------------------------------- double t = 0.0; //時刻 double dt= 1.0; //時間刻み double omega = 2.0*PI * 1.0/40.0; int tn = 0; //ステップ数 // ボールの定義 struct BALL { double x, y, z; double Ax, Ay, Az; }; const int L = 20; const int N = L*L; BALL ball[N]; void SetUp(void){ for(int i=0; i<L; i++ ){ for(int j=0; j<L; j++ ){ ball[i*L+j].x = double(i); ball[i*L+j].y = double(j); ball[i*L+j].z = 0.0; ball[i*L+j].Ax = ((double)rand()-(double)rand())/(double)RAND_MAX; //変位の設定 ball[i*L+j].Ay = ((double)rand()-(double)rand())/(double)RAND_MAX; //変位の設定 ball[i*L+j].Az = ((double)rand()-(double)rand())/(double)RAND_MAX; //変位の設定 } } } //-------------------------------------------------------- // OpenGL用変数定 //-------------------------------------------------------- ////////////////////////////////////////// // ウィンドウ生成用 int WindowPositionX = 200; //生成するウィンドウ位置のX座標 int WindowPositionY = 200; //生成するウィンドウ位置のY座標 int WindowWidth = 512; //生成するウィンドウの幅 int WindowHeight = 512; //生成するウィンドウの高さ char WindowTitle[] = "仮想物理実験室(ver 1.0)"; //ウィンドウのタイトル static GLfloat LightPosition[4] = { -10, -20, 70, 1 }; //光源の位置 ////////////////////////////////////////// // アニメーション用 ビットマップ保存 gl_screenshot gs; //「gl_screenshot」クラスのインスタンス「gs」を宣言 ////////////////////////////////////////// //-------------------------------------------------------- // 関数のプロトタイプ //-------------------------------------------------------- ////////////////////////////////////////// // メイン関数用 void Initialize(void); void Display(void); void Idle(void); void Keyboard(unsigned char key, int x, int y); ////////////////////////////////////////// // 描画用 void Calculate(void); //計算 //-------------------------------------------------------- // メイン関数 //-------------------------------------------------------- int main(int argc, char *argv[]){ srand((unsigned)time(NULL)); SetUp(); #if _BITMAP _mkdir("bitmap"); //bmpファイル保存用のフォルダの作成 #endif glutInit(&argc, argv); //環境の初期化 glutInitWindowPosition(WindowPositionX, WindowPositionY); //ウィンドウの位置の指定 glutInitWindowSize(WindowWidth, WindowHeight); //ウィンドウサイズの指定 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモードの指定 glutCreateWindow(WindowTitle); //ウィンドウの作成 glutDisplayFunc(Display); //描画時に呼び出される関数を指定する(関数名:Display) glutIdleFunc(Idle); //プログラムアイドル状態時に呼び出される関数 Initialize(); //初期設定の関数を呼び出す glutMainLoop(); return 0; } //-------------------------------------------------------- // 初期設定の関数 //-------------------------------------------------------- void Initialize(void){ glClearColor(0.0, 0.0, 0.0, 0.0); //背景色 glEnable( GL_DEPTH_TEST ); //デプスバッファを使用:glutInitDisplayMode() で GLUT_DEPTH を指定する glDepthFunc( GL_LEQUAL ); glClearDepth( 1.0 ); ////////////////////////////////////////// //透視変換行列の設定 glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列) glLoadIdentity();//行列の初期化 gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far); } //-------------------------------------------------------- // 描画の関数 //-------------------------------------------------------- void Display(void) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); ////////////////////////////////////////// //モデルビュー変換行列の設定 glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列) glLoadIdentity();//行列の初期化 glViewport(0, 0, WindowWidth, WindowHeight); ////////////////////////////////////////// //視点の設定 gluLookAt( double(L/2), -25.0, 40.0, // 視点の位置x,y,z; double(L/2), 0.0, 10.0, // 視界の中心位置の参照点座標x,y,z 0.0, 0.0, 1.0 ) ; //視界の上方向のベクトルx,y,z ////////////////////////////////////////// // 光源ON glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); glLightfv( GL_LIGHT0,GL_POSITION,LightPosition ); ////////////////////////////////////////// // 描画 glPushMatrix(); Calculate(); //計算 glPopMatrix(); ////////////////////////////////////////// //陰影OFF glDisable(GL_AUTO_NORMAL); glDisable(GL_NORMALIZE); glDisable(GL_LIGHTING); ////////////////////////////////////////// //ビットマップの保存 #if _BITMAP ostringstream fname; int tt = tn +10000; fname << "bitmap/" << tt << ".bmp" ;//出力ファイル名 string name = fname.str(); gs.screenshot(name.c_str(), 24); #endif glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可 } //-------------------------------------------------------- // 計算と物体の描画 //-------------------------------------------------------- void Calculate(){ t = dt * double(tn); for(int i=0; i<N; i++){ glPushMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT, ms_ruby.ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, ms_ruby.diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, ms_ruby.specular); glMaterialfv(GL_FRONT, GL_SHININESS, &ms_ruby.shininess); glTranslated(ball[i].x + ball[i].Ax * sin(omega*t), ball[i].y + ball[i].Ay * sin(omega*t), ball[i].z + ball[i].Az * sin(omega*t)); //平行移動値の設定 glutSolidSphere(0.5, 20, 20); //引数:(半径, Z軸まわりの分割数, Z軸に沿った分割数) glPopMatrix(); } tn++; } //-------------------------------------------------------- // アイドル時に呼び出される関数 //-------------------------------------------------------- void Idle(){ glutPostRedisplay(); //glutDisplayFunc()を1回実行する }
インクルードファイル
gl_screenshot.hとgl_material.hは、インクルードファイルです。