//------------------------------------------------------------
// $Id: frustumSRG.h,v 1.1.1.1 1999/11/25 06:26:09 yamauchi Exp $
//------------------------------------------------------------
// distribute secondary ray generation	
//	光の発生時に錐体を用いた分散レイを発生させる．
//
//	Original file is prbDist.h by TOKUNAGA Mayumi
//	Changed to frustumSRG.h by YAMAUCHI Hitoshi
//
//	Copyright (C) 1998  TOKUNAGA Mayumi  徳永 真由美
//	Copyright (C) 1998  YAMAUCHI Hitoshi 山内 斉
//
// 錐体の底面は正方形を仮定する．
//
// 各パラメータを指定するファイル
//	・底面の解像度 	: view file 
// 	・視角        	: material data 
//---------------------------------------------------------
#ifndef _frustumSRG_h
#define _frustumSRG_h 1

#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include <assert.h>
#include "Vector3.h"

class frustumSRGClass {
private:
    // frustum はけしてコピーされないため， copy constructor 関係を利
    // 用できなくする． 
    frustumSRGClass(const frustumSRGClass &rhs);
    const frustumSRGClass& operator=(const frustumSRGClass &rhs);    

protected:
    int     mBaseSquareEdgeResol;	// 底辺の解像度
    int     mNumberOfTotalSamples;	// サンプリング数 = 底辺^2 = pixel 数
    Vector3 *mpPixelBasePos;	// 底面の変換前の方向 : 回転前に初期化
    Vector3 *mpPixelSamplePos;	// 変換後の方向 : 反射レイの方向による
    double  *mpWeight;		// frustum の底辺の各 pixel に対する重み

protected:
    // このクラスの出力メッセージの一括管理 (多国語対応というわけでは
    // ないが) この方法が良いかどうかはわからない．多国語のソフトウェ
    // アについてまず調べるのが良いだろう．
    //  enum frustumSRGClass_message {
    // 	frustumSRG_SumpleSquareResolutionIsSmall_e,
    // 	frustumSRG_IllegalFrustumParamInViewfile_e,
    // 	frustumSRG_
    // 	frustumSRG_
    //  };
    //  void outMessage(int messageType);

public:
    frustumSRGClass(void);
    ~frustumSRGClass(void);
    //------------------------------
    // frustum のメモリ取得
    //   @param resolBaseSquareEdge frustum の底辺の一辺の解像度 
    void init(int resolBaseSquareEdge);

    //------------------------------
    // 回転前の (0, 0, 1.0) 方向を向く frustum の底辺位置初期化
    //   @param frustumTopHalfRad  	 : 錐の頂角/2 (radian)
    //   @param pow_cos_n		 : Phone の cos n 乗則の n 
    // これを呼ぶ前に必ず init が必要
    void setBaseSamplePosition(double halfFrustumTopRad, double pow_cos_n);

    //------------------------------ 
    // rotate base 位置から光線の放射方向に光を放射する． 
    //   @param secondRayDir 光線の放射方向
    void rotate(const Vector3& secondRayDir);

    //------------------------------ 
    // frustum の頂点の角度を変更し，回転させるため
    // setBaseSamplePosition + rotate 用 : 上記2つを分離させる必要があ
    // るかは検討する．同じ material の場合には回転だけが良いかと思っ
    // たが，そうもいかないようだ．
    void setTopAngleRadandRotate(double halfFrustumTopRad, 
				 double pow_cos_n,
				 const Vector3& secondRayDir)
    {
	this->setBaseSamplePosition(halfFrustumTopRad, pow_cos_n);
	this->rotate(secondRayDir);
    }

    // 全サンプル数を返す
    int getTotalSampleNum(void)
    {
	return(this->mNumberOfTotalSamples);
    }

    // i 番目のサンプル位置を返す
    Vector3 getSamplePixelPos(int i) const
    {
	assert((0 <= i) && (i < this->mNumberOfTotalSamples));
	return(this->mpPixelSamplePos[i]);
    }

    // i 番目のサンプルの重みを返す
    double getWeight(int i)  const
    {
	assert((0 <= i) && (i < this->mNumberOfTotalSamples));
	return(this->mpWeight[i]);
    }
};

#endif
