/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This file contains the declaration of the CBooleanSurface class.    //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
#ifndef __CBOOLEANSURFACE_HPP__
#define __CBOOLEANSURFACE_HPP__


#include <memory>
#include <iostream>
#include "CSurface.hpp"


/////////////////////////////////////////////////////////////////////////
//                                                                     //
// This class is a constructive geometry implementation for boolean    //
// operation between two surfaces.                                     //
//                                                                     //
/////////////////////////////////////////////////////////////////////////
class CBooleanSurface : public CSurface
{
public:
  CBooleanSurface(const std::string& strName,
                  CSurface* pOrigSurface1,
                  CSurface* pOrigSurface2);
  virtual ~CBooleanSurface();


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

  // Do the necessary preprocessing that a surface needs
  virtual void      Preprocess();

  // Compute the intersections of the surface with a ray
  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
  virtual void      DrawGL()                                      const;

  // Generate shader code creating a global object describing the
  // specific object.
  virtual void GenerateShaderForObject(std::ostream& o) const;


protected:
  CBooleanSurface(const CBooleanSurface& surface);

  // This function describes the boolean operation representing this
  // surface
  virtual bool IsIn(bool surface1, bool surface2) const = 0;

  // This function does the concrete OpenGL drawing of the surface
  virtual void ConcreteDrawGL() const = 0;


  // This function sets the stencil buffer to show the part of the
  // first surface (A) (front or back face according to 'face') that
  // is inside of the second surface B.
  void drawInside(CSurface *pA, CSurface *pB, GLenum face, GLenum test) const;

  // This function fixes up the depth buffer with the surface depth
  // values
  void drawFixup(CSurface *pA) const;


  // The two surfaces to which the boolean operation is applied
  std::auto_ptr<CSurface> pSurface1;
  std::auto_ptr<CSurface> pSurface2;
};


#endif // __CBOOLEANSURFACE_HPP__
