// ===================================================================
// $Id: db_brdf.h,v 1.6 2003/10/30 16:36:35 havran Exp $
//
// phong.h
//     Header file for CSurfacePhong class.
//
// Class: CSurfacePhong, CSurfacePhongPhysical,
//        CSurfacePhongPhysicalDR (DR means deterministic reflection)
//
// Licence and usage conditions in November 2003:
// This file can be used and modified only with written permission of
// Vlastimil Havran, Pohodli 27, 57001 Litomysl, the Czech Republic.
// This library is granted to be used by Polina Kondratieva within
// her MPI HIWI job working on BRDFLIB library. The usage condition
// may change in the next version of the library. At the moment,
// the library development is supported by Max-Planck-Institut for
// Informatik, Stuhlsatzenhausweg 85, 66123 Saarbruecken Germany
// See WWW: http://www.mpi-sb.mpg.de
// REPLACEMENT_STRING
//
// Initial coding by Vlastimil Havran, 1999; Jaroslav Krivanek (Nov 2000)
//
// Given to BRDFLIB project for the Polina Kondratieva's
// HIWI JOB assignment in November 2003.

#ifndef __DB_BRDF_H__
#define __DB_BRDF_H__

// BRDFLIB library
#include "configh.h"
#include "surface.h"
#include "functions.h"
#include "hemigon.h"
#include "../../ann_1.1.2/include/ANN/ANN.h"
#include "../../ann_1.1.2/include/ANN/ANNperf.h"
/*
#include "../ann_0.2/include/ANN/ANN.h"
#include "../ann_0.2/include/ANN/ANNperf.h"
*/

__BEGIN_BRDFLIB_HEADER

typedef vector<double> T_vec_d;
typedef vector<CValues> T_vec_cv;
typedef vector<S_polarCoords> T_vec_polars;
typedef vector<T_vec_d> T_vec_vec_d;
typedef vector<T_vec_cv> T_vec_vec_cv;
typedef vector<CHemisphereGonio> T_vec_hemigons;

// Forward-declare classes
class CHitPointInfo;
class CMatrix4;
class CRay;
class CTexture;

