HOME > natural science Laboratory > コンピュータ・シミュレーション講座 > TIPS 集

振動子のアニメーション (OpenGL + VisualC++)

文責:遠藤 理平 (2010年2月21日) カテゴリ:TIPS 集(84)備忘録(17)

各点(20×20)に初期変位(Ax,Ay,Az)を与え、sin(ωt)で振動している様子。 初期値はランダムで与えているので、特に物理的意味はなし。

2010221a.gif

プログラム

//////////////////////////////////////////////////////////////////////////
// 仮想物理実験室(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.hgl_material.hは、インクルードファイルです。



▲このページのトップNPO法人 natural science トップ

関連記事

TIPS 集







備忘録

▲このページのトップNPO法人 natural science トップ