
#include "dest.h"
#include "phong.h"
#include "scene.h"
#include "Common.h"
#include "SamplingStrategy.h"



double CosNThetaBRDFSamplingStrategy::BounceRay(RAY &rin,HITREC &hin,RAY &rout,HITREC &hout)
{
  DENSITY_ESTIMATION_DATA_PTR thisData;
  BSDF                        *thisBsdf;
  PHONG_BRDF                  *phong;
  COORDSYS                    reflCoord;
  VECTOR                      reflDir;
  double                      xi_1,xi_2,pdf;
  
  // Access density estimation data more easily
  thisData  = (DENSITY_ESTIMATION_DATA_PTR) hin.patch->radiance_data;
  thisBsdf  = hin.patch->surface->material->bsdf;

  // Halton sampling
  xi_1 = drand48();
  xi_2 = drand48();

  // Initiate cos theta n sampling
  phong = (PHONG_BRDF *) thisBsdf->data;
  reflDir = IdealReflectedDirection(&rin.dir,&hin.normal);
  VectorCoordSys(&reflDir,&reflCoord);

  // Initiate reflection ray
  rout.pos = hin.point;
  rout.dir = SampleHemisphereCosNTheta(&reflCoord, (int)phong->Ns,
				       xi_1, xi_2, &pdf);

  // Send ray
  RayCastingFunction(hin.patch,&rout,hout);

  // Set probability
  return (VECTORDOTPRODUCT(hin.patch->normal,rout.dir)<0.0) ? 0.0 : pdf;
}



double CosNThetaBRDFSamplingStrategy::EvalRay(RAY &rin,HITREC &hin,RAY &rout,HITREC &,const double cosTheta)
{ 
  BSDF                        *thisBsdf;
  PHONG_BRDF                  *phong;
  VECTOR                      reflDir;
  double                      tmpCos;
  int                         ns;

  thisBsdf = hin.patch->surface->material->bsdf;
  phong    = (PHONG_BRDF *) thisBsdf->data;
  ns       = (int)phong->Ns;
  reflDir  = IdealReflectedDirection(&rin.dir,&hin.normal);  
  tmpCos   = VECTORDOTPRODUCT(reflDir,rout.dir);

  return (cosTheta<0.0) ? 0.0 : (ns + 1.0) * pow(tmpCos,ns) * M_1_2PI;
}

