//------------------------------------------------------------
// $Id: hemicube.h,v 1.1.1.1 1999/11/25 06:26:09 yamauchi Exp $
//------------------------------------------------------------
//
//	Hemi cube class for (Mπ)^2 System 
//	First Ray Generation Unit has Hemi cube.
//	(This is only use radiosity mode)
//      (C) 1993-1998 Copyright By YAMAUCHI Hitoshi
// 	平成５年１０月２０日(水)(start implementation)
//	平成６年６月１８日(土) 	(simulation implementation finished)
//	平成８年９月６日(金)	(start SP2 mpi2 implementation)
//
// シミュレーション用の HC は一本づつレイの発生をしては停止することが
// できなくてはいけなかったが、今回はその必要がない。そのためいくつか
// の簡単化が可能である。たとえば Master Hemi-Cube を内蔵してしまうこ
// となど。 
//
// 今回の実装では、
// 	1.HemiCube をある hemres で作成し、patch の Normal Vector を用
// 	  いて初期化する。 
// 	2.その後は、patch の Normal vector を与えて次の初期化を行うこ
//	  とで再利用する。
//------------------------------------------------------------
#ifndef _hemicube_h
#define _hemicube_h 1

#include <assert.h>

#include "IntVec3.h"
#include "Vector3.h"
#include "mpi2.h"

// class declaration
class objBaseClass;
class Ray;

enum hemicube_plane_type_e {
    WALL_CEILING_e,		// 天井(変だが、名前を統一するために)
    WALL_XPLUS_e,		// 壁
    WALL_XMINUS_e,    
    WALL_YPLUS_e,
    WALL_YMINUS_e,
    HEMICUBE_PLANE_MAX_e	// xlC のおかげで , を消去せねばならん
};

//------------------------------------------------------------------- 
// Hemi-Cube (この Hemi-cube は各パッチのために動的に作成、削除される)
//------------------------------------------------------------------- 
class hemiCubeClass {
private:
    // don't make hemicube as {default|copy} constructor and substitute
    hemiCubeClass(void);
    hemiCubeClass(const hemiCubeClass& rhs);
    const hemiCubeClass &operator=(const hemiCubeClass &rhs);

protected:
    // set in getMemory()
    double   ***mpFFval;	// FormFacterの値 壁のものは1つで良い
    Vector3  ***mpFFEOrgPos;	// それぞれのエレメントの回転前の位置
    Vector3  ***mpFFEPos;	// 回転後のそれぞれのエレメントの位置

    // hemi cube info
    double   mElemArea;		// それぞれのエレメントの面積
    int	     mHemres;		// Hemi-cube resolution

    IntVec3  mPEID;		// 担当 PE ID
    
    // raiation patch informatio
    Vector3  mPatchNormal; 	// 放射パッチの放射方向法線
    Vector3  mGravityCenter;	// 放射パッチの重心位置
    double   mPatchArea;	// 放射パッチの面積
    IntVec3  mSpcpos;		// 放射パッチの存在する副空間指標
    objBaseClass *mpPatch;	// 放射パッチ
    Vector3  mLockingNotYetRad;	// 未放射値のロック用

protected:
    int getHemres(void)	const 	{ return(this->mHemres);	}

protected:
    void getMemory(void);	// メモリ取得
    void setFormFactor(void);	// Master Hemi-Cube の位置と FF 設定
    void rotateHC(const Vector3& patchNorm); // HemiCubeのオイラー変換

    // generation rays using by Hemi-Cube
    void distributeRadiation(Ray *pRayArea[]);
    void continuousRadiation(Ray *pRayArea[]);
    inline Ray *genOneRay(int plane, int height, int width);
    // エラーチェック
    YorN isHemiCubePosXYZRight(//const hemicube_plane_type_e plane, 
			       const int plane,
			       const int height, const int width) const;

public:
    hemiCubeClass(int hemres, const IntVec3& PEID);
    ~hemiCubeClass(void);    

    // 発生 ray 数 = 壁 * 4 + 天井(壁の大きさは天井の半分) = 3 * 天井 
    int getGenRayNum(void) const { return(3 * this->mHemres * this->mHemres); }

    // 一気に一つの HemiCube 分の ray を発生させ，pRetRays にポインタ
    // をコピーして(ポインタの先は new されている)返す． 
    // pRetRays の領域は呼び出し側が確保して渡すこと．
    void genRays(objBaseClass *const apPatch, 	   // 放射パッチ
		 const YorN isDistributedRadiation,// ray の発生方式
		 Ray *pRetRays[]);		   // 作成されるrayのptr配列
#ifdef TEST_HEMICUBE
    void test();
#endif
};

#endif				// (#ifndef _hemicube_h)

