/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This file contains the declaration of the CConcreteSurface class.   //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
#ifndef __CCONCRETESURFACE_HPP__
#define __CCONCRETESURFACE_HPP__


#include "portable_gl.h"
#include "CSurface.hpp"


/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This class is an interface that must be implemented by the concrete //
// surfaces, which are the real elementary surfaces, as opposed to     //
// surfaces made of other surfaces.                                    //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
class CConcreteSurface : public CSurface
{
public:
  CConcreteSurface(const std::string& strName, bool useTransformation = true);
  virtual ~CConcreteSurface();



  ///////////////////////////////////////////////////////
  // Interface that must be implemented to be rendered //
  ///////////////////////////////////////////////////////

  // This functions calculates the normal vector at the given point.
  virtual void Normal(const CVector& hit, CVector& normal)    const = 0;



  // Compute the intersections of the surface with a ray, just
  // redirects the call to a protected function and sets the pFirst it
  // to this
  virtual int  Intersect(const CRay&              ray,
                         hitcontainer&            hits,
                         const CConcreteSurface **pFirstHit)  const;

  // Do the necessary preprocessing that a surface needs the be
  // rendered in OpenGL
  virtual void PreprocessGL();

  // Render the surface in OpenGL, just redirects the call to a
  // protected function that properly sets materials and matrices
  virtual void DrawGL()                                       const;

  // Generate shader code creating a global object describing the
  // specific object.  It is an overload of the "real" function so
  // that a class name can be given to the generation function.
  virtual void GenerateShaderForObject(std::ostream& o,
                                       const std::string& className) const;




  ////////////////
  // Properties //
  ////////////////

  // Color of the surface
  CColor  m_PropSurfaceColor;

  // Ambient color coefficient
  real_t  m_PropAmbientCoef;

  // Diffuse color coefficient
  real_t  m_PropDiffuseCoef;

  // Specular color coefficient
  real_t  m_PropSpecularCoef;

  // Shininess coefficient
  real_t  m_PropShininessCoef;

  // Reflexion coefficient
  real_t  m_PropReflexionCoef;

  // Refraction coefficient
  real_t  m_PropRefractionCoef;


protected:
  // Compute the intersections of the surface with a ray
  virtual int  Intersect(const CRay& ray, hitcontainer& hits) const = 0;

  // Render the surface in OpenGL
  virtual void ConcreteDrawGL()                               const = 0;


  // Display list for this concrete surface
  GLuint  m_displayList;

private:
  bool    m_useTransformation;
};




#endif // __CCONCRETESURFACE_HPP__
