最終更新: mikk_ni3_92 2008年12月16日(火) 17:52:35履歴
現在地: メニュー >> 実践編04 >> 実践編04::まとめコード
#include <ctime> #include <cstdlib> #include <GL/glut.h> //--------- 各種外部変数 ------------// //最大値 const int MaxParticle = 500; //パーティクル struct Particles { float life; //生存期間 float fadeSpeed; //消滅速度 float x,y,z; //現在値 float r,g,b,a; //色 float MoveX,MoveY,MoveZ; //移動方向 float xg,yg,zg; //重力 }; Particles balls[MaxParticle]; const float SlowDown = 10.0; //マウスの状態 struct MOUSE { int Xstart,Ystart; bool flag; double weight; }; MOUSE MouseStatus={0,0,false,0.5}; //回転関係 struct ObjectRotate { double xAngle,yAngle; }; ObjectRotate ObjRot={0,0}; //----------- プロトタイプ宣言 ------------// void display(); void reshape(int w, int h); void timer(int value); void myMouseFunc(int button,int state,int x,int y); void myMouseMotion(int x,int y); void DRAW_XYZ(); void InitParticles(); void DrawParticles(); void CalcNextStatus(); //------------- OpenGLの初期設定 ------------------// void GLUT_INIT() { glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE | GLUT_DEPTH); //ダブルバッファ、Zバッファ glutInitWindowSize(640,480); glutCreateWindow("Basic Particle"); } void GLUT_CALL_FUNC() { glutDisplayFunc(display); glutReshapeFunc(reshape); glutTimerFunc(0,timer,17); glutMouseFunc(myMouseFunc); glutMotionFunc(myMouseMotion); } void MY_INIT() { glClearColor(1.0, 1.0, 1.0, 1.0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); //Zバッファ有効化 } //パーティクルの初期化 void InitParticles() { srand( static_cast<unsigned int>( time(NULL) ) ); for(int loop = 0; loop < MaxParticle; ++loop){ //生存時間の設定 balls[loop].life = 1.0; //初期生存時間 balls[loop].fadeSpeed = static_cast<float>((rand() % 100)) / 1000 + 0.003f; //消滅速度(0.001〜0.099 + 0.003) //初期位置の設定 balls[loop].x = balls[loop].y = balls[loop].z = 0; //各移動量決定 balls[loop].MoveX = static_cast<float>( (rand() % 50 - 26.0) ) * 10; balls[loop].MoveY = static_cast<float>( (rand() % 50 - 25.0 ) ) * 10; balls[loop].MoveZ = static_cast<float>( (rand() % 50 - 25.0 ) ) * 10; balls[loop].xg = 0; balls[loop].yg = -1.0; balls[loop].zg = 0; } } //----------- メイン関数 --------------// int main(int argc, char **argv) { glutInit(&argc,argv); GLUT_INIT(); GLUT_CALL_FUNC(); MY_INIT(); InitParticles(); //パーティクルの初期化 glutMainLoop(); return 0; } //----------- ここからコールバック --------------// void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(-6.0, 7.0, 8.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glRotated(ObjRot.xAngle,1,0,0); glRotated(ObjRot.yAngle,0,1,0); DRAW_XYZ(); //XYZ軸の描画 DrawParticles(); glColor3d(1,1,1); //色のリセット glutSwapBuffers(); CalcNextStatus(); //パーティクルの次の状態を計算 } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); //行列モード切替 glLoadIdentity(); //行列初期化 gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); //行列モード切替 } void timer(int t) { glutPostRedisplay(); glutTimerFunc(t,timer,17); //タイマー関数 } void myMouseFunc(int button,int state,int x,int y) { if(button == GLUT_LEFT_BUTTON &&state == GLUT_DOWN){ MouseStatus.Xstart = x; MouseStatus.Ystart = y; MouseStatus.flag = true; } else{ MouseStatus.flag =false; } } void myMouseMotion(int x,int y) { if(MouseStatus.flag == false)return; static int xdir,ydir; xdir = x - MouseStatus.Xstart; ydir = y - MouseStatus.Ystart; ObjRot.xAngle += (double)ydir * MouseStatus.weight; ObjRot.yAngle += (double)xdir * MouseStatus.weight; MouseStatus.Xstart = x; MouseStatus.Ystart = y; //glutPostRedisplay(); } //----------- ここから各種関数 ---------------// void DRAW_XYZ() { glBegin(GL_LINES); glColor3d(0,1,0);//x glVertex2d(-100,0); glVertex2d(100, 0); glColor3d(1,0,0);//y glVertex2d(0,0); glVertex2d(0,100); glColor3d(0,0,1);//z glVertex3d(0,0,-100); glVertex3d(0,0, 100); glEnd(); } void DRAW_TRI() { glBegin(GL_TRIANGLES); glVertex2d(0,1); glVertex2d(-0.5, 0); glVertex2d(0.5, 0); glEnd(); } //------- パーティクル描画 -------// void DrawParticles() { glEnable(GL_BLEND); glPointSize(3); glBegin(GL_POINTS); for(int loop = 0; loop < MaxParticle; ++loop){ glColor4f(0,0,1,balls[loop].life); glVertex3f(balls[loop].x,balls[loop].y,balls[loop].z); } glEnd(); glDisable(GL_BLEND); glPointSize(1); } void CalcNextStatus() { for(int loop = 0; loop < MaxParticle; ++loop){ balls[loop].life -= balls[loop].fadeSpeed;//ライフを減らす if (balls[loop].life <= 0)//ライフチェック { balls[loop].life = 1.0; //初期生存時間 balls[loop].fadeSpeed = static_cast<float>((rand() % 100)) / 1000 + 0.003f; //消滅速度(0.001〜0.099 + 0.003) //初期位置の設定 balls[loop].x = balls[loop].y = balls[loop].z = 0; //各移動量決定 balls[loop].MoveX = static_cast<float>( (rand() % 50 - 26.0) ) * 10; //最大230 balls[loop].MoveY = static_cast<float>( (rand() % 50 - 25.0 ) ) * 10; //最大240 balls[loop].MoveZ = static_cast<float>( (rand() % 50 - 25.0 ) ) * 10; //最大240 // balls[loop].xg = 0; balls[loop].yg = -0.8; balls[loop].zg = 0; }else{ //位置更新 balls[loop].x += balls[loop].MoveX/(SlowDown*1000); balls[loop].y += balls[loop].MoveY/(SlowDown*1000); balls[loop].z += balls[loop].MoveZ/(SlowDown*1000); balls[loop].MoveX += balls[loop].xg; balls[loop].MoveY += balls[loop].yg; balls[loop].MoveZ += balls[loop].zg; } } }