/*#### 	$Id: m_view.h,v 1.2 2004/02/12 22:54:41 tong Exp $
 |###   --- View - 射影制御 ---
 |##
 |#
 *
 */
/*
 *$Log: m_view.h,v $
 *Revision 1.2  2004/02/12 22:54:41  tong
 *new header files to compile cpak, flash, rtc stuff
 *
 *Revision 1.9  2000-09-18 20:21:29+09  otsuki
 **** empty log message ***
 *
 *Revision 1.8  2000/07/10 02:18:55  hayakawa
 **** empty log message ***
 *
 *Revision 1.7  2000-06-08 17:48:12+09  matutani
 *near/farセットマクロ追加
 *
 */

#ifndef __VIEW_H_
#define __VIEW_H_

#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif

//#include "u64basic.h" /* 2000/9/18 otsuki */
#include "graph.h"
#include "m_olib.h"

#define _VIEW_KEYCODE    'VIEW'

typedef struct zelda_view_struct {
#ifdef _ODEBUG /* 小川さんデバック */
    int  keycode;
#endif
    GRAPH  *graph;

    irect   sc;                         /* for veiwport(シザリングの上下右左) */
    float  fovy, near, far, scale;      /* for perspective */
    xyz_t  eye, center, up;             /* for lookat */
    Vp      vp;				/* ビューポートの構造体 */
    Mtx     projection,  viewing;	/* プロジェクション・ビューマトリックス */
    Mtx     *pprojection, *pviewing;	/* プロジェクション・ビューマトリックスポインタ */
    
    /* 水中のカメラ効果を生むためのデータ */
    struct  {
	xyz_t  t_rotate, t_scale;	/* rotate, scale が目指す値 */
	float  f;			/* t_rotate,t_scale と rotate,scale の差を分割する変数 */
	xyz_t  rotate, scale;		/* 実際にprojectionマトリックスに影響させる値 */
    }       stretch;
    u16     normal;			/*gSPPerspNormalizeコマンドと一緒に使用するための数値 */

    int    setflag;	/* 何のデータを新しくセットしたかのマスクフラグ(VIEW_DO_*を使う) */
//    int    againflag;	/* プレイヤー移動後のカメラ処理フラグ（主観カメラ用:現在必要なし） */
} View;

/*###
 |##  マクロ
 |#
 */

/*
** マトリックスを作成＆ロードするか？ マスクフラグ */
#define VIEW_DO_LOOKAT      (0x01)   /* lookat行列用設定(guLookAtの要素をセット)	(1 << 0) */
#define VIEW_DO_SCISSOR     (0x02)   /* シザリングボックス用設定(gDPSetScissorの要素をセット) (1 << 1) */
#define VIEW_DO_PERSPECTIVE (0x04)   /* 透視射影変換設定(guPerspectiveの要素をセット)	(1 << 2) */
#define VIEW_DO_ORTHO       (0x08)   /* 正射影用変換設定(guOrthoの要素をセット)         (1 << 3) */
#define VIEW_DO_AUTO        (0x0f)   /* 必要なものだけ勝手に作成＆ロード(上４つ全て) */

#define VIEW_DO_PERSALL     (0x7f)   /* すべて作成＆ロード透視射影用(0x8000は立ってない) */
#define VIEW_DO_ORTHOALL    (0xbf)   /* すべて作成＆ロード正射影用(0x4000は立ってない) */

/*
** 汎用レジスタ設定 - BASE ADDRESS (200) */
#ifdef VIEW_USE_OREG
/* keep 70 - 95 */
#define VIEW_SCTOP       (int)OREG(70)    /* シザリングボックス 上 */
#define VIEW_SCBOTTOM    (int)OREG(71)    /* シザリングボックス 下 */
#define VIEW_SCLEFT      (int)OREG(72)    /* シザリングボックス 左 */
#define VIEW_SCRIGHT     (int)OREG(73)    /* シザリングボックス 右 */
#define VIEW_FOVY      ((float)OREG(74)/100.0f)    /* 透視射影Ｙ方向の視野角 */
#define VIEW_NEAR      (float)OREG(75)    /* 透視射影ニアークリップ */
#define VIEW_FAR       (float)OREG(76)    /* 透視射影ファークリップ */
#define VIEW_SCALE     (float)OREG(77)    /* 透視射影スケーリング値 */

