/************************************************************
  Ninja Sample
  COPYRIGHT (C) SEGA ENTERPRISES, LTD.

  タイトル ： マルチライト
************************************************************/

#include <shinobi.h>
#include <njdef.h>

void main(void)
{
    njUserInit();
    while (njUserMain() == NJD_USER_CONTINUE) {
        njWaitVSync();
    }
    njUserExit();
}

/* 外部定義のモデルデータとテクスチャデータ */
#define	OBJ		 object_tea_Teapot1E_Teapot1E
#define	TEXLIST	texlist_tea_Teapot1E
extern NJS_CNK_OBJECT   OBJ[];
extern NJS_TEXLIST  TEXLIST;

/* マトリクス関連 */
#define MATRIX_DEPTH 16
#define VERTEX_MAX   5000

/* 光源 ＆ カメラ */
static NJS_CAMERA  camera;
static NJS_LIGHT g_Light;

/* 回転データ */
static Angle g_XAng = NJM_DEG_ANG(0.0F);
static Angle g_YAng = NJM_DEG_ANG(0.0F);
static Angle g_ZAng = NJM_DEG_ANG(0.0F);

/* テクスチャ関連 */
#define TEXTURE_NUM 1
static NJS_TEXMEMLIST g_Texture[TEXTURE_NUM]; /*テクスチャデータ保持領域*/

static NJS_VERTEX_BUF *g_VBuf;
static NJS_MATRIX *g_Matrix;  /* マトリクススタック */

/* ローカル関数プロトタイプ宣言 */
void SimpleLightOnOff(void);
void InitCnkSimpleMultiLight(void);
void ExecCnkSimpleMultiLight(void);
void EasyLightOnOff(void);
void InitCnkEasyMultiLight(void);
void ExecCnkEasyMultiLight(void);

/**********************************************************************
    njUserInit --- Ninjaシステム初期化関数
**********************************************************************/
void njUserInit(void)
{
    /* システムの初期化 */
	sbInitSystem( NJD_RESOLUTION_640x480_NTSCNI, NJD_FRAMEBUFFER_MODE_RGB565, 1 );
   /* 画面のアスペクト比を設定 */
    njSetAspect( 1.0F, 1.0F );
    /* メモリの割り当て */
    g_Matrix = (NJS_MATRIX *)syMalloc(sizeof(NJS_MATRIX) * MATRIX_DEPTH);
    g_VBuf = (NJS_VERTEX_BUF *)syMalloc(sizeof(NJS_VERTEX_BUF) * VERTEX_MAX);
    njInitTextureBuffer( ( Sint8 * )g_VBuf, 0x800*10 );
    /* 背景色の設定 */
	njSetBackColor(0x00000000,0x00000000,0x000000FF);
    /* 頂点格納バッファの確保 */
    njInitVertexBuffer(80000, 0, 80000, 0, 0);
	njInitPrint( NULL, 0, NJD_TEXFMT_ARGB_1555 );
    /* マトリクススタックの初期化 */
    njInitMatrix(g_Matrix, MATRIX_DEPTH, 1);
    /* 頂点演算用バッファの初期化 */
    njInit3D( g_VBuf, VERTEX_MAX);
    /* カメラの初期化 */
    njInitCamera(&camera);
    njSetCamera(&camera);

    /* テクスチャのロードとセットアップ */
    njInitTexture(g_Texture, TEXTURE_NUM);  /* テクスチャの領域を確保 */
    njLoadTexture(&TEXLIST);  /* テクスチャリストのデータのロード */
    njSetTexture(&TEXLIST);   /* テクスチャリストをカレントにセット */

    /* クリッピング面の設定 */
    njClipZ( -1.0f, -500.f );

    /* テキストの設定 */
	njPrintSize(16);
    njPrintColor(ARGB(0xff, 0xc0, 0xc0, 0xc0));

	njSetBorderColor(0x00000000);

	/* njCnkSimpleMulti のライト設定 */
	InitCnkSimpleMultiLight();

	/* njCnkEasyMulti のライト設定 */
	InitCnkEasyMultiLight();
}

