回転1

前回では書きませんでしたが、拡大縮小の4つのパラメータはアフィン変換という方法が使われています。アフィン変換は数学の行列が関係するのでここでは説明をしません。より複雑なパラメータの組み合わせを試したい場合は、アフィン変換について調べると良いと思います。さて画像を回転させるには、4つの16bitパラメータを以下のように設定します。

PAcos(angle)
PBsin(angle)
PC-sin(angle)
PDcos(angle)

このように値をセットすればそれだけで元の画像を回転させた画像が表示されますが、C標準関数のsin,cosは浮動小数点用なのでそのまま使うには問題があります。GBAのCPUでは浮動小数演算は非常に遅いので、処理速度の面で使いづらいです。GBAでsin、cosの値を利用したいときは、あらかじめ配列に整数のデータとして作成しておき、その配列から値を取得するようにすると速度の面で不安がなくなります。s16の配列でSinTab[]、CosTab[]という配列のデータを使います。この配列は符号付の-256~256の範囲のデータで、360個のデータを持ち、配列の要素1個につき1°になります。

また整数の角度から配列のデータを取得するGetSin()、GetCos()関数を作っておきます。サインテーブルなどはパソコン上で簡単なプログラムを作り、それで出力したデータを使うといいでしょう。以上の用意が終われば、以下のようにするだけで任意の角度(整数)に画像を回転させて表示することができます。適当な数値をかければ拡大縮小も同時に行うことも可能です。

REG_BG2PA =  GetCos(angle);
REG_BG2PB =  GetSin(angle);
REG_BG2PC = -GetSin(angle);
REG_BG2PD =  GetCos(angle);

REG_BG2PA、REG_BG2PB、REG_BG2PC、REG_BG2PD

4000020h - BG2PA - BG2 Rotation/Scaling Parameter A (alias dx) (W)
4000022h - BG2PB - BG2 Rotation/Scaling Parameter B (alias dmx) (W)
4000024h - BG2PC - BG2 Rotation/Scaling Parameter C (alias dy) (W)
4000026h - BG2PD - BG2 Rotation/Scaling Parameter D (alias dmy) (W)

  Bit   Expl.
  0-7   Fractional portion (8 bits)
  8-14  Integer portion    (7 bits)
  15    Sign               (1 bit)

これらのパラメータは28bitの数値で、下位8bitが小数部、上位1bitが符号です。

REG_BGxX、REG_BGxY

#define REG_BG2X	*((vu32 *)(REG_BASE + 0x28))
#define REG_BG2Y	*((vu32 *)(REG_BASE + 0x2c))
#define REG_BG3X	*((vu32 *)(REG_BASE + 0x38))
#define REG_BG3Y	*((vu32 *)(REG_BASE + 0x3c))

これに加えて、BGの回転では、回転の中心を画面の中心になるようにしてみます。画面の中心を回転の中心になるようにするには、BG面全体を動かします。これは拡大縮小パラメータの4つの数値ではなく、REG_BG2XとREG_BG2Yで行います。

REG_BG2XとREG_BG2Yは、格納した値がそのまま画面上のBGの移動になるのでなく、拡大縮小回転パラメータに影響されます。BGが1/10に縮小される場合は、REG_BG2Xのセットした値の1/10だけ画面上で移動することになります。また、BGが回転している場合は、回転したあとのBGの上下左右を基準に画像が移動します。REG_BG2XとREG_BG2Yに格納する値の計算式は以下のようになります。計算式の求め方について詳しくは解説しません。

bgx, bgyBGオフセットレジスタ
x1, y1BG面での回転の中心座標(x1,y1)
hzoom, vzoom横・縦の拡大率
θ回転の角度
α(0,0)から(x1,y1)までの長さ
α = sqrt(x1*x1 + y1*y1)
β(0,0)から(x1,y1)までの角度
β = atan2(y1,x1)

こちらも浮動小数点で求めると処理が重くなるので、あらかじめ分かる値は入れておき、sin、cos配列も使います。今回は(120,80)が中心なのでx1 = 120、y1 = 80、α ≒ 144、β ≒ 33としておきます。

s32 bg2x = 120 * 256 - 144 *  GetCos(angle-33);
s32 bg2y =  80 * 256 - 144 * -GetSin(angle-33);

また、REG_BG2X、REG_BG2Yに格納するときに、値がマイナスの場合は0xFFFFFFFからその値を引くようにします。(REG_BG2Xなどは32bitの変数として扱われているので、28bitとして格納したいときに符号の位置がおかしくなります。繰り返しになりますが32bit単位ではないので注意してください。

4000028h - BG2X_L - BG2 Reference Point X-Coordinate, lower 16 bit (W)
400002Ah - BG2X_H - BG2 Reference Point X-Coordinate, upper 12 bit (W)
400002Ch - BG2Y_L - BG2 Reference Point Y-Coordinate, lower 16 bit (W)
400002Eh - BG2Y_H - BG2 Reference Point Y-Coordinate, upper 12 bit (W)
These registers are replacing the BG scrolling registers which are used for Text mode, ie.
the X/Y coordinates specify the source position from inside of the BG Map/Bitmap of the pixel to be displayed at upper left of the GBA display.
The normal BG scrolling registers are ignored in Rotation/Scaling and Bitmap modes.

  Bit   Expl.
  0-7   Fractional portion (8 bits)
  8-26  Integer portion    (19 bits)
  27    Sign               (1 bit)
  28-31 Not used
	//REG_BGX,Yの28bitフォーマットに調整
	if(bg2x < 0)
	{
	 	REG_BG2X = 0xFFFFFFF - abs(bg2x);
	}
	else
	{
		REG_BG2X = abs(bg2x);
	}
	
	if(bg2y < 0)
	{
		REG_BG2Y = 0xFFFFFFF - abs(bg2y);
	}
	else
	{
		REG_BG2Y = abs(bg2y);
	}

画面全体を回転

動作画面

1.png

履歴


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS