現在地: メニュー >> 実践編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;
		}
	}
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます