//------------------------------------------------------------
// $Id: rayTrFRGUnit.h,v 1.2 2000/05/19 20:35:51 yamauchi Exp $
//------------------------------------------------------------
//	calcRayTrFRG.h
//
//	calculation of First Ray Generation unit for ray tracing 
//	ray-tracing 法において ray を一気に発生させるのではなく、
//	いくつか発生させてから計算・通信を行うためどこまで ray を発生
//	したかなどを保持する必要がある。そのためのクラスである。 
//
//	(C) Copyright 1996--1998 YAMAUCHI Hitoshi 山内 斉
//
//	初期レイ発生
//------------------------------------------------------------
#ifndef _calcRayTrFRG_h
#define _calcRayTrFRG_h 1

#include "viewdata.h"
#include "SpaceParam.h"

class Ray;
class scrPtrIF;

//------------------------------------------------------------
// First Ray Generation Unit 
//------------------------------------------------------------
class rayTrFRGUnitClass {
private:
    rayTrFRGUnitClass(const rayTrFRGUnitClass& rhs);
    const rayTrFRGUnitClass operator=(const rayTrFRGUnitClass& rhs);
    
protected:
    int     mScanMethodOnScreen; // first ray generation method
    
    IntVec3 mPEid;
    Vector3 mViewPoint;		
    scrPtrIF *mpScreenPtr;	// screen pointer: screen の pixel 位置発生器
    
    Vector3 mScreenLeftUpFromVp; // 画面左上方を指す vector
    Vector3 mDeltaXscr;		 // screen における 1 pixel 分のベクトル X
    Vector3 mDeltaYscr;		 // 					 Y
    int     mMaxRaysInAPixel;	 // 1 pixel に発っする ray の本数
    int     mGenRayParPixel;	 // 現在の pixel に対して何本 ray を発っしたか
    YorN    mCanGenerateNextRay; // 次の ray は発生可能か
 
    // [空間情報]
    Vector3 mDefSpcMin;		// [空間情報] 定義空間
    Vector3 mDefSpcMax;
    Vector3 mPartVolMinPos;	// Partition volume の最小値
    double  mSubDivNum;		// 分割空間数
    double  mPartVolOneSize;	// 副空間の一辺の長さ
      
    // 
    IntVec3 mVpSpcPos;		 // 視点の存在空間位置(視点が定義空間内の時)
    YorN    mIsVpInDefSpc;	 // 視点が定義空間内部にあるか
    int     mNumOfTotalGenRays;	 // 現在までの総 ray 発生数
    double  mDistRaysFactor;	 // 各rayの1つの画素への寄与の割合 分散 
    // 				 // raytrace が 4本/pixel ならば 1/4 

    // screen 位置
    int	    mScrX;
    int	    mScrY;

protected:
    // screen pointer(分散レイなどをどのように発生するかの Strategy) 
    // の初期化とそれに伴う member の初期化．たとえば，mVpSpcPos など
    // は視点が定義空間の内部か外部かを示すがこれは初期光分散を行うか
    // どうかに深くかかわっているのでここで初期化する．
    void initForScreenPointer(int scrSizeX, int scrSizeY,  
			      int myRank,   int totalPEnum);
    void initForAllScanMethod(int scrSizeX, int scrSizeY);
    void initForScanlineScanMethod(int scrSizeX, int scrSizeY,  
				   int myRank,   int totalPEnum);
    void initForDistributedScanMethod(int scrSizeX, int scrSizeY,
				      int myRank,   int totalPEnum);

    void moveOnScreen(void);	// 次の pixel へ移動する

    // 副空間の指標を位置から得る
    IntVec3 getSpcposOfaPoint(const Vector3& pos) const; 

    // view vector generator
    inline Vector3 genViewVec(void) const;
 
    // ray generator
    Ray *newOneRayVpInDefineSpc(void) const; // 視点が定義空間内部にある
    Ray *newOneRayVpOutOfDefSpc(void) const; // 視点が定義空間外部にある
	
public:
    rayTrFRGUnitClass(void);
    //------------------------------
    // init 
    //	@param rayGenerationMethod : 分散 ray 手法(Allscan や ScanlineScan)
    //  @param viewDat	: 視点の位置，視線方向などの視点情報
    //  @param spcDat	: 空間情報
    //  @param PEid	: この初期光発生ユニットの属する PE の ID
    //  @param totalPEnum : システムの全 PE 数 (初期光分散時に必要)
    //  @param myRank 	: 自分の rank (0 からはじまる)
    void init(int	     	     rayGenerationMethod,
	      const ViewDataClass&   viewDat, 
 	      const SpaceParam&      spcDat, 
 	      const IntVec3& 	     PEid,
	      int   	 	     totalPEnum,
	      int 		     myRank);
    
    YorN canGenerateNextRay(void) const { return(this->mCanGenerateNextRay); }
    Ray *newNextRay(void);
    int       getTotalGenRays(void) const { return(this->mNumOfTotalGenRays); }
    int  getScanMethodOnScreen(void) const{ return(this->mScanMethodOnScreen);}
};

#endif				// #ifndef _calcRayTrFRG_h
