振動子のアニメーション (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は、インクルードファイルです。



