/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This file contains the declaration of the CScene class.             //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
#ifndef __CSCENE_HPP__
#define __CSCENE_HPP__


#include <vector>
#include "real.hpp"
#include "CColor.hpp"
#include "CVector.hpp"
#include "CPropertyObject.hpp"

class CImage;
class CLight;
class CSurface;


/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This class is just a structure that represents all the informations //
// describing a scene.                                                 //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
class CScene : public CPropertyObject
{
public:
  // Rendering mode
  int      m_renderingModes;
  static const int ModeNone         = 0;
  static const int ModeRaytrace     = (1 << 0);
  static const int ModeOpenGL       = (1 << 1);
  static const int ModeDepth        = (1 << 2);
  static const int ModeStereogram   = (1 << 3);
  static const int ModeShaderRender = (1 << 4);
  static const int ModeShaderText   = (1 << 5);

  // Constant used to compare real values with zero
  real_t   m_PropSmallReal;

  // Width of the image
  int      m_PropWidth;
  // Height of the image
  int      m_PropHeight;

  // Color of the background of the scene
  CColor   m_PropBackColor;
  // Position of the viewer
  CVector  m_PropCameraPos;
  // Target towards with the viewer looks
  CVector  m_PropCameraTarget;
  // Up vector of the camera
  CVector  m_PropUpVector;

  // Focale distance of the lens of the camera
  real_t   m_PropFocale;
  // Dimension of the film of the camera
  real_t   m_PropDimFilm;

  // Near clip plane
  real_t   m_PropNearClipPlane;
  // Far clip plane
  real_t   m_PropFarClipPlane;

  // Refraction index of the scene
  real_t   m_PropGenRefrIndex;

  // Max level of recursion
  int      m_PropMaxLevel;
  // Minimal energy to launch a new ray
  real_t   m_PropMinEnergy;


  // Stereogram pattern image file
  std::string m_PropPatternFile;
  // Random pattern width
  int         m_PropRandomPatternWidth;
  // Random pattern height
  int         m_PropRandomPatternHeight;
  // Nearest depth (in world coordinates) in the stereogram
  real_t      m_PropNearestDepth;
  // Farthest depth (in world coordinates) in the stereogram
  real_t      m_PropFarthestDepth;
  // The value to which the nearest depth will map
  real_t      m_PropNearestMapsTo;
  // The value to which the farthest depth will map
  real_t      m_PropFarthestMapsTo;


  // Reflection enabled in shader
  int    m_PropReflectionEnabled;
  // Refraction enabled in shader
  int    m_PropRefractionEnabled;
  // Ray offset when launching a new ray in shader
  real_t m_PropRayOffset;
  // Shadow type in shader
  int    m_PropShadowType;


  CScene();
  virtual ~CScene();

  inline void addLight(CLight *pLight);
  inline void addSurface(CSurface *pSurface);

  typedef std::vector<CSurface *>  surface_container;
  typedef std::vector<CLight *>    light_container;

  // Lights of the scene
  light_container   m_vLights;
  // Surface of the scene
  surface_container m_vSurfaces;


  // Scene preprocessing
  void init();
  // Raytracing entry point
  void rayTrace(CImage *pImage, CImage *pDepthImage = NULL) const;
};




// Add a light to the scene
inline void CScene::addLight(CLight *pLight)
{
  m_vLights.push_back(pLight);
}


// Add a surface to the scene
inline void CScene::addSurface(CSurface *pSurface)
{
  m_vSurfaces.push_back(pSurface);
}


#endif // __CSCENE_HPP__