#define VIEW_EYE_X     (float)OREG(80)    /* LookAt() 視点 X */
#define VIEW_EYE_Y     (float)OREG(81)    /* LookAt() 視点 Y */
#define VIEW_EYE_Z     (float)OREG(82)    /* LookAt() 視点 Z */
#define VIEW_CENTER_X  (float)OREG(83)    /* LookAt() 注目点 X */
#define VIEW_CENTER_Y  (float)OREG(84)    /* LookAt() 注目点 Y */
#define VIEW_CENTER_Z  (float)OREG(85)    /* LookAt() 注目点 Z */
#define VIEW_UP_X      (float)OREG(86)    /* LookAt() 上方点 X */
#define VIEW_UP_Y      (float)OREG(87)    /* LookAt() 上方点 Y */
#define VIEW_UP_Z      (float)OREG(88)    /* LookAt() 上方点 Z */

#define INIT_VIEW_OREG() {           \
             OREG(70) = 0;                  /* VIEW_SCTOP */ \
             OREG(71) = (short)SCREEN_HT;   /* VIEW_SCBOTTOM */ \
             OREG(72) = 0;                  /* VIEW_SCLEFT */ \
             OREG(73) = (short)SCREEN_WD;   /* VIEW_SCRIGHT */ \
             OREG(74) = 20*100;             /* VIEW_FOVY */ \
             OREG(75) = 200;                 /* VIEW_NEAR */ \
             OREG(76) = 1600;              /* VIEW_FAR */ \
             OREG(77) = 1;                  /* VIEW_SCALE */ \
             OREG(80) = 0;                  /* VIEW_EYE_X */ \
             OREG(81) = 0;                  /* VIEW_EYE_Y */ \
             OREG(82) = -1;                 /* VIEW_EYE_Z */ \
             OREG(83) = 0;                  /* VIEW_CENTER_X */ \
             OREG(84) = 0;                  /* VIEW_CENTER_Y */ \
             OREG(85) = 0;                  /* VIEW_CENTER_Z */ \
             OREG(86) = 0;                  /* VIEW_UP_X */ \
             OREG(87) = 1;                  /* VIEW_UP_Y */ \
             OREG(88) = 0;                  /* VIEW_UP_Z */ \
	}

#else

#define VIEW_SCTOP     (0)                /* シザリングボックス 上 */
#define VIEW_SCBOTTOM  SCREEN_HT          /* シザリングボックス 下 */
#define VIEW_SCLEFT    (0)                /* シザリングボックス 左 */
#define VIEW_SCRIGHT   SCREEN_WD          /* シザリングボックス 右 */
#define VIEW_FOVY      (20.0f)            /* 透視射影Ｙ方向の視野角 */
#define VIEW_NEAR      (200.0f)            /* 透視射影ニアークリップ */
#define VIEW_FAR       (1600.0f)         /* 透視射影ファークリップ */
#define VIEW_SCALE     (1.0f)             /* 透視射影スケーリング値 */

#define VIEW_EYE_X     (0.0f)             /* LookAt() 視点 X */
#define VIEW_EYE_Y     (0.0f)             /* LookAt() 視点 Y */
#define VIEW_EYE_Z     (-1.0f)            /* LookAt() 視点 Z */
#define VIEW_CENTER_X  (0.0f)             /* LookAt() 注目点 X */
#define VIEW_CENTER_Y  (0.0f)             /* LookAt() 注目点 Y */
#define VIEW_CENTER_Z  (0.0f)             /* LookAt() 注目点 Z */
#define VIEW_UP_X      (0.0f)             /* LookAt() 上方点 X */
#define VIEW_UP_Y      (1.0f)             /* LookAt() 上方点 Y */
#define VIEW_UP_Z      (0.0f)             /* LookAt() 上方点 Z */

#define INIT_VIEW_OREG() 
#endif

/*###
 |##  関数仮宣言
 |#
 */

#ifdef __VIEW_C_
#define _LOCAL
_LOCAL  void set_viewport(Vp *vp, irect *sc);
#define _GLOBAL
#else /* __VIEW_C_ */
#define _GLOBAL    extern
#endif /* __VIEW_C_ */