#define LTNUM	10
#define RANGE	10
Sint32 _num = 0;
static char *_name[LTNUM]= {
	"ALL", "OFF", "DIR", "PT1", "PT2", "PT3", "P12", "P13", "P23", "P123",
};
static int _lt_1[LTNUM]={1,0,1,0,0,0,0,0,0,0};
static int _lt_2[LTNUM]={1,0,0,1,0,0,1,1,0,1};
static int _lt_3[LTNUM]={1,0,0,0,1,0,1,0,1,1};
static int _lt_4[LTNUM]={1,0,0,0,0,1,0,1,1,1};

Sint32	xx,yy,zz = 0;
NJS_PERIPHERAL *per;

Sint32 njUserMain(void)
{
static Sint32 mode = 0;
static	Sint32 _stop = 1;

	per = (PDS_PERIPHERAL *) njGetPeripheral(NJD_PORT_A0);

	/* ライトのＯＮ／ＯＦＦ */
	if( per->press & NJD_DGT_TA ) {
		_num++;
		_num %= LTNUM;
		if (mode == 0) SimpleLightOnOff();
		else EasyLightOnOff();
	}
	njPrint(NJM_LOCATION(2,5), "LIGHT : %s", _name[_num]);

	/* Simple と Easy の切り替え */
	if (per->press & NJD_DGT_TX) {
		if (!(mode = ~mode)) SimpleLightOnOff();
		else EasyLightOnOff();
	}
	if (mode == 0) {
		ExecCnkSimpleMultiLight();
	} else {
		ExecCnkEasyMultiLight();
	}

	/* モデルの回転ＯＮ／ＯＦＦ */
	if(per->press & NJD_DGT_ST){
		_stop ^= 1;
	}
	if (_stop) {
		xx += 257;
		yy += 179;
		zz += 193;
	}
	njPrintC(NJM_LOCATION(2,23), "    A:CHANGE LIGHT");
	njPrintC(NJM_LOCATION(2,24), "    X:CHANGE DRAW");
	njPrintC(NJM_LOCATION(2,25), "START:PAUSE");

    return NJD_USER_CONTINUE;
}

/**********************************************************************

    njUserExit --- Ninjaシステム終了処理関数

**********************************************************************/

void njUserExit(void)
{
    /* メモリの開放 */
    syFree(g_Matrix);
    syFree(g_VBuf);
	njExitPrint();
    njExitTexture();
    /* システムの終了処理をします 最後に必ず呼び出してください */
    sbExitSystem();
}


/*----------------------------------------------
     njCnkSimpleMulti のライト設定と処理本体
 --------------------------------------------- */
void InitCnkSimpleMultiLight(void)
{
	/* チャンクライトの個数の設定              *
	 * （内部で光源設定キューを持たないので    *
	 *   個数とライトの種類は以下のように      *
	 *   関連します。                     ）   *
	 *                                         *
	 * 1:平行光源１                            *
	 * 2:平行光源１+点光源２                   *
	 * 3:平行光源１+点光源２+点光源３          *
	 * 4:平行光源１+点光源２+点光源３+点光源４ *
	 *                                         */

	njCnkSetSimpleMultiLight(4);

	/* チャンクライトの平行光源（一番目の光源）方向設定 */
	njCnkSetSimpleMultiLightVector(0.f, 0.f, -1.f);

	/* チャンクライトの点光源位置設定 */
	/* ２番目の光源（点光源）の設定 */
	njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_2, 0.f, 0.f, -12.f);
	/* ３番目の光源（点光源）の設定 */
	njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_3, 0.f, 0.f, -12.f);
	/* ４番目の光源（点光源）の設定 */
	njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_4, 0.f, 0.f, -12.f);

	/* チャンクライトの点光源範囲（距離）設定 */
	njCnkSetSimpleMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_2, 6.f, 40.f);
	njCnkSetSimpleMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_3, 6.f, 40.f);
	njCnkSetSimpleMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_4, 6.f, 40.f);

	/* チャンクライトのアンビエント色設定 */
	njCnkSetSimpleMultiAmbient(0.1f, 0.1f, 0.1f);

	/* チャンクライトの光源色設定 */
	njCnkSetSimpleMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_1, 0.5f, 0.5f, 0.5f);
	njCnkSetSimpleMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_2, 1.f, 0.0f, 0.0f);
	njCnkSetSimpleMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_3, 0.0f, 1.f, 0.0f);
	njCnkSetSimpleMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_4, 0.0f, 0.0f, 1.f);
}

