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

  タイトル ： クリッピング領域を変える
  編集履歴 ： 98-04-28 製作開始
              98-06-19 SET5対応
              99-04-05 appends the English comments
************************************************************/

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

void main(void)
{
#ifdef __GNUC__
	shinobi_workaround();
#endif
    njSetBorderColor( 0x00000000 );
    njUserInit();
    while (njUserMain() == NJD_USER_CONTINUE) {
        njWaitVSync();
    }
    njUserExit();
}

#define MAX_MATRIX_DEPTH 10
#define MAX_VERTEXES 2048

#define CUBE_NUM 3                      /* 並べる立方体の数（たてｘよこ）*/
                                        /* the number of cubes           */
#define AREA_CHANGE_CYCLE 1440          /* クリッピングエリアを表示する周期   */
                                        /* the cycle of display clipping area */
#define ROTATE_ANGLE NJM_DEG_ANG(45.0F) /* 立方体を表示する角度          */
                                        /* the angle of display the cube */
#define AREA_CHANGE_ANGLE NJM_DEG_ANG(0.5F) /* クリッピングエリアを変更する速度 */
                                            /* the speed of the changing clipping area */
extern NJS_OBJECT object_cube_root[];

static NJS_MATRIX *Matrix;
static NJS_VERTEX_BUF *VertexBuffer;

static NJS_VIEW View;
static NJS_LIGHT DirLight;

/*----------------------------------------------------------------------
           初期化
           initialization
----------------------------------------------------------------------*/
void njUserInit(void)
{
    /* システムの初期化 */
    /* Initializes the Dreamcast H/W and readies the SEGA library */
    sbInitSystem(NJD_RESOLUTION_640x240_NTSCNI, NJD_FRAMEBUFFER_MODE_RGB565, 1);

    /* ＮＴＳＣ画面の縦横比を補正 */
	/* corrects the screen aspect ratio */
    njSetAspect(1.0F, 0.45F);

    /* メモリの割り当て */
    /* allocates the memory */
    Matrix = syMalloc(sizeof(NJS_MATRIX) * MAX_MATRIX_DEPTH);
    VertexBuffer = syMalloc(sizeof(NJS_VERTEX_BUF) * MAX_VERTEXES);

    /* 背景色の設定 */
	/* sets background color */
    njSetBackColor(ARGB(0, 0, 0, 0), ARGB(0, 0, 0, 0), ARGB(0, 0, 0, 0));

    /* 頂点格納バッファの確保 */
    /* allocates the buffers for registration of vertex data */
    njInitVertexBuffer(MAX_VERTEXES * 64 / 4, 0, MAX_VERTEXES * 64 / 4, 0, 0);
	njInitPrint( NULL, 0, NJD_TEXFMT_ARGB_1555 );

    /* マトリクススタックの初期化 */
	/* initializes the matrix stack */
    njInitMatrix(Matrix, MAX_MATRIX_DEPTH, 1);

    /* 3Dシステムの初期化 */
    /* initializes 3D system  */
    njInit3D(VertexBuffer, MAX_VERTEXES);

    /* 光源の初期化 */
    /* initializes the light source */
    njCreateLight(&DirLight, NJD_DIR_LIGHT);
	njSetLightColor(&DirLight, 0.7F, 0.7F, 0.7F);

    /* ビューの初期化 */
    /* initializes the user-defined view */
    njInitView(&View);

    /* ビューの設定 */
    /* sets the user-defined view as the current view */
    njSetView(&View);

	/* 文字色の設定 */
	/* sets the color of debug printing */
	njPrintColor(0xFFC0C0C0);
}

/*----------------------------------------------------------------------
         メイン
         main
----------------------------------------------------------------------*/
Sint32 njUserMain(void)
{
    /* 初期変数の設定 */
    /* initializes the valiables */

    int xPos;	/* 立方体を並べるためのループ用カウンタ(縦) */
				/* the cube counter (vertical) */

    int zPos;	/* 立方体を並べるためのループ用のカウンタ（横）*/
    			/* the cube counter (horizontal) */

    static int counter = 0;/* クリッピングエリア表示時間調整用カウンタ */
    static Angle areaAng = NJM_DEG_ANG(0.0F);/* 回転角度用変数 */

	static PDS_PERIPHERAL *key;/* ボタン入力 */
	                           /* periheral information */

	static Bool pause = FALSE;/* ポーズがかかっているかどうか */
	                          /* pause(TRUE) or not(FALSE)    */

	/* ポーズの判定 */
	/* checks the pause */
	key = pdGetPeripheral(PDD_PORT_A0);

	if (key->press & PDD_DGT_ST) {
	    if (pause == FALSE) {
		    pause = TRUE;
		} else {
		    pause = FALSE;
		}
	}

    /* クリッピングエリアの変更 */
    /* changes the clipping area */
	if (pause == FALSE) {
	    counter++;
	}
    if (counter == AREA_CHANGE_CYCLE) {
        counter = 0;/* カウンターのリセット */
                    /* resets the counter   */
    }
    if (counter < AREA_CHANGE_CYCLE / 2) { /* 手前を動かす    */
                                           /* moves the front */
        njClipZ(-10.0F - (njCos(areaAng) + 1) * 15.0F, -40.0F);
    } else {                               /* 奥を動かす      */
                                           /* moves the back  */
        njClipZ(-10.0F , -40.0F + (njCos(areaAng) + 1) * 15.0F);
    }
    njSetView(&View);

    /* サンプル名の表示 */
    /* prints the sample program name */
    njPrintC(NJM_LOCATION(23, 4), "Ninja Sample CLIP AREA CHANGE");
	if (pause == TRUE) {
	    njPrintC(NJM_LOCATION(30, 5), "PAUSE");
	}

    /* マトリクススタックのクリア */
    /* clears the matrix stack */
    njClearMatrix();

    /* 平行移動 */
    njTranslate(NULL, 0.0F, 0.0F, -5.0F);

    /* 立方体を並べる */
    /* draws the cubes */
    for (zPos = 0; zPos < CUBE_NUM; zPos++){
        for (xPos = 0; xPos < CUBE_NUM; xPos++){
            njPushMatrix(NULL);
            njTranslate(NULL, (xPos - 1) * -5.0F , zPos * 3.0F - 4.0F,
                        zPos * -10.0F - 10.0F);

            /* X,Y,Z 軸の順番に回転 */
            /* roteate the object   */
            njRotateXYZ(NULL, ROTATE_ANGLE, ROTATE_ANGLE, ROTATE_ANGLE);

            /* オブジェクトの描画 */
            /* draws the object */
            njDrawObject(object_cube_root);
            njPopMatrix(1);
        };
    };
	if (pause == FALSE) {
	    areaAng += AREA_CHANGE_ANGLE;
	}
    return NJD_USER_CONTINUE;
}

/*----------------------------------------------------------------------
         終了処理
         exit
----------------------------------------------------------------------*/
void njUserExit(void)
{
	njExitPrint();

    /* メモリの開放 */
	/* frees the memory area */
    syFree(Matrix);
    syFree(VertexBuffer);

    /* システムの終了 */
    /* exits the system    */
    sbExitSystem();
}