_GLOBAL View  *createView(GRAPH *graph);
_GLOBAL void  destroyView(View *obj);
_GLOBAL void  initView(View *obj, GRAPH *graph);
_GLOBAL void  setPerspectiveView(View *obj, float fovy, float near, float far);
_GLOBAL void  getPerspectiveView(View *obj, float *fovy, float *near, float *far);
_GLOBAL void  setScaleView(View *obj, float scale);
_GLOBAL void  getScaleView(View *obj, float *scale);
#if 0	/* 2000 1/17 komatu */
_GLOBAL void  setOrthoView(View *, float fovy, float near, float far);
_GLOBAL void  getOrthoView(View *, float *fovy, float *near, float *far);
#endif
_GLOBAL void  setScissorView(View *obj, irect *vp);
_GLOBAL void  getScissorView(View *obj, irect *vp);
_GLOBAL void  setLookAtView(View *obj, xyz_t *eye, xyz_t *center, xyz_t *up);
_GLOBAL void  getLookAtView(View *obj, xyz_t *eye, xyz_t *center, xyz_t *up);
_GLOBAL int   showView(View *obj, int do_mask);
_GLOBAL int   showPerspectiveView(View *obj);
_GLOBAL int   showOrthoView(View *obj);
_GLOBAL int   showOverLayView(View *obj);
_GLOBAL int   showPerspectiveOverLayView(View *obj);
_GLOBAL int   showView1(View *obj, int do_mask, Gfx **glistpp);
_GLOBAL int   showOrthoView1(View *obj, Gfx **glistpp);
_GLOBAL int   showViewAgain(View *obj);

_GLOBAL int   stretchViewInit(View *obj);

#define getEyeView(vv)         (&((vv)->eye))
#define getCenterView(vv)      (&((vv)->center))
#define getUpView(vv)          (&((vv)->up))

#define setFovyView(vv, ff)    ((vv)->fovy = (ff))
#define setNearView(vv, nn) ((vv)->near = (nn))
#define setFarView(vv, ff) ((vv)->far = (ff))

/*###
 |##  標準, オリジナルコンパチブル
 |#
 */

#define View_ct(vv, gg)     initView(vv, gg)
#define View_dt(vv)         (vv)

/* VIEW_DO_AUTO:必要なものだけ勝手に作成＆ロード */
#define view_init(vv, gg)   initView(vv, gg)
#define view_setup_view(vv) showView(vv, VIEW_DO_AUTO)
#define view_setup_again(vv) showViewAgain(vv)
#define view_setup_view_ovl1(vv, glistpp) showOrthoView1(vv, glistpp)
#define view_setup_view1(vv, glistpp) showView1(vv, VIEW_DO_AUTO, glistpp)
#define view_set_ScissorBox(vv, ll, tt, rr, bb) { \
             irect __rr;                          \
	     __rr.top = tt;  __rr.bottom = bb;    \
	     __rr.left = ll;  __rr.right = rr;    \
            setScissorView(vv, &__rr);             \
	}
#if 0	/* 1999 1/17 komatu */
#define view_set_Perspective(vv, yy, nn, ff, ss) \
            setPerspectiveView(vv, yy, nn, ff)
#endif		
#define view_set_LookAtXYZ(vv, ex, ey, ez, cx, cy, cz, ux, uy, uz) { \
            xyz_t  __ee, __cc, __uu;                           \
	    __ee.x = ex;  __ee.y = ey;  __ee.z = ez;           \
	    __cc.x = cx;  __cc.y = cy;  __cc.z = cz;           \
	    __uu.x = ux;  __uu.y = uy;  __uu.z = uz;           \
	    setLookAtView(vv, &__ee, &__cc, &__uu);               \
	}
#define view_set_LookAt(vv, ee, cc, uu)    setLookAtView(vv, ee, cc, uu)

#define view_get_eye(vv)         getEyeView(vv)
#define view_get_center(vv)      getCenterView(vv)
#define view_get_up(vv)          getUpView(vv)

#undef _GLOBAL
#undef _LOCAL

#if DEBUG
	    extern int
debug_eyecheck(float eyex, float eyey, float eyez);
#else
#define debug_eyecheck(eyex, eyey, eyez) (void)0 /* nop */
#endif
	    
#ifdef _LANGUAGE_C_PLUS_PLUS
} /* extern "C" */
#endif

#endif /* __VIEW_H_ */
