English
SGL User's ManualPROGRAMMER'S TUTORIAL
戻る進む

8-9. 回転スクロール画面

 回転スクロール画面“RBG0”は、スクロールの拡大縮小と回転が可能です。
また、ノーマルスクロールとは考え方が異なりますが、スクロールの縦横それぞれへの移動も実行可能です。
ここでは、回転スクロールの移動、拡大縮小、回転機能をサンプルプログラムと共に解説していきます。

回転スクロールの移動

 回転スクロールの移動も、実際はスクロール表示位置の変化として実現されます。
関数“slLookR”を利用することで、見かけ上、スクロールがモニターに対して上下左右それぞれに移動しているように見せることができます。

図8-21 回転スクロールの移動イメージ

 回転スクロール画面の拡大縮小

 SGLでは、回転スクロール画面の拡大縮小操作も可能になっています。回転スクロール画面の拡大縮小はノーマルスクロール画面の拡大縮小と異なり、常に任意倍率での拡大縮小が可能です。
また、回転スクロール画面の場合、後述するスクロール回転操作、拡大縮小操作、移動操作との併用も可能です。
SGLで回転スクロール画面の拡大縮小を実行したい場合は、ライブラリ関数“slZoomR”を使用してください。

【void slZoomR ( FIXED scale_x , FIXED scale_y ) ;】
 回転スクロール画面”RBG0”の拡大縮小を行い、現在の状態をカレント回転パラメータに保存します(カレントパラメータは関数“slCurRpara”で切り替え可能)。
パラメータには、スクロール縦横の倍率を逆数で代入します。
例えば、2倍に拡大したい場合はパラメータに1/2を代入、1/2倍に縮小したい場合は2を代入します。
回転スクロールの場合、拡大縮小は常に任意倍率で設定可能です。

 回転スクロール画面の回転

 セガサターンでは、回転スクロール画面に対して任意軸・任意角値でのスクロール回転が可能になっています
(下図はイメージモデル)。

図8-22 スクロール回転イメージ

●2D回転(Z軸回転)
 SGLで回転スクロール画面の2D回転操作(Z軸回転)を行いたい場合、ライブラリ関数“slZrotR”を使用してください。
回転の中心となる点(スクロールマップ上の一点)は、ライブラリ関数“slDispCenterR”で設定された点を使用します。

【void slZrotR ( ANGLE z_angle ) ;】
 回転スクロール画面“RBG0”を、Z軸に対して回転させます。
パラメータには、カレント回転パラメータのZ軸回転角を指定します。
回転角は、現在の状態からの回転角値ではなく、絶対的な回転角値を代入してください。
(カレントパラメータは関数“slCurRpara”で切り替え可能)。
また、回転中心はライブラリ関数“slLookR”で設定された点を使用します。

図8-23 スクロール回転の実際の動作

関数使用上の注意
 回転スクロールの変換操作操作に使用される関数群“slZrotR”、“slZoomR”、“slLookR”は、同じく回転スクロールの各種変換操作(3D回転含む)を行う関数“slScrMatSet”と、同一の回転パラメータにおいて、併用できませんので注意してください。
これは、前記関数群が回転パラメータの特定領域の書き換えを行うのに対して、後記関数群は回転パラメータ全域に対する書き換えを実行するためです。

 次のサンプルプログラム(リスト8-5)は、SGLライブラリ関数を用いて、実際に回転スクロール画面の回転操作を行った例です。

リスト8-5 sample_8_9_1:スクロールの2D回転

/*----------------------------------------------------------------------*/
/*	Graphic Rotation						*/
/*----------------------------------------------------------------------*/
#include	"sgl.h"
#include	"ss_scrol.h"

#define		RBG0_CEL_ADR		VDP2_VRAM_A0
#define		RBG0_MAP_ADR		VDP2_VRAM_B0
#define		RBG0_COL_ADR		( VDP2_COLRAM + 0x00200 )
#define		RBG0_PAR_ADR		( VDP2_VRAM_A1 + 0x1fe00 )
#define		BACK_COL_ADR		( VDP2_VRAM_A1 + 0x1fffe )

void ss_main(void)
{
	ANGLE yama_angz = DEGtoANG(0.0);
	FIXED posx = toFIXED(128.0) , posy = toFIXED(64.0);
	
	slInitSystem(TV_320x224,NULL,1);
	slTVOff();
	slPrint("Sample program 8.9.1" , slLocate(9,2));

	slColRAMMode(CRM16_1024);
	slBack1ColSet((void *)BACK_COL_ADR , 0);

	slRparaInitSet((void *)RBG0_PAR_ADR);
	slCharRbg0(COL_TYPE_256 , CHAR_SIZE_1x1);
	slPageRbg0((void *)RBG0_CEL_ADR , 0 , PNB_1WORD|CN_10BIT);
	slPlaneRA(PL_SIZE_1x1);
	sl1MapRA((void *)RBG0_MAP_ADR);
	slOverRA(2);
	Cel2VRAM(yama_cel , (void *)RBG0_CEL_ADR , 31808);
	Map2VRAM(yama_map , (void *)RBG0_MAP_ADR , 32 , 16 , 1 , 0);
	Pal2CRAM(yama_pal , (void *)RBG0_COL_ADR , 256);

	slDispCenterR(toFIXED(160.0) , toFIXED(112.0));
	slLookR(toFIXED(128.0) , toFIXED(64.0));

	slScrAutoDisp(NBG0ON | RBG0ON);
	slTVOn();

	while(1){
		slZrotR(yama_angz);
		yama_angz += DEGtoANG(1.0);
		slSynch();
	} 
}

