dragon spx

FFDスプライトってなに?

自由に変形できるスプライトのこと。4頂点を自由に指定してねじれたスプライトなんかを表現できる。Free Form Deformationの略。そもそもねじれたポリゴンとはどういうものなのか?2枚の三角形で構成できるものなのか?画像を見てもらえばわかると思う。

ffd01.PNG

ねじれているけどこれじゃない。ねじれているというよりは折れている。
2枚の三角形だとコレが限界。テクスチャの歪みがひどい。

ffd02.PNG

4分割。分割数を増やすと滑らかになってテクスチャの歪みが減る。

ffd03.PNG

9分割 だいぶなめらかになってる。テクスチャの歪みもわかりにくくなった。

ffd04.PNG

16分割 9分割よりは綺麗に見えるけどあまり違いがなくなってきた。

ffd05.PNG
256分割 ここまで細かくしても16分割と大差ない感じ。ポリゴンの無駄かな。

結局どういうものなのか?

1枚の四角形を複数のメッシュに分けて構成することで表現する。どんな4頂点にも対応しようと思うと2枚の三角形ではねじれに限界がでてくるので分割数を増やさないと上記の通りテクスチャが崩れてしまう。

プログラム

すごくベタに書くとこんな感じ。

{
	dqPoint pos[4];

	Sint32 div = divNum+1;

	if( div < 2  ) div = 2;
	if( div > 16 ) div = 16;

	for( Sint32 ii=0; ii<4; ii++ )
	{
		pos[ii].x = pXY[ii].x;
		pos[ii].y = pXY[ii].y;

		pos[ii].x *= fx;
		pos[ii].y *= fy;

		dqUtil::RotationPoint( &pos[ii] , fRot );
	}

	Sint32 max = div*div;

	dqPoint* pMat = new dqPoint[max];
	dqPoint* pTx  = new dqPoint[max];

	//四辺の分割座標を確定

	for( Sint32 ii=0;ii<div;ii++ )
	{
		pMat[ ii ].x = pos[0].x + 1.0f * ii * ( pos[1].x - pos[0].x ) /( div-1 );
		pMat[ ii ].y = pos[0].y + 1.0f * ii * ( pos[1].y - pos[0].y ) /( div-1 );

		pMat[ (div-1)*div+ii ].x = pos[3].x + 1.0f * ii * ( pos[2].x - pos[3].x ) /( div-1 );
		pMat[ (div-1)*div+ii ].y = pos[3].y + 1.0f * ii * ( pos[2].y - pos[3].y ) /( div-1 );

		pMat[ ii*div ].x = pos[0].x + 1.0f * ii * ( pos[3].x - pos[0].x ) /( div -1 );
		pMat[ ii*div ].y = pos[0].y + 1.0f * ii * ( pos[3].y - pos[0].y ) /( div -1 );

		pMat[ ii*div+(div-1) ].x = pos[1].x + 1.0f * ii * ( pos[2].x - pos[1].x ) /( div -1 );
		pMat[ ii*div+(div-1) ].y = pos[1].y + 1.0f * ii * ( pos[2].y - pos[1].y ) /( div -1 );
	}

	//中の補完座標を策定

	for( Sint32 ii=1;ii<div-1;ii++ )
	{
		for( Sint32 xx=1;xx<div-1;xx++ )
		{
			Float32 x1 = pMat[ ii*div+0 ].x;
			Float32 y1 = pMat[ ii*div+0 ].y;
			Float32 x2 = pMat[ ii*div+(div-1) ].x;
			Float32 y2 = pMat[ ii*div+(div-1) ].y;

			pMat[ ii*div+xx ].x = x1 + xx * (x2-x1)/(div-1);
			pMat[ ii*div+xx ].y = y1 + xx * (y2-y1)/(div-1);
		}
	}

	for( Sint32 yy=0;yy<div;yy++)
	{
		for( Sint32 xx=0;xx<div;xx++)
		{
			pTx[ yy*div + xx ].x = u + 1.0f * xx *  w  / (div-1);
			pTx[ yy*div + xx ].y = v + 1.0f * yy *  h  / (div-1);
		}
	}


	for( Sint32 yy=0;yy<div-1;yy++)
	{
		for( Sint32 xx=0;xx<div-1;xx++)
		{
			Sint32 p1,p2,p3,p4;
			p1 = yy*div + xx;
			p2 = yy*div + xx+1;
			p3 = yy*div + xx+1+div;
			p4 = (yy+1)*div + xx;

			dqLib::PutTriangle(
					pMat[ p1 ].x+x , pMat[ p1 ].y+y ,	pTx[p1].x , pTx[p1].y,
					pMat[ p2 ].x+x , pMat[ p2 ].y+y ,	pTx[p2].x , pTx[p2].y,
					pMat[ p4 ].x+x , pMat[ p4 ].y+y ,	pTx[p4].x , pTx[p4].y,
					0,
					prio ,ATR_DFLT , ARGB_DFLT );

			dqLib::PutTriangle(
					pMat[ p2 ].x+x , pMat[ p2 ].y+y ,	pTx[p2].x , pTx[p2].y,
					pMat[ p4 ].x+x , pMat[ p4 ].y+y ,	pTx[p4].x , pTx[p4].y,
					pMat[ p3 ].x+x , pMat[ p3 ].y+y ,	pTx[p3].x , pTx[p3].y,
					0,
					prio ,ATR_DFLT , ARGB_DFLT );

		}
	}


	SAFE_DELETES( pMat );
	SAFE_DELETES( pTx );

	return 0;
}