Skip to content

Latest commit

 

History

History
160 lines (112 loc) · 5.16 KB

scalerot.md

File metadata and controls

160 lines (112 loc) · 5.16 KB

BG伸縮回転

英語では、Scale and Rotation なので略して scalerot と呼ばれることも多いです。また数学的にはアフィン変換とも呼ばれます。

オフセットレジスタ

伸縮回転とビットマップモードでは、BGスクロールレジスタとして、(テキストモードの)BGnOFSの代わりにこちらが使用されます。

BGスクロールレジスタに入っている値は、伸縮回転とビットマップモードでは無視されます。

  0x0400_0028/0x0400_002c - BG2X/BG2Y - BG2 X/YオフセットX(0-27bit) (W)
  0x0400_0038/0x0400_003c - BG3X/BG3Y - BG3 X/YオフセットX(0-27bit) (W)
  Bit   Expl.
  0-7   小数部分 (8 bits)
  8-26  整数部分 (19 bits)
  27    符号     (1 bit)
  28-31 不使用

例えば、0x12を設定したい時は、分数部分は0x00、整数部分は0x12にしたいのでレジスタには 0x12 << 8 を格納することになります。

符号付きの32bit値を上記のレジスタに書き込むことができますが、このとき最上位bitは無視され、値は28bitに切り捨てられます。

内部レジスタについて

上記の基準点(BGnX/Y)は、VBlankの間に自動的に内部レジスタにコピーされ、最初の走査線の原点を指定します。内部レジスタは、各スキャンラインの後にdmxとdmy(PBとPD)によってインクリメントされます。

VBlank期間外にBGnX/Yを変更すると即座に内部レジスタにコピーされます。

実際のオフセット

BGnX/BGnYは、格納した値がそのまま画面上のBGのオフセットになるのでなく、後述の伸縮回転パラメータに影響されます。

BGが1/10に縮小される場合は、BGnX/BGnYにセットした値の1/10だけ画面上で移動することになります。

また、BGが回転している場合は、回転したあとのBGの上下左右を基準に画像が移動します。

BGnX/BGnYに格納する値の計算式は以下のようになります。

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

伸縮回転パラメータ

  0x0400_0020 - BG2PA - BG2伸縮回転パラメータA (W)
  0x0400_0022 - BG2PB - BG2伸縮回転パラメータB (W)
  0x0400_0024 - BG2PC - BG2伸縮回転パラメータC (W)
  0x0400_0026 - BG2PD - BG2伸縮回転パラメータD (W)
  
  0x0400_0030 - BG3PA - BG3伸縮回転パラメータA (W)
  0x0400_0032 - BG3PB - BG3伸縮回転パラメータB (W)
  0x0400_0034 - BG3PC - BG3伸縮回転パラメータC (W)
  0x0400_0036 - BG3PD - BG3伸縮回転パラメータD (W)
bit 15 14-8 7-0
内容 符号 整数部分 (7 bits) 分数部分 (8 bits)

伸縮回転パラメータの4つの数値(PA,PB,PC,PD)を組み合わせることで、伸縮や回転などさまざまな効果を出すことができます。

GBAでのアフィン変換は以下の行列を座標に対してかけることで行われます。

  [PA, PB]   [cos(θ)/Sx, -sin(θ)/Sx]
  [PC, PD] = [sin(θ)/Sy,  cos(θ)/Sy]
  • θ: 回転角度
  • Sx, Sy: 拡大倍率

拡大倍率が逆数をとることに注意してください。

行列の例

画像を2倍の大きさに拡大する場合は、

  [1/2 * 256,       0]
  [0,       1/2 * 256]

画像をX方向に2倍、Y方向にはそのままの大きさにする場合は、

  [1/2 * 256,       0]
  [0,         1 * 256]

画像を60度回転させる場合は、

  [cos(π/3), -sin(π/3)]
  [sin(π/3), cos(π/3)]
  
  ↓
  
  [0.9921875 * 256, -0.8660254 * 256]
  [0.8660254 * 256,  0.9921875 * 256]

となります。

画像をX方向に2倍、Y方向にはそのままの大きさにして、60度回転させるのを同時にやりたい場合には

  [1/2, 0]   [0.9921875, -0.8660254]   [256, 0]
  [0,   1] * [0.8660254,  0.9921875] * [0, 256]

  ↓

  [1/2 * 0.9921875 * 256, 1/2 * (-0.8660254) * 256]
  [      0.8660254 * 256,          0.9921875 * 256]

  ↓

  [127,      110.8512]
  [221.7025,      254]

となります。

はみでた場合

変換の結果、画像がBGの外にはみ出てしまう場合の挙動はBGモードによってことなります。

BGモードが1,2のときは、BG2CNT,BG3CNTのbit13で、無視するかwrap(1周)するか指定することができます。

BGモードが3,4,5のときははみでた部分は無視されます。