//------------------------------------------------------------
// $Id: calcRayTrSRG.cc,v 1.1.1.1 1999/11/25 06:26:09 yamauchi Exp $
//------------------------------------------------------------
//	calcRayTrSRG.cc
//	calculation of Secondary Ray Generation unit for ray tracing 
//	1996/8/8
//	(C) 1995-1998 Copyright YAMAUCHI Hitoshi 山内 斉
//
//	ray-tracing 法と radiosity 法では反射レイの生成に違いあり．
//	二次レイ発生 for RayTracing
//------------------------------------------------------------
#include "calcRayTrSRGgetdir.h"

//------------------------------------------------------------
// 2次 ray-tracing ray 生成
//     	輝度計算は IC で済んでいる
//	(論文に書いている設計とは違い，このことは IC->SRG の接続を示し
//	 ている．論文では反射毎に FrameBuffer へと送信しているが，実装
//	 には ray 消滅の際にしか FrameBuffer への更新が起こらない．
//		(see mpi2doc_implementation)
//------------------------------------------------------------
// YorN PEClass::
// newSecondaryRayTracingRays(Ray *pRay, const materialClass *pMat, 
// 			   objBaseClass * pHitObj)
// {
//     YorN isGenerateRay = NO;	// レイは発生したか? 
// 
//     // この ray は反射・屈折回数を越えているか
//     if(pRay->getReflectedNum() >= this->mViewData.getMaxRayRefNum())
//     {				// 越えている。ray は発生しない。
// 	assert(isGenerateRay == NO);
// 	return(isGenerateRay);
//     }
//     
//     //------------------------------------------------------------
//     // 反射 2 次 ray-tracing ray を new し、PE の処理キューへ登録
//     //------------------------------------------------------------
//     Ray *pNewHanshaRay = 
// 	newReflectionRayTracingRays(pRay, pMat, 
// 				    this->mViewData.getMinRayRefCoeffNorm(),
// 				    pHitObj);
//     if(pNewHanshaRay != NULL)	// ray を発生した。
//     {
// 	pNewHanshaRay->setColor(pRay->getColor()); // IC で計算した輝度を託す
// 	this->setRayPtrToThisPE(pNewHanshaRay);		   
// 	isGenerateRay = YES;
// 	// 反射 ray-tracing レイ生成を数えるのならばここ Hint TOKUNAGA
//     }
// 
//     //------------------------------------------------------------
//     // 透過 2 次 refraction レイを new し、PE の処理キューへ登録
//     //------------------------------------------------------------
//     Ray *pNewToukaRay = 
//     	newRefractionRayTracingRays(pRay, pMat, 
// 				    this->mViewData.getMinRayRefCoeffNorm(),
// 				    pHitObj);
//     if(pNewToukaRay != NULL)
//     {
// 	// ray を発生した。既に輝度は託されているのか?
// 	if(isGenerateRay == NO)
// 	{			// 託されていない。輝度を託す
// 	    pNewToukaRay->setColor(pRay->getColor());	    
// 	}
// 	this->setRayPtrToThisPE(pNewToukaRay);
// 	isGenerateRay = YES;
// 	// 屈折 ray-tracing ray 生成を数えるのならばここ Hint TOKUNAGA
//     }
//     return(isGenerateRay);
// }

//------------------------------------------------------------
// 2次 ray-tracing ray 生成
//     	輝度計算は IC で済んでいる
//	(論文に書いている設計とは違い，このことは IC->SRG の接続を示し
//	 ている．論文では反射毎に FrameBuffer へと送信しているが，実装
//	 には ray 消滅の際にしか FrameBuffer への更新が起こらない．
//		(see mpi2doc_implementation)
//------------------------------------------------------------
// 分散無しの二次光放射
//------------------------------
YorN PEClass::
secondRayGenWithoutDistribute(Ray *pRay, const materialClass *pMat, 
			      objBaseClass * pHitObj)
{
    YorN isGenerateRay = NO;	// レイは発生したか? 

    // この ray は反射・屈折回数を越えているか
    if(pRay->getReflectedNum() >= this->mViewData.getMaxRayRefNum())
    {				// 越えている。ray は発生しない。
	assert(isGenerateRay == NO);
	return(isGenerateRay);
    }
    
    //------------------------------------------------------------
    // 反射 2 次 ray-tracing ray を new し、PE の処理キューへ登録
    //------------------------------------------------------------
    Vector3 reflectedRayDir, reflectedRayCoeff;
    YorN isGenReflectRay = 
	getReflectionRayDirRayTrace(pRay, pMat, 
				    this->mViewData.getMinRayRefCoeffNorm(),
				    pHitObj, 
				    &reflectedRayDir,
				    &reflectedRayCoeff);
    if(isGenReflectRay == YES)	// ray を発生した。
    {
	// 反射レイ作成 newRay! 
	// このコンストラクタで作成したレイは一度当った物体には交差しない 
	Ray *pNewHanshaRay = Ray::newForReflectionRayTracing(pRay, 
							     reflectedRayDir, 
							     reflectedRayCoeff,
							     pHitObj);
	
	pNewHanshaRay->setColor(pRay->getColor()); // IC で計算した輝度を託す
	this->setRayPtrToThisPE(pNewHanshaRay);		   
	isGenerateRay = YES;
	// 反射 ray-tracing レイ生成を数えるのならばここ Hint TOKUNAGA
    }

    //------------------------------------------------------------
    // 透過 2 次 refraction レイを new し、PE の処理キューへ登録
    //------------------------------------------------------------
    Vector3 refractedRayDir, refractedRayCoeff;    
    YorN isGenRefractedRay = 
	getRefractionRayDirRayTrace(pRay, pMat, 
				    this->mViewData.getMinRayRefCoeffNorm(),
				    pHitObj, 
				    &refractedRayDir,
				    &refractedRayCoeff);
    if(isGenRefractedRay == YES)
    {
	Ray *pNewToukaRay = Ray::newForReflectionRayTracing(pRay, 
							    refractedRayDir, 
							    refractedRayCoeff,
							    pHitObj);
	pNewToukaRay->changeSide(); // 屈折の場合には物体の中と外の状態を変換
	
	// ray を発生した。既に輝度は託されているのか?
	if(isGenerateRay == NO)
	{			// 託されていない。輝度を託す
	    pNewToukaRay->setColor(pRay->getColor());	    
	}
	this->setRayPtrToThisPE(pNewToukaRay);
	isGenerateRay = YES;
	// 屈折 ray-tracing ray 生成を数えるのならばここ Hint TOKUNAGA
    }
    return(isGenerateRay);
}

// 二次光放射で分散するかしないか
YorN PEClass::
newSecondaryRayTracingRays(Ray *pRay, const materialClass *pMat, 
			   objBaseClass * pHitObj)
{
    if(pMat->getFrustumHalfTopRad() != 0.0)
    {
	// 分散二次光放射 
 	return(this->secondRayGenWithDistrbute(pRay, pMat, pHitObj));
    }
    else
    {
	// 二次光放射の分散放射無し
	return(this->secondRayGenWithoutDistribute(pRay, pMat, pHitObj));
    }
}