// ------------------------------------------------------------------------
// These classes are adjusted for Dana's BRDF database. It reads BRDF values
// in RGB format and average BRDF values from the specified files and make
// data interpolation to get some number (equal to the number of prescribed
// incoming directions) of hemispherical grids with corresponding BRDF
// values in the nodes.
//
// The number of incoming directions depends of anisotropic or isotropic
// properties of the surface material.
// * For isotropic case the number of grids is equal to the number of vertical
//   angles (BRDF does not depend on horizontal angle Phi).
// * For anisotropic case the number of grids is equal to the number of
//   nodes in the grid.
// ------------------------------------------------------------------------
/*****************************************************************************
*                                                                            *
*               DBDana_BRDFAnisotropic - Anisotropic case                    *
*                                                                            *
******************************************************************************/
class CDBDana_BRDFAnisotropic:
  public CSurface
{
public:
  // constructor
  CDBDana_BRDFAnisotropic():
    CSurface(EE_NONE),
    _db_color(0),
    _db_s_tree(NULL),
    _v_count(0),
    _h_count(0),
    _v_angles(NULL),
    _h_angles(NULL),
    _gridAngles(0),
    _brdf_i(0),
    _BRDF_avg_val(0),
    _BRDF_rgb_val(0),
    _hemigons(0),
    _validHemigons(false)
  {}

  virtual ~CDBDana_BRDFAnisotropic()
  {
    if(_v_angles != NULL)
      delete [] _v_angles;

    if(_h_angles != NULL)
      delete [] _h_angles;

    if(_db_s_tree != NULL)
      delete _db_s_tree;
  };

  // this is deep copy
  virtual CSurface *Dup() const;
  virtual CDBDana_BRDFAnisotropic* CreateNewObject() const
  { return new CDBDana_BRDFAnisotropic; }

  // Set and Get public functions
  //----------------------------------------------------------------------
  inline void SetDB_color(CTexture *texture)
  {
    _db_color = texture;
    if (texture)
      _setSupportedType(EE_REFLECTED_DIFFUSE);
    else
      _unsetSupportedType(EE_REFLECTED_DIFFUSE);
  }

  inline CTexture* GetDB_color()      { return _db_color; }

  inline int GetVCount()              { return _v_count; }

  inline int GetHCount()              { return _h_count; }

  inline ANNkd_tree *GetDBSearchTree()  { return _db_s_tree; }

  inline double* GetVAngles()         { return _v_angles; }

  inline double* GetHAngles()         { return _h_angles; }

  inline int GetHemigonsSize()
  {
    if(_validHemigons)
      return (int)_hemigons.size();
    return 0;
  }

  inline void GetHemigon(int &rindex, CHemisphereGonio &hg)
  {
    if((_validHemigons && ((int)_hemigons.size() > 0)) &&
       rindex < (int)_hemigons.size())
    {
       hg = _hemigons[rindex];
    }
  }

  inline T_dataDB GetBRDFData()
  {
    int dim = 4;  // Anisotropic case

    if((int)_brdf_i.size() <= 0)
    {
      cout << "Currently this array is empty. Please, specify the data\n";
      T_dataDB dummy_data;
      S_entryDB dummy;
      CValues blackc(0,0,0);
      ANNpoint d_pt;
      d_pt = annAllocPt(dim);

      for(int i = 0; i < dim; i++) d_pt[i] = 0.0;

      dummy.p = d_pt;
      dummy.brdf = blackc;
      dummy.avg = 0.0;
      dummy_data = T_dataDB(0, dummy);

      return dummy_data;
    }
    return _brdf_i;
  }

  inline T_vec_d GetBRDF_avg_val_ind(int &rindex)
  {
    if(((int)_BRDF_avg_val.size() <= 0)||(rindex > (int)_BRDF_avg_val.size()))
    {
      cout << "Currently _BRDF_avg_val array is empty.\n";
      cout << "Please, specify the data\n";
      T_vec_d dummy_data(0, 0);

      return dummy_data;
    }
    return _BRDF_avg_val[rindex];
  }

  inline T_vec_vec_d GetBRDF_avg_val()
  {
    if((int)_BRDF_avg_val.size() <= 0)
    {
      cout << "Currently _BRDF_avg_val[index] array is empty.\n";
      cout << "Please, specify the data\n";
      T_vec_vec_d dummy_data(0, T_vec_d(0, 0));

      return dummy_data;
    }
    return _BRDF_avg_val;
  }

  inline T_vec_cv GetBRDF_rgb_val_ind(int &rindex)
  {
    if(((int)_BRDF_rgb_val.size() <= 0)||(rindex > (int)_BRDF_rgb_val.size()))
    {
      cout << "Currently _BRDF_rgb_val[index] array is empty.\n";
      cout << "Please, specify the data\n";
      T_vec_cv dummy_data(0, CValues(0,0,0));

      return dummy_data;
    }
    return _BRDF_rgb_val[rindex];
  }

  inline T_vec_vec_cv GetBRDF_rgb_val()
  {
    if((int)_BRDF_rgb_val.size() <= 0)
    {
      cout << "Currently _BRDF_rgb_val array is empty.\n";
      cout << "Please, specify the data\n";
      T_vec_vec_cv dummy_data(0, T_vec_cv(0, CValues(0,0,0)));

      return dummy_data;
    }
    return _BRDF_rgb_val;
  }

  virtual EType GetType() const { return EE_DBBRDF;}

  virtual bool
  GetAlbedo(CValues &albedo, const CHitPointInfo &hitInfo,
	    EDistributionType   distType=EE_ALL) const;

  virtual bool
  GetAlbedoMax(CValues &albedo,
	       const CHitPointInfo &hitInfo,
	       EDistributionType   distType=EE_ALL) const;
  //----------------------------------------------------------------------

  // Different variants of data processing. See source file for explanation
  //----------------------------------------------------------------------
  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count,
			double *v_angles, double *h_angles);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, double *v_angles,
			double *h_angles, T_vec_polars &grid_angles);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count,
			int &h_count, T_dataDB &brdf_i, ANNkd_tree *tree);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, double *v_angles,
			double *h_angles, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count, int &h_count,
			double *v_angles, double *h_angles,
			T_dataDB &brdf_i, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count, int &h_count,
			double *v_angles, double *h_angles,
			T_vec_polars &grid_angles, T_dataDB &brdf_i,
			ANNkd_tree *tree);
  //----------------------------------------------------------------------


  virtual float GetAverageDiffuseness(void) const;

  virtual float GetDiffuseness(const CHitPointInfo &hitinfo,
			       EDistributionType distType=EE_ALL) const;

  virtual bool GetTransparency(CValues &transparency,
			       const CHitPointInfo &hitinfo) const;

  virtual bool GetDefaultColor(CValues &defaultColor,
			       const CHitPointInfo &hitInfo) const;

  virtual void Describe(ostream &app, int ind) const;

  virtual int
  SpawnDeterministicRays(CContributionArray  &carray,
		         const CHitPointInfo &hitInfo,
       		         EDistributionType   distType = EE_ALL) const
  {return 0;}

  virtual int
  SpawnStochasticRays(CContributionArray  &carray,
		      const CHitPointInfo &hitInfo,
		      CSamplingInfo       &samplingInfo,
      		      EDistributionType   distType = EE_ALL) const;

  virtual bool
  EvaluateBSDF(CValues             &brdf,
	       const CHitPointInfo &hitInfo,
	       const CVector3D     &out,
	       EDistributionType   distType=EE_ALL) const;

  // Print members of this class:
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void PrintDB_SearchTree(ostream &app) const;
  virtual void PrintVAngles(ostream &app) const;
  virtual void PrintHAngles(ostream &app) const;
  virtual void PrintGridAngles(ostream &app) const;
  virtual void PrintBRDF_DB(ostream &app) const;
  virtual void PrintBRDF_avg_val(ostream &app) const;
  virtual void PrintBRDF_rgb_val(ostream &app) const;

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

private:
  CDBDana_BRDFAnisotropic& operator=(const CDBDana_BRDFAnisotropic&);
  CDBDana_BRDFAnisotropic(const CDBDana_BRDFAnisotropic&);

protected:
  CTexture *_db_color;	      // RGB_color computed by the interpolation
                              // of RGB_values of samples taken from DB
  ANNkd_tree *_db_s_tree;     // data structure for search (for 4D-coordinates)

  int _v_count;
  int _h_count;
  double *_v_angles;
  double *_h_angles;
  T_vec_polars _gridAngles;   // nodes of the grid with 2D-polar coords

  T_dataDB _brdf_i;           // coordinates and BRDF values from the DB
  T_vec_vec_d  _BRDF_avg_val; // vector of grids with average BRDF values
  T_vec_vec_cv _BRDF_rgb_val; // vector of grids with R, G, B BRDF values
  T_vec_hemigons  _hemigons;

  bool _validHemigons;


protected:
  // the auxiliary storage of random variable
  typedef vector<double> rnd_array;
  static double aux_rnd;
  static rnd_array diffuse_rnd;
  static rnd_array specular_rnd;
  static rnd_array refraction_rnd;

  void SetAuxRnd(double rnd_num, float min, float max) const {
    assert( (rnd_num >= min) && (rnd_num <= max));
    aux_rnd = (rnd_num - min) / (max - min);
  }
  void SetAuxRnd(double rnd_num) const { aux_rnd = rnd_num; }

  // Some helpful functions
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void AllocArrays();

  virtual void InitGridAngles();

  virtual void GetBRDFforInc_i(int &rdim, double &incomingTheta,
                double &incomingPhi, int &incIndex, int &neigh, double &eps);

  virtual void GetBRDFforAllInc(int &neigh, double &eps);

  virtual void ComputeGrid();

  virtual void ReadDataDB(int &sample_num, int &measur_num, int &rdim,
                          vector<const char*> &names_db);

  virtual void ReadDataBuildSTree(int &sample_num, int &measur_num, int &rdim,
                                  vector<const char*> &names_db);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  // Such variables as _v_angles, _h_angles, _gridAngles do not depend on
  // DB data => they can be computed at once for all classes and then
  // just set for these classes to reduce time-consuming.
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // This is user's responsibility to set h_count equa to 'h_angles' array
  // size. (h_angles should be static array)
  inline void SetHAngles(int &h_count, double *h_angles)
  {
    _h_count = h_count;     _h_angles = h_angles;
  }

  inline void SetVAngles(int &v_count, double *v_angles)
  {
    _v_count = v_count;     _v_angles = v_angles;
  }

  inline void SetVHAngles(int &v_count, double *v_angles,
                          int &h_count, double *h_angles)
  {
    _h_count = h_count;     _h_angles = h_angles;
    _v_count = v_count;     _v_angles = v_angles;
  }

  inline void SetGrid(int &v_count, double *v_angles, int &h_count,
                      double *h_angles, T_vec_polars &gridAngles)
  {
    _h_count = h_count;     _h_angles = h_angles;
    _v_count = v_count;     _v_angles = v_angles;
    _gridAngles = gridAngles;
  }
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  inline void SetDBSearchTree(int &r_npts, int &r_dim, ANNkd_tree *tree)
  {
    int r_bs = 1; // bucket size;
    _db_s_tree = new ANNkd_tree(r_npts, r_dim, r_bs);
    _db_s_tree = tree;
  }

  inline void SetAllDBData(T_dataDB &brdf_i, int &r_npts, int &r_dim,
                           ANNkd_tree *tree)
  {
    int r_bs = 1; // bucket size;

    _db_s_tree = new ANNkd_tree(r_npts, r_dim, r_bs);
    _db_s_tree = tree;

    _brdf_i = brdf_i;
  }
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  // used by SpawnStochasticRays
  int SpawnStochasticDiffuseRays(const CValues       &kd_local,
				 CContributionArray  &carray,
				 const CHitPointInfo &hitInfo,
				 CSamplingInfo        &samplingInfo,
				 int                 maxRays) const;


};

