Home | Lesson | Game | Tool | Link

11.フラグエフェクト

ポリゴンの頂点を動的に変更して、旗のような効果を得ます。
画面ではよくわかりませんが、実際はゆらゆらと動いています。


各種定義
sin関数を使用するので、math.hをインクルードしておきます。
また、計算用にπとラジアンを定義します。
divはポリゴンの分割数で、vertexには分割した分だけ頂点配列を用意します。
#include <math.h>

#define div 45
#define PI 3.141592654
float vertex[div][div][3];
float rad = (float)PI/180.0f;

配列の初期化
頂点配列を初期化します。
XY座標は-2.5〜2.5の範囲におさまるように調整します。
Z座標はsin関数を使用して-1.0〜1.0におさまるように調整します。
※sinの引数がラジアンで指定するために、radをかけて調整してあります。
//頂点情報初期化
void init()
{
	int i,j=0;
	float v = 360/div;//1処理あたりの度数
	for(i=0;i<div;i++)
	{
		for(j=0;j<div;j++)
		{
			vertex[i][j][0]=float((i*5.0)/div-2.5);//-2.5〜2.5の範囲に
			vertex[i][j][1]=float((j*5.0)/div-2.5);//-2.5〜2.5の範囲に
			vertex[i][j][2]=float(sin(i*v*rad));//1.0〜-1.0
		}
	}
}

描画の前準備
いつものように、ポリゴンを描画する際の前準備をしておきます。
void makeScene(IVideoDriver *driver)
{
	int x,y;
	float hold;
	float x1,y1,x2,y2;
	u16 list[] = {0,1,2, 2,1,3};
	S3DVertex ver[4];

	//テクスチャ読み込み
	ITexture* Texture;
	Texture = driver->getTexture("wall.bmp");
	SMaterial Material;
	Material.Lighting = false;
	Material.BackfaceCulling = false;
	Material.TextureLayer[0].Texture = Texture;
	driver->setMaterial(Material);

描画
頂点情報をもとにポリゴンを描画します。
テクスチャのUVは分割した値を計算してセットしています。
	for(x=0;x<div-1;x++)
	{
		for(y=0;y<div-1;y++)
		{
			x1 = float(x  )/(div-1);
			y1 = float(y  )/(div-1);
			x2 = float(x+1)/(div-1);
			y2 = float(y+1)/(div-1);

			ver[0] = S3DVertex(
				vertex[x  ][y  ][0], 
				vertex[x  ][y  ][1], 
				vertex[x  ][y  ][2], 
				0,0,1, 0xFFFFFFFF, x1,y1);
			ver[1] = S3DVertex(
				vertex[x+1][y  ][0], 
				vertex[x+1][y  ][1], 
				vertex[x+1][y  ][2], 
				0,0,1, 0xFFFFFFFF, x2,y1);
			ver[2] = S3DVertex(
				vertex[x  ][y+1][0], 
				vertex[x  ][y+1][1], 
				vertex[x  ][y+1][2], 
				0,0,1, 0xFFFFFFFF, x1,y2);
			ver[3] = S3DVertex(
				vertex[x+1][y+1][0], 
				vertex[x+1][y+1][1], 
				vertex[x+1][y+1][2], 
				0,0,1, 0xFFFFFFFF, x2,y2);
			driver->drawIndexedTriangleList(&ver[0], 4, &list[0], 2);
		}
	}

Z座標の更新
Z座標を1つずつずらします。
これにより、動いているように見えます。
	//頂点情報(Z)更新
	for(y=0;y<div;y++)
	{
		hold = vertex[0][y][2];
		for(x=0;x<div-1;x++)
		{
			vertex[x][y][2] = vertex[x+1][y][2];
		}
		vertex[div-1][y][2] = hold;
	}
}

初期化関数の呼び出し
メインループ前に初期化関数を呼び出しておきます。
	//カメラ設定
	smgr->addCameraSceneNode(0, vector3df(0,0,-5), vector3df(0,0,0));//通常カメラ

	init();

	while(device->run())
	{

ダウンロード
今回作成したファイル一式です。

宿題
1.はためく速度を半分/倍にしてみましょう。
2.旗全体を回転させてみましょう。