/*	
 *	cliprend.h
 *
 *	描画ライブラリを定義します。
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2002 Naoyuki Sawa
 *
 *	* Wed Feb 13 06:00:00 JST 2002 Naoyuki Sawa
 *	- 作成開始。
 */
#ifndef __CLIP_REND_H__
#define __CLIP_REND_H__

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

#ifdef PIECE
typedef PBMP_FILEHEADER	TEXTUREHEADER;
typedef PIECE_BMP	TEXTURE;
#else /*PIECE*/
typedef struct _TEXTUREHEADER {		/* PBMP_FILEHEADERにバイナリ互換 */
	unsigned long head;		/* + 0,4 シグネチャ'PBMP'        */
	unsigned long fsize;		/* + 4,4 ファイルサイズ          */
	unsigned char bpp;		/* + 8,1 ビット深度              */
	unsigned char mask;		/* + 9,1 マスク深度              */
	short w;			/* +10,2 幅                      */
	short h;			/* +12,2 高さ                    */
					/* +14,2 パディング              */
	unsigned long buf_size;		/* +16,4 データサイズ            */
					/* =20                           */
} TEXTUREHEADER;
typedef struct _TEXTURE {		/* PIECE_BMPにバイナリ互換 */
	TEXTUREHEADER header;		/* + 0,20 ヘッダ           */
	unsigned char* buf;		/* +20, 4 ビットデータ     */
	unsigned char* mask;		/* +24, 4 マスクデータ     */
					/* =28                     */
} TEXTURE;
#endif /*PIECE*/

/* SURFACE構造体は、PIECE_VRAM構造体の上位バイナリ互換です。
 * PIECE_VRAMへのポインタを要求する関数に、SURFACEへのポインタを渡せます。
 */
typedef struct _SURFACE {		/* 描画先サーフェイス   */
	short w;			/* + 0,2 幅             */
	short h;			/* + 2,2 高さ           */
	unsigned char* vbuff;		/* + 4,4 カラーバッファ */
	/* ↑ここまでPIECE_VRAM互換。↓これ以降は拡張部分です。 */
	unsigned char* zbuff;		/* + 8,4 Ｚバッファ     */
					/* =12                  */
} SURFACE;

typedef struct _VERTEX {		/* ポリゴン頂点          */
	short x;			/* +0,2 水平ピクセル座標 */
	short y;			/* +2,2 垂直ピクセル座標 */
	unsigned char s;		/* +4,1 水平テクセル座標 */
	unsigned char t;		/* +5,1 垂直テクセル座標 */
} VERTEX;				/* =6                    */

typedef struct _TCOORD {		/* テクスチャ座標 */
	unsigned char s;		/* +0,1 水平座標  */
	unsigned char t;		/* +1,1 垂直座標  */
					/* =2             */
} TCOORD;

typedef struct _FACEVERTEX {		/* フェイス頂点                  */
	unsigned char iv;		/* +0,1 頂点座標インデクス       */
	unsigned char ic;		/* +1,1 テクスチャ座標インデクス */
} FACEVERTEX;

typedef struct _FACE {			/* フェイス                      */
	unsigned char nfv;		/* +0,1    頂点の数              */
	unsigned char c;		/* +1,1    カラー                */
	/*FACEVERTEX fv[nfv];*/		/* +2,2nfv フェイス頂点リスト    */
					/* =2+2nfv                       */
} FACE;

typedef struct _MESH {			/* メッシュ                             */
	unsigned char nv;		/* +0,1            頂点座標の数         */
	unsigned char nc;		/* +1,1            テクスチャ座標の数   */
	unsigned char nf;		/* +2,1            フェイスの数         */
	unsigned char reserved;		/* +3,1            (予約)               */
	/*VECTOR v[nv];*/		/* +4,12nv         頂点座標リスト       */
	/*TCOORD c[nc];*/		/* +4+12nv,2nc     テクスチャ座標リスト */
	/*FACE f[nf];*/			/* +4+12nv+2nc,(?) フェイスリスト       */
					/* =4+12nv+2nc+(?)                      */
} MESH;

/* テクスチャ構造体を初期化します。
 * [in]
 *	texture		初期化するテクスチャ構造体。
 *	data		PBMPファイルイメージの先頭アドレス。
 * [out]
 *	戻り値		引数textureの値をそのまま返します。
 * [note]
 *	* TEXTURE構造体はPIECE_BMP構造体と同じ(typedef)なので、
 *	  この関数はPIECE_BMP構造体の初期化にも利用できます。
 */
TEXTURE* texture_init(TEXTURE* texture, const void* data);

/* サーフェイスをクリアします。
 * [in]
 *	surface		サーフェイス構造体。
 *	color		背景色。
 * [note]
 *	* カラーバッファ(vbuff)がNULLでなければ、背景色でクリアします。
 *	* Ｚバッファ(zbuff)がNULLでなければ、0xFFでクリアします。
 */
void surface_clear(SURFACE* surface, int color);

/* ピクセルカラーを取得します。
 * [in]
 *	surface		サーフェイス構造体。
 *	x,y		ピクセル座標。
 * [out]
 *	戻り値		ピクセルカラー。
 *			サーフェイス外のピクセル座標なら、-1を返します。
 * [note]
 *	* この関数は、render_point()と対を成します。
 */
int surface_point(SURFACE* surface, int x, int y);

/*****************************************************************************
 *	RENDER
 *****************************************************************************/

#define RENDER_CONTEXT_STACK_SIZE	16			/* コンテキストスタックサイズ */

typedef struct _RENDERCONTEXT {
	MATRIX matrix;						/* 変換行列               */
	TEXTURE* texture;					/* テクスチャ(NULL:なし)  */
} RENDERCONTEXT;

typedef struct _RENDER {
	SURFACE* surface;					/* 描画サーフェイス                 */
	short left, top, right, bottom;				/* ビューポート矩形(グリッド座標系) */
	float front, back;					/* クリッピング距離                 */
	RENDERCONTEXT* context;					/* コンテキストスタックトップ       */
	RENDERCONTEXT context_stack[RENDER_CONTEXT_STACK_SIZE];	/* コンテキストスタック             */
} RENDER;

/* フレームを初期化します。
 * [in]
 *	render		レンダラーへのポインタ。
 *	surface		描画サーフェイス。
 *	x,y		ビューポート原点。
 *	width,height	ビューポートサイズ。
 *	front,back	クリッピング距離。
 *	fovy		垂直視野角度。
 * [note]
 *	* width,heightに0を指定すると、サーフェイスの幅、高さと同じと見なします。
 *	  従って、サーフェイス全体をビューポート領域として指定するには、
 *	  x,y,width,heightを0,0,0,0と指定するのが簡単です。
 *	* ３Ｄ描画を行わない場合は、front,back,fovyの指定は適当な値で構いません。
 *	  front,back.fovyを0,0,0と指定するのが簡単です。
 *	* この関数は、サーフェイスのクリアを行いません。
 *	  カラーバッファおよびＺバッファのクリアは、呼び出し側で行ってください。
 */
void render_init(RENDER* render, SURFACE* surface, int x, int y, int width, int height, float front, float back, float fovy);

/* コンテキストを退避します。
 * [in]
 *	render		レンダラーへのポインタ。
 */
void render_save(RENDER* render);

/* コンテキストを復元します。
 * [in]
 *	render		レンダラーへのポインタ。
 */
void render_restore(RENDER* render);

/* 点を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		点の座標。
 *	color		カラー。
 * [note]
 *	* この関数は、surface_point()と対を成します。
 */
void render_point(RENDER* render, int x, int y, int color);

/* 同じ色の範囲を塗りつぶします。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		塗りつぶし開始点。
 *	color		カラー。
 * [out]
 *	戻り値		塗ったピクセルの数。
 * [note]
 *	* (x0,y0)の色が続く範囲を、colorで塗りつぶします。
 *	  (x0,y0)の色が既にcolorと同じなら、何もしません。
 *	* (x0,y0)がビューポート外なら、何もしません。
 */
int render_paint(RENDER* render, int x0, int y0, int color);

/* 線分を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		始点座標。
 *	x1,y1		終点座標。
 *	color		カラー。
 * [note]
 *	* 多角形を描くために、連続して呼び出されることを想定しています。
 *	  よって、終点ピクセル(x1,y1)は描きません。
 *	* ただし実装の都合上、クリッピングされた側の終点も描かないので、
 *	  画面内から画面外への線分を描こうとすると、画面端に1ピクセルの
 *	  すき間ができてしまいます。要修正。
 *	* Fri Mar  8 07:00:00 JST 2002 Naoyuki Sawa
 *	  修正しました。
 */
void render_line(RENDER* render, int x0, int y0, int x1, int y1, int color);

/* 破線を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x0,y0		始点座標。
 *	x1,y1		終点座標。
 *	i_pat		破線パターンの開始インデックス。
 *	pat		破線パターン。(カラー値の配列。値4以上は透明)
 *	n_pat		破線パターンの要素数。(1以上)
 * [out]
 *	戻り値		破線パターンの終了インデックス＋１。
 *			連続した線分を描くときは、この戻り値を次のrender_dashes()呼び出しのi_patに渡せば、
 *			破線パターンがうまくつながります。
 * [note]
 *	* n_patに0を指定すると、ゼロ除算エラーが発生します。
 *	* i_pat>=n_patでも構いません。適切な繰り返し位置から開始します。
 */
int render_dashes(RENDER* render, int x0, int y0, int x1, int y1, unsigned i_pat, const unsigned char* pat, unsigned n_pat);

/* 矩形を描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		左上原点座標。
 *	w,h		矩形のサイズ。
 *	color		カラー。
 */
void render_rectangle(RENDER* render, int x, int y, int w, int h, int color);

/* 矩形を塗りつぶします。
 * [in]
 *	render		レンダラーへのポインタ。
 *	x,y		左上原点座標。
 *	w,h		矩形のサイズ。
 *	color		カラー。
 */
void render_rectangle_fill(RENDER* render, int x, int y, int w, int h, int color);

/* ポリゴンを描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	vertices	頂点リスト。
 *	n_vertices	頂点の数。
 *	color		カラー。
 */
void render_polygon(RENDER* render, const VERTEX* vertices, int n_vertices, int color);

/* メッシュを描きます。
 * [in]
 *	render		レンダラーへのポインタ。
 *	mesh		描画されるメッシュ。
 */
void render_mesh(RENDER* render, const MESH* mesh);

#endif /*__CLIP_REND_H__*/