/*
     ライトのＯＮ／ＯＦＦ
*/
void SimpleLightOnOff(void)
{
	/* チャンクライトのＯＮ・ＯＦＦ設定               *
	 * （ＯＮ：１、ＯＦＦ：０）                       *
	 *  NJD_CNK_SIMPLE_MULTILIGHT_ALLフラグを使用する *
	 *  ことで設定されたすべてのライトを切り換えれます*/
 
	if (!_num) {
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_ALL, 1);
	}
	if (_num==1) {
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_ALL, 0);
	} else {
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_1, _lt_1[_num]);
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_2, _lt_2[_num]);
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_3, _lt_3[_num]);
		njCnkSetSimpleMultiLightSwitch(NJD_CNK_SIMPLE_MULTILIGHT_4, _lt_4[_num]);
	}
}

/*
	処理本体
*/
void ExecCnkSimpleMultiLight(void)
{
	njPushMatrix(NULL);
	{
		NJS_POINT3 p1,p2,p3;
		static int a1,a2,a3;

		a1 += 0x100;
		a2 += 0x200;
		a3 += 0x300;

		p1.x = RANGE * njCos(a1);
		p1.y = RANGE * njSin(a1);
		p1.z = -12.f;

		p2.x = RANGE * njCos(a2);
		p2.y = 0.f;
		p2.z = -12.f + RANGE * njSin(a2);

		p3.x = 0.f;
		p3.y = RANGE * njSin(a3);
		p3.z = -12.f + RANGE * njCos(a3);

		njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_2, p1.x, p1.y, p1.z);
		njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_3, p2.x, p2.y, p2.z);
		njCnkSetSimpleMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_4, p3.x, p3.y, p3.z);
		
		/* チャンクライトの方向・位置の反映              *
		 * この関数は、基本的にビュー・カメラの設定後に  *
		 * 設定してください。                            *
		 * これより前に設定されたすべてのライトの位置・  *
		 * 方向を反映させます。                          */
	 
		njCnkSetSimpleMultiLightMatrices();
	}

	njTranslate( NULL, 0.f, 0.f, -12.f );
	njRotateXYZ( NULL, xx,yy,zz );
	njCnkSimpleMultiDrawObject( OBJ );
	njPopMatrix(1);
	njPrintC(NJM_LOCATION(2,3), "Simple Multi");
}

/*----------------------------------------------
    njCnkEasyMulti のライト設定と処理本体
 --------------------------------------------- */