フロー8-6 sample_8_9_1:スクロールの2D回転

●カレントマトリクスを使用した3D回転
 SGLでカレントマトリクスを利用した回転スクロール画面の3D回転操作(全軸回転)を行うには、以下の手順を踏む必要があります。

1)回転スクロール諸設定
 回転パラメータ設定、画面オーバー処理、係数テーブル設定など、回転スクロール使用に際し必要となる諸設定を済ませます。

2)座標演算
 回転スクロールに掛け合わせる3D回転操作を、まず、カレントマトリクスに対して実行します。
使用する関数群は、“slRorX”、“slTranslate”、“slScale”など同じものを使用します。
ただし、回転・移動・拡大縮小操作の操作順序は、通常の座標変換操作とは逆になります(変換操作順序は“第4章:座標変換”を参照してください)。
また、スクロール座標系はZ軸の正負が逆で左手座標系になりますが、スクロールに対してモニターが回転移動するイメージで捉えられるため、見かけ上は全く同じに映ります。
通常の座標変換操作と同じマトリクス操作手順で座標変換操作を行いたい場合は、マトリクスデータの転送の前に関数“slScrMatConv”を使用するようにしてください。
関数“slScrMatConv”は、通常の座標変換手順で変換されたカレントマトリクスを、スクロール用座標変換マトリクスにコンバートしカレントマトリクスとします。

【void slScrMatConv ( void ) ;】
カレントマトリクスをスクロール用座標変換データにコンバートし、カレントマトリクスを置き換えます。
当然のことながら、スクロール用座標変換操作を実行した後のカレントマトリクスに、当該関数を使用すれば、カレントマトリクスは通常の座標変換用マトリクスに置き換わります。

3)演算結果を回転パラメータに転送
 カレントマトリクスに対して実行された座標演算結果を、回転パラメータに転送します。
回転スクロールは、演算結果を転送された回転パラメータのデータを元に変形・描画されます。
データの転送には、関数“slScrMatSet”を使用します。

【void slScrMatSet ( void ) ;】
 カレント回転パラメータにカレントマトリクスのデータを転送します。
回転スクロールに合わせて座標変換操作を施されたカレントマトリクスの転送に使用してください。

フロー8-7 カレントマトリクスを使用した3D回転操作の手順

●係数テーブルを使用したズーム比率の制御
 回転スクロールの3D回転操作実行時、回転スクロールは、スクロールの奥行きに応じてスクロールをスケーリングさせます。通常、このスケール比率は透視変換など3D座標演算に使用される各パラメータを元に計算し、 スクロールを変形させますが、この変形比率をライン単位あるいはドット単位であらかじめ設定しておき、スクロールの変形実行時に利用することができ、これを係数テーブルと呼びます。
係数テーブルの使用に際しては、次の2つの関数が必要になります。

1)係数テーブルの作成
 まず最初に、VRAM領域中に係数テーブル用の領域を確保しておく必要があります。
係数テーブルは、必ずVRAM中に作成するようにしてください。
また、係数テーブルはVRAM領域中の1バンクを占有します。これは、係数テーブルが、1バンク当たりの最大アクセス回数(8回)でVRAM領域を参照しにいくためです。

【void slMakeKtable ( void *adr ) ;】
 指定されたアドレスに3D回転操作で使用する係数テーブルを作成します。
パラメータには係数テーブルを作成する領域の先頭アドレスを代入します。
また、係数テーブルは必ずVRAM領域中に確保される必要があります。

2)係数テーブル使用モードの設定
 係数テーブルとして指定された領域を係数テーブルとして使用する際、係数テーブルをどのように使用するかの使用モードを決定します。

【void slKtableRA,RB ( void *table_adr , Uint16 mode ) ;】
 使用する係数テーブルのアドレスを指定し、更に係数テーブルの使用内容を決定します。
パラメータには、係数テーブルの先頭アドレス、係数テーブルの使用モードを表す下図の値(or演算子“|”で連結使用可能)をそれぞれ代入してください。
関数“slKtableRA”は回転パラメータAの使用する係数テーブルの設定、関数“slKtableRB”は回転パラメータBの使用する係数テーブルの設定をそれぞれ実行します。