/*****************************************************************************
*                                                                            *
*                  CDBDana_BRDFIsotrpic - Isotropic case                     *
*                                                                            *
******************************************************************************/

class CDBDana_BRDFIsotropic:
  public CDBDana_BRDFAnisotropic
{
public:
  // constructor
  CDBDana_BRDFIsotropic():CDBDana_BRDFAnisotropic()
  {}

  virtual ~CDBDana_BRDFIsotropic()
  {};

  // this is deep copy
  virtual CSurface *Dup() const;
  virtual CDBDana_BRDFIsotropic* CreateNewObject() const
  { return new CDBDana_BRDFIsotropic; }

  inline T_dataDB GetBRDFData()
  {
    int dim = 3;  // Isotropic case

    if((int)_brdf_i.size() <= 0)
    {
      cout << "Currently this array is empty. Please, specify the data\n";
      T_dataDB dummy_data;
      S_entryDB dummy;
      CValues blackc(0,0,0);
      ANNpoint d_pt;
      d_pt = annAllocPt(dim);

      for(int i = 0; i < dim; i++) d_pt[i] = 0.0;

      dummy.p = d_pt;
      dummy.brdf = blackc;
      dummy.avg = 0.0;
      dummy_data = T_dataDB(0, dummy);

      return dummy_data;
    }
    return _brdf_i;
  }

  virtual EType GetType() const { return EE_DBBRDF;}

  virtual bool
  GetAlbedo(CValues &albedo, const CHitPointInfo &hitInfo,
	    EDistributionType   distType=EE_ALL) const;

  //----------------------------------------------------------------------

  // Different variants of data processing. See source file for explanation
  //----------------------------------------------------------------------
  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count,
			double *v_angles, double *h_angles);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, double *v_angles,
			double *h_angles, T_vec_polars &grid_angles);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count, int &h_count,
			T_dataDB &brdf_i, ANNkd_tree *tree);

  virtual void InitData(int &sample_num, int &measur_num,
			vector<const char*> &names_db, int &neigh, double &eps,
                        int &v_count, int &h_count, double *v_angles,
			double *h_angles, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count, int &h_count,
			double *v_angles, double *h_angles,
			T_dataDB &brdf_i, ANNkd_tree *tree);

  virtual void InitData(int &neigh, double &eps, int &v_count, int &h_count,
			double *v_angles, double *h_angles,
			T_vec_polars &grid_angles, T_dataDB &brdf_i,
			ANNkd_tree *tree);
  //----------------------------------------------------------------------


  virtual float GetAverageDiffuseness(void) const;

  virtual float GetDiffuseness(const CHitPointInfo &hitinfo,
			       EDistributionType distType=EE_ALL) const;

  virtual bool GetTransparency(CValues &transparency,
			       const CHitPointInfo &hitinfo) const;

  virtual bool GetDefaultColor(CValues &defaultColor,
			       const CHitPointInfo &hitInfo) const;


  virtual void Describe(ostream &app, int ind) const;


  virtual int
  SpawnStochasticRays(CContributionArray  &carray,
		      const CHitPointInfo &hitInfo,
		      CSamplingInfo       &samplingInfo,
      		      EDistributionType   distType = EE_ALL) const;

  virtual bool
  EvaluateBSDF(CValues             &brdf,
	       const CHitPointInfo &hitInfo,
	       const CVector3D     &out,
	       EDistributionType   distType=EE_ALL) const;

  // Print members of this class:
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void PrintDB_SearchTree(ostream &app) const;
  virtual void PrintBRDF_avg_val(ostream &app) const;
  virtual void PrintBRDF_rgb_val(ostream &app) const;

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

private:
  CDBDana_BRDFIsotropic& operator=(const CDBDana_BRDFIsotropic&);
  CDBDana_BRDFIsotropic(const CDBDana_BRDFIsotropic&);