void InitCnkEasyMultiLight(void)
{
	/* チャンクライトの個数の設定              *
	 * （内部で光源設定キューを持たないので    *
	 *   個数とライトの種類は以下のように      *
	 *   関連します。                     ）   *
	 *                                         *
	 * 1:平行光源１                            *
	 * 2:平行光源１+点光源２                   *
	 * 3:平行光源１+点光源２+点光源３          *
	 * 4:平行光源１+点光源２+点光源３+点光源４ *
	 *                                         */

	njCnkSetEasyMultiLight(4);

	/* チャンクライトの平行光源（一番目の光源）方向設定 */
	njCnkSetEasyMultiLightVector(0.f, 0.f, -1.f);

	/* チャンクライトの点光源位置設定 */
	/* ２番目の光源（点光源）の設定 */
	njCnkSetEasyMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_2, 0.f, 0.f, -12.f);
	/* ３番目の光源（点光源）の設定 */
	njCnkSetEasyMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_3, 0.f, 0.f, -12.f);
	/* ４番目の光源（点光源）の設定 */
	njCnkSetEasyMultiLightPoint(NJD_CNK_SIMPLE_MULTILIGHT_4, 0.f, 0.f, -12.f);

	/* チャンクライトの点光源範囲（距離）設定 */
	njCnkSetEasyMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_2, 6.f, 40.f);
	njCnkSetEasyMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_3, 6.f, 40.f);
	njCnkSetEasyMultiLightRange(NJD_CNK_SIMPLE_MULTILIGHT_4, 6.f, 40.f);

	/* チャンクライトのアンビエント色設定 */
	njCnkSetSimpleMultiAmbient(0.1f, 0.1f, 0.1f);

	/* チャンクライトの光源色設定 */
	njCnkSetEasyMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_1, 0.5f, 0.5f, 0.5f);
	njCnkSetEasyMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_2, 1.f, 0.0f, 0.0f);
	njCnkSetEasyMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_3, 0.0f, 1.f, 0.0f);
	njCnkSetEasyMultiLightColor(NJD_CNK_SIMPLE_MULTILIGHT_4, 0.0f, 0.0f, 1.f);
}

/*
     ライトのＯＮ／ＯＦＦ
*/
void EasyLightOnOff(void)
{
	/* チャンクライトのＯＮ・ＯＦＦ設定               *
	 * （ＯＮ：１、ＯＦＦ：０）                       *
	 *  NJD_CNK_SIMPLE_MULTILIGHT_ALLフラグを使用する *
	 *  ことで設定されたすべてのライトを切り換えれます*/
 
	if (!_num) {
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_ALL, 1);
	}
	if (_num==1) {
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_ALL, 0);
	} else {
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_1, _lt_1[_num]);
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_2, _lt_2[_num]);
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_3, _lt_3[_num]);
		njCnkSetEasyMultiLightSwitch(NJD_CNK_EASY_MULTILIGHT_4, _lt_4[_num]);
	}
}

/*
	処理本体
*/
void ExecCnkEasyMultiLight(void)
{
	njPushMatrix(NULL);
	{
		NJS_POINT3 p1,p2,p3;
		static int a1,a2,a3;
		
		a1 += 0x100;
		a2 += 0x200;
		a3 += 0x300;
		
		p1.x = RANGE * njCos(a1);
		p1.y = RANGE * njSin(a1);
		p1.z = -12.f;
	
		p2.x = RANGE * njCos(a2);
		p2.y = 0.f;
		p2.z = -12.f + RANGE * njSin(a2);
	
		p3.x = 0.f;
		p3.y = RANGE * njSin(a3);
		p3.z = -12.f + RANGE * njCos(a3);
	
		njCnkSetEasyMultiLightPoint(NJD_CNK_EASY_MULTILIGHT_2, p1.x, p1.y, p1.z);
		njCnkSetEasyMultiLightPoint(NJD_CNK_EASY_MULTILIGHT_3, p2.x, p2.y, p2.z);
		njCnkSetEasyMultiLightPoint(NJD_CNK_EASY_MULTILIGHT_4, p3.x, p3.y, p3.z);
	
		/* チャンクライトの方向・位置の反映              *
		 * この関数は、基本的にビュー・カメラの設定後に  *
		 * 設定してください。                            *
		 * これより前に設定されたすべてのライトの位置・  *
		 * 方向を反映させます。                          */

		njCnkSetEasyMultiLightMatrices();
	}
	njTranslate( NULL, 0.f, 0.f, -12.f );
	njRotateXYZ( NULL, xx,yy,zz );
	njCnkEasyMultiDrawObject( OBJ );
	njPopMatrix(1);
	njPrintC(NJM_LOCATION(2,3), "Easy Multi");
}
