
#ifndef HEMISPHERE_SCRATCHPAD_H
#define HEMISPHERE_SCRATCHPAD_H


#include <math.h>

#include "color.h"
#include "ScratchPad.h"

class HemisphereScratchPad
{
private:
  int           maxr;              // Maximum recursion level 
  int           maxnumsub;         // Maximum number of subdivisions
  int           maxnumpar;         // Maximum number of parallels
  int           maxnumspps;        // Maximum number of points on hemisphere

  int           curr;              // Current recursion level
  int           curnumsub;         // Current number of subdivisions
  int           curnumpar;         // Current number of parallels
  int           curnumspps;        // Current number of points on hemisphere


  float         h,h2,h2inv;
  float         chgsz;
  double        convtheta;
  ScratchPad    **spps;            // Corresponding scratch pad 

  // Reconstruct outgoing radiance
  HemisphereScratchPad* evaluateOutgoing();


public:

  // Constructs a new HemisphereScratchPad.
  // IN  : the recursion level for positionnal and directionnal subdivision.
  // OUT : a pointer to a hemisphere scratchpad (NULL if memory allocation failed).
  // POST: the hemisphere scratchpad is ready to be used (the content is random).
  HemisphereScratchPad(int rpos,int rdir);

 
  // Destroy a HemisphereScratchPad.
  // POST: the memory is released.
  ~HemisphereScratchPad();


  // Configure the HemisphereScratchpad for the construction of a new SurfWav4D.
  // IN:   p is a pointer to the patch we want to reconstruct the illumination onto.
  //       grdsz is the grid size for positionnal information reconstruction
  //	   rdir is the direction subdivision recursion level.
  // POST: you are allowed to call addImpact.
  void configure(PATCH* p,const float grdsz,const int rdir);
  

  // Change the reconstruction kernel size.
  // IN:   hp is the new size of the reconstruction kernel (position).
  //       hd is the new size of the reconstruction kernel (direction).
  // OUT:  The new size will be taken into account for subsequent impacts.
  void setKernelSize(const float hp,const float hd);
  

  // Add an impact for the construction.
  // IN:   pos    is the position of the impact in parameter space of the patch.
  //       dir    is the direction of the impact.
  //       weight is the weight of the reconstruction kernel (w>0).
  // POST: The impact has been taken into account.
  void addImpact(const VEC2D &pos,const VEC2D &dir,const COLOR &weight);


  // Construct a SurfWav4D from the HemisphereScratchPad contents.
  // IN:   The expected compression ratio.
  // OUT:  A pointer to a SurfWav4D. (NULL if memory allocation failed).
  NonDiffuseSurface* constructNonDiffuseCompressedSurface(const float t);

  
  // Construct a non diffuse SurfDec.
  NonDiffuseSurface* constructNonDiffuseDecimatedSurface(const float t);



  // ====================================== STATIC UTILITIES FUNCTIONS =========================
  
  // Compute the number of points resulting a recusive subdivision.
  // IN:   The recursion level r
  // PRE:  r >= 0
  // OUT:  The number of points
  static int numberOfPoints(int r);

  // Compute the index of the point closest to the phi, theta coordinates on the hemisphere
  // IN:   recursion level r, phi and theta coordinates
  // PRE:  r>=0, 0.0 <= phi <= 2.0*PI, 0.0 <= theta <= PI/2.0
  // OUT:  the index number of the point that is the closest to the input coordinates in a
  //       hemisphere subdivided recursively r times.
  static int indexDirection(int r,double phi,double theta);

  // Convert spherical coordinates to unit vector.
  static void to3d(const float p,const float t,VECTOR& v);


  // Add an impact on a scratchpad for the construction of a view dependent image.
  // IN:   pos    is the position of the impact in parameter space of the patch.
  //       dir    is the direction of the impact.
  //       weight is the weight of the reconstruction kernel (w>0).
  // POST: The impact has been taken into account.
  static void addImpact(ScratchPad *spp,const int vr,const float vh,const VEC2D &pos,const VEC2D &dir,const COLOR &weight);


};



#endif