protected:

  // Some helpful functions
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void AllocArrays();
  virtual void GetBRDFforAllInc(int &neigh, double &eps);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  // used by SpawnStochasticRays
  int SpawnStochasticDiffuseRays(const CValues       &kd_local,
				 CContributionArray  &carray,
				 const CHitPointInfo &hitInfo,
				 CSamplingInfo        &samplingInfo,
				 int                 maxRays) const;


};


/*****************************************************************************
*                                                                            *
*                  CDBBonn_BRDFAnisotrpic - Anisotropic case                 *
*                                                                            *
******************************************************************************/

class CDBBonn_BRDFAnisotropic:
  public CDBDana_BRDFAnisotropic
{
public:
  // constructor
  CDBBonn_BRDFAnisotropic():CDBDana_BRDFAnisotropic()
  {}

  virtual ~CDBBonn_BRDFAnisotropic()
  {};

  // this is deep copy
  virtual CSurface *Dup() const;
  virtual CDBBonn_BRDFAnisotropic* CreateNewObject() const
  { return new CDBBonn_BRDFAnisotropic; }

  inline T_dataDB GetBRDFData()
  {
    int dim = 4;  // Anisotropic case

    if((int)_brdf_i.size() <= 0)
    {
      cout << "Currently this array is empty. Please, specify the data\n";
      T_dataDB dummy_data;
      S_entryDB dummy;
      CValues blackc(0,0,0);
      ANNpoint d_pt;
      d_pt = annAllocPt(dim);

      for(int i = 0; i < dim; i++) d_pt[i] = 0.0;

      dummy.p = d_pt;
      dummy.brdf = blackc;
      dummy.avg = 0.0;
      dummy_data = T_dataDB(0, dummy);

      return dummy_data;
    }
    return _brdf_i;
  }

  virtual EType GetType() const { return EE_DBBRDF;}

  virtual bool GetDefaultColor(CValues &defaultColor,
			       const CHitPointInfo &hitInfo) const;

  virtual void Describe(ostream &app, int ind) const;


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

private:
  CDBBonn_BRDFAnisotropic& operator=(const CDBBonn_BRDFAnisotropic&);
  CDBBonn_BRDFAnisotropic(const CDBBonn_BRDFAnisotropic&);

protected:

  // Some helpful functions
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void ReadDataDB(int &sample_num, int &measur_num, int &rdim,
                          vector<const char*> &names_db);

  virtual void ReadDataBuildSTree(int &sample_num, int &measur_num, int &rdim,
                                  vector<const char*> &names_db);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
};


/*****************************************************************************
*                                                                            *
*                    CDBBonn_BRDFIsotrpic - Isotropic case                   *
*                                                                            *
******************************************************************************/

class CDBBonn_BRDFIsotropic:
  public CDBDana_BRDFIsotropic
{
public:
  // constructor
  CDBBonn_BRDFIsotropic():CDBDana_BRDFIsotropic()
  {}

  virtual ~CDBBonn_BRDFIsotropic()
  {};

  // this is deep copy
  virtual CSurface *Dup() const;
  virtual CDBBonn_BRDFIsotropic* CreateNewObject() const
  { return new CDBBonn_BRDFIsotropic; }

  inline T_dataDB GetBRDFData()
  {
    int dim = 3;  // Isotropic case

    if((int)_brdf_i.size() <= 0)
    {
      cout << "Currently this array is empty. Please, specify the data\n";
      T_dataDB dummy_data;
      S_entryDB dummy;
      CValues blackc(0,0,0);
      ANNpoint d_pt;
      d_pt = annAllocPt(dim);

      for(int i = 0; i < dim; i++) d_pt[i] = 0.0;

      dummy.p = d_pt;
      dummy.brdf = blackc;
      dummy.avg = 0.0;
      dummy_data = T_dataDB(0, dummy);

      return dummy_data;
    }
    return _brdf_i;
  }

  virtual EType GetType() const { return EE_DBBRDF;}


  virtual bool GetDefaultColor(CValues &defaultColor,
			       const CHitPointInfo &hitInfo) const;

  virtual void Describe(ostream &app, int ind) const;


private:
  CDBBonn_BRDFIsotropic& operator=(const CDBBonn_BRDFIsotropic&);
  CDBBonn_BRDFIsotropic(const CDBBonn_BRDFIsotropic&);

protected:

  // Some helpful functions
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual void ReadDataDB(int &sample_num, int &measur_num, int &rdim,
                          vector<const char*> &names_db);

  virtual void ReadDataBuildSTree(int &sample_num, int &measur_num, int &rdim,
                                  vector<const char*> &names_db);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

};




__END_BRDFLIB_HEADER

#endif // __PHONG_H__