図8-24 “slKtableRA,RB”のパラメータ代入値(mode)
テーブル使用: [K_OFF | K_ON ]|
係数データサイズ:[K_2WORD | K_1WORD]|
係数モード: [K_MODE0 | K_MODE1 | K_MODE2 | K_MODE3]|
ラインカラー: [K_LINECOL ]|
変形単位: [K_DOT | K_LINE ]|
係数固定: [K_FIX ]|

注)
 パラメータに係数固定を指定した場合、係数テーブルがあらかじめ用意されているものとしリアルタイムでの係数テーブルの計算を実行しません。

参照
 係数テーブルの詳細は“HARDWARE MANUAL vol.2:VDP2ユーザーズマニュアル ”を参照してください。

リスト8-6 sample_8_9_2:3D回転

#include	"sgl.h"
#include	"ss_scrol.h"

#define		RBG0RB_CEL_ADR			(VDP2_VRAM_A0            )
#define		RBG0RB_MAP_ADR			(VDP2_VRAM_B0            )
#define		RBG0RB_COL_ADR			(VDP2_COLRAM    + 0x00200)
#define		RBG0RA_CEL_ADR			(RBG0RB_CEL_ADR + 0x06e80)
#define		RBG0RA_MAP_ADR			(RBG0RB_MAP_ADR + 0x02000)
#define		RBG0RA_COL_ADR			(RBG0RB_COL_ADR + 0x00200)
#define		RBG0_KTB_ADR			(VDP2_VRAM_A1            )
#define		RBG0_PRA_ADR			(VDP2_VRAM_A1   + 0x1fe00)
#define		RBG0_PRB_ADR			(RBG0_PRA_ADR   + 0x00080)
#define		BACK_COL_ADR			(VDP2_VRAM_A1   + 0x1fffe)

void ss_main(void)
{
	FIXED	posy = toFIXED(0.0);
	ANGLE	angz = DEGtoANG(0.0);
	ANGLE	angz_up = DEGtoANG(0.0);

	slInitSystem(TV_320x224,NULL,1);
	slTVOff();
	slPrint("Sample program 8.9.2" , slLocate(9,2));

	slColRAMMode(CRM16_1024);

	slRparaInitSet((void *)RBG0_PRA_ADR);
	slMakeKtable((void *)RBG0_KTB_ADR);
	slCharRbg0(COL_TYPE_256 , CHAR_SIZE_1x1);
	slPageRbg0((void *)RBG0RB_CEL_ADR , 0 , PNB_1WORD|CN_12BIT);
	slPlaneRA(PL_SIZE_1x1);
	sl1MapRA((void *)RBG0RA_MAP_ADR);
	slOverRA(0);
	slKtableRA((void *)RBG0_KTB_ADR , K_FIX | K_DOT | K_2WORD | K_ON);
	Cel2VRAM(tuti_cel , (void *)RBG0RA_CEL_ADR , 65536);
	Map2VRAM(tuti_map , (void *)RBG0RA_MAP_ADR , 64 , 64 , 2 , 884);
	Pal2CRAM(tuti_pal , (void *)RBG0RA_COL_ADR , 160);

	slPlaneRB(PL_SIZE_1x1);
	sl1MapRB((void *)RBG0RB_MAP_ADR);
	slOverRB(0);
	slKtableRB((void *)RBG0_KTB_ADR , K_FIX | K_DOT | K_2WORD | K_ON);
	Cel2VRAM(sora_cel , (void *)RBG0RB_CEL_ADR , 28288);
	Map2VRAM(sora_map , (void *)RBG0RB_MAP_ADR , 64 , 20 , 1 , 0);
	Pal2CRAM(sora_pal , (void *)RBG0RB_COL_ADR , 256);

	slRparaMode(K_CHANGE);

	slBack1ColSet((void *)BACK_COL_ADR , 0);

	slScrAutoDisp(NBG0ON | RBG0ON);
	slTVOn();

	while(1)
	{
		slCurRpara(RA);
		slUnitMatrix(CURRENT);
		slTranslate(toFIXED(0.0) , toFIXED(0.0) + posy , toFIXED(100.0));
		posy -= toFIXED(5.0);
		slRotX(DEGtoANG(-90.0));
		slRotZ(angz);
		slScrMatSet();

		slCurRpara(RB);
		slUnitMatrix(CURRENT);
		slTranslate(toFIXED(160.0) , toFIXED(155.0) , toFIXED(100.0));
		slRotZ(angz);
		slScrMatSet();

		angz_up += DEGtoANG(0.5);
		angz = (slSin(angz_up) >> 4);

		slSynch();
	} 
}

フロー8-8 sample_8_9_2:3D回転


戻る進む
SGL User's ManualPROGRAMMER'S TUTORIAL
Copyright SEGA ENTERPRISES, LTD., 1997