/*	
 *	cliprenf.h
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2008 Naoyuki Sawa
 *
 *	* Sun Aug 10 01:12:48 JST 2008 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sun Aug 17 22:24:29 JST 2008 Naoyuki Sawa
 *	- vecf→vec3f、matf→mat3f、vecx→vec3x、matx→mat3xに名前変更しました。
 *	  全置換で変換したので、本日以前のコメントなどもすべて名前変更されています。
 */
#ifndef __CLIP_RENF_H__
#define __CLIP_RENF_H__

/*****************************************************************************
 *	RENDF
 *****************************************************************************/

typedef struct _RENDF_SAVE {
	mat3f matrix;		/* + 0,48 */
	TEXTURE* texture;	/* +48, 4 */
} RENDF_SAVE;			/* =52    */
#define RENDF_SAVE_MAX	8	/* 調整可 */

typedef struct _RENDF {
	//{{RENDF_SAVE
	mat3f matrix;		/* + 0,48 */
	TEXTURE* texture;	/* +48, 4 */
	//}}RENDF_SAVE
	SURFACE* surface;	/* +52, 4 */
	float front;		/* +56, 4 */
	float back;		/* +60, 4 */
	float left;		/* +64, 4 */
	float right;		/* +68, 4 */
	float top;		/* +72, 4 */
	float bottom;		/* +76, 4 */
	//
	/*{{View Frustum Culling*/
	mat3f vfc_matrix;	/* (ビューポート変換×透視変換)の逆行列 */
	float vfc_width_2;	/* 前クリッピング面の幅の半分 */
	float vfc_height_2;	/* 前クリッピング面の高さの半分 */
	/*}}View Frustum Culling*/
	//
	int save_cnt;
	RENDF_SAVE save[RENDF_SAVE_MAX];
} RENDF;

/*---------------------------------------------------------------------------*/

void rendf_init(RENDF* r, SURFACE* surface, int x, int y, int width, int height, float front, float back, float fovy);
void rendf_save(RENDF* r);
void rendf_restore(RENDF* r);
void rendf_mesh(RENDF* r, const MESH* mesh); /* MESHの頂点座標はvec3f[]とする */
void rendf_wire(RENDF* r, const WIRE* wire, int color); /* WIREの頂点座標はvec3f[]とする */
void rendf_line(RENDF* r, const vec3f* v0, const vec3f* v1, int color);

/*---------------------------------------------------------------------------*
 *	視錐台カリング
 *---------------------------------------------------------------------------*/

/* 境界球を使って、視錐台カリング(VFC: View Frustum Culling)のテストを行います。
 * [in]
 *	r		RENDFへのポインタ。
 *	bounding_sphere	境界球の半径。
 * [out]
 *	戻り値		境界球が視錐台の完全に内に有るか、一部を含む場合、0以外の値を返します。
 *			境界球が視錐台の完全に外に有る場合、0を返します。
 * [note]
 *	* <使用例>
 *		float bounding_sphere = meshf_bounding_sphere(mesh);	// 境界球の半径を求めておく
 *			...
 *		mat3f_...(&rendf.matrix, ...);				// 移動、回転など
 *		if(rendf_vfc_sphere(&rendf, bounding_sphere)) {		// 境界球を視錐台の中に見えているならば
 *			rendf_mesh(&rendf, mesh);			// 実際に描画を行います
 *		}
 *	* 変換行列の平行移動成分だけを使って、境界球の中心座標を判断し、視錐台カリングを行います。
 *	  rendf_vfc_sphere()は、変換行列のスケーリング成分を考慮しません。
 *	  拡大、縮小の変換を行っていた場合、rendf_vfc_sphere()の戻り値は、正しい結果となりません。
 *	  拡大、縮小の変換を行っていた場合、呼び出し側において、境界球の半径を乗ずる必要が有ります。
 *	* 全てのオブジェクトに対して視錐台カリングを行うわけではないので、あえて高速化していません。
 *	  視錐台カリングの中で毎回、(ビューポート変換×透視変換)の逆行列を掛けて(モデルビュー変換)を取得するよりも、
 *	  (ビューポート変換×透視変換)と(モデルビュー変換)を分けて保持しておく方が、視錐台カリングは高速になります。
 *	  しかし、描画だけを行うならば(ビューポート変換×透視変換×モデルビュー変換)を合成して保持する方が高速です。
 *	  視錐台カリングは補助的に用い、視錐台カリング無しに描画を行う方が多いと考えて、描画の高速性を重視しました。
 */
int rendf_vfc_sphere(RENDF* r, float bounding_sphere);

/* メッシュモデルの境界球の半径を求めます。
 * [in]
 *	mesh		メッシュモデルへのポインタ。
 * [out]
 *	戻り値		境界球の半径。
 */
float meshf_bounding_sphere(const MESH* mesh);

/* ワイヤーフレームモデルの境界球の半径を求めます。
 * [in]
 *	mesh		ワイヤーフレームモデルへのポインタ。
 * [out]
 *	戻り値		境界球の半径。
 */
float wiref_bounding_sphere(const WIRE* wire);

/*---------------------------------------------------------------------------*/

#endif /*__CLIP_RENF_H__*/
