//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  VISU OBJECT : interactive object for VISU entities implementation
// File:    VISU_OpenGLPointSpriteMapper.hxx
// Author:  
// Module : VISU
//
#ifndef VISU_OpenGLPointSpriteMapper_HeaderFile
#define VISU_OpenGLPointSpriteMapper_HeaderFile

#if defined(_MSC_VER)
# pragma warning ( disable : 4275 )
#endif

#ifdef WIN32
#include <windows.h>
#endif

#include <GL/gl.h>

#include <vtkSmartPointer.h>
#include <vtkConfigure.h>

#include "VTKViewer.h"

class vtkCellArray;
class vtkPoints;
class vtkProperty;
class vtkImageData;
class vtkXMLImageDataReader;

#ifndef VTK_IMPLEMENT_MESA_CXX
#include <vtkOpenGLPolyDataMapper.h>
#define MAPPER_SUPERCLASS vtkOpenGLPolyDataMapper
#else
#include <vtkMesaPolyDataMapper.h>
#define MAPPER_SUPERCLASS vtkMesaPolyDataMapper
#endif

#ifndef GL_ARB_shader_objects
typedef GLuint GLhandleARB;
#endif

#include "VISUPipeline.hxx"

//----------------------------------------------------------------------------
//! OpenGL Point Sprites PolyData Mapper.
/*!
 * VISU_OpenGLPointSpriteMapper is a class that maps polygonal data 
 * (i.e., vtkPolyData) to graphics primitives. It is performing the mapping
 * to the rendering/graphics hardware/software. It is now possible to set a 
 * memory limit for the pipeline in the mapper. If the total estimated memory 
 * usage of the pipeline is larger than this limit, the mapper will divide 
 * the data into pieces and render each in a for loop.
 */
class VISU_PIPELINE_EXPORT VISU_OpenGLPointSpriteMapper : public MAPPER_SUPERCLASS
{
public:
  //! The Point Sprites rendering mode.
  /*!
   * Accumulate : Uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), and no depth testing
   * so that points are accumulated. Suitable for Galaxy plots.
   * Occlude : No blending. Particles are solid spheres and depth testing is
   * used as usual. Suitable for most particle simulations without the need
   * for opacity.
   */
  enum RenderModes { Accumulate = 0, Occlude };

  enum PrimitiveTypes { PointSprite = 0, OpenGLPoint, GeomSphere };

  static VISU_OpenGLPointSpriteMapper *New();
  vtkTypeRevisionMacro(VISU_OpenGLPointSpriteMapper,MAPPER_SUPERCLASS);

  //! Set the initial point size to be used.
  /*!
   * This value forms the base upon which the distance attenuation acts.
   * Usually the pointsize is set to the maximum supported by the graphics
   * card for sprite display, then the quadratic factors are adjusted to
   * bring the size down.
   */
  //! Get the initial point size to be used.
  vtkGetMacro(DefaultPointSize, float);

  //! Set Average Cell Size.
  void
  SetAverageCellSize(float theSize);

  //! Get Average Cell Size.
  vtkGetMacro(AverageCellSize, float);

  //! Set the Render Mode for the mapper.
  vtkSetMacro(RenderMode, int);

  //! Get the Render Mode for the mapper.
  vtkGetMacro(RenderMode, int);

  //! Implement superclass render method.
  virtual void RenderPiece(vtkRenderer *ren, vtkActor *a);

  //! Release any graphics resources that are being consumed by this mapper.
  void ReleaseGraphicsResources(vtkWindow *);

  //! Draw method for OpenGL.
  virtual int Draw(vtkRenderer *ren, vtkActor *a);

  //! Return the maximum point size supported by the graphics hardware.
  static float GetMaximumSupportedSize();

  //! Set usage of #vtkOpenGLPolyDataMapper.
  /*!
   * This flags prevents using of the VISU_OpenGLPointSpriteMapper
   * (#vtkOpenGLPolyDataMapper is using instead).
   */
  vtkSetMacro(UseOpenGLMapper, bool);

  //! Get usage of #vtkOpenGLPolyDataMapper.
  vtkGetMacro(UseOpenGLMapper, bool);

  //! Set usage of Point Sprites.
  vtkSetMacro(UsePointSprites, bool);

  //! Get usage of Point Sprites.
  vtkGetMacro(UsePointSprites, bool);

  //! Set usage of textures for Point Sprites.
  /*! Works only if usage of Point Sprites is turned on. */
  vtkSetMacro(UseTextures, bool);

  //! Get usage of textures for Point Sprites.
  vtkGetMacro(UseTextures, bool);

  //! Set usage of vertex shader.
  /*! Works only if usage of Point Sprites is turned on. */
  vtkSetMacro(UseShader, bool);

  //! Get usage of vertex shader.
  vtkGetMacro(UseShader, bool);

  //! Point Sprite drawing mode
  /*!
   * 0 - Results  - different colors, different sizes.
   * 1 - Geometry - fixed color, fixed size.
   * 2 - Outside  - different colors, fixed size.
   */
  vtkGetMacro(PointSpriteMode, int);
  void SetPointSpriteMode( int );

  //! Get the Primitive type
  vtkGetMacro(PrimitiveType, int);

  //! Set the Primitive type
  void SetPrimitiveType( int );

  //! Set Point Sprite Clamp.
  void SetPointSpriteClamp( float );

  //! Get Point Sprite Clamp.
  vtkGetMacro(PointSpriteClamp, float);

  //! Set Point Sprite Const Size.
  void SetPointSpriteSize( float );

  //! Get Point Sprite Const Size.
  vtkGetMacro(PointSpriteSize, float);

  //! Set Point Sprite Minimum Size.
  void SetPointSpriteMinSize( float );

  //! Get Point Sprite Minimum Size.
  vtkGetMacro(PointSpriteMinSize, float);

  //! Set Point Sprite Maximum Size.
  void SetPointSpriteMaxSize( float );

  //! Get Point Sprite Maximum Size.
  vtkGetMacro(PointSpriteMaxSize, float);

  //! Set Point Sprite Magnification.
  void SetPointSpriteMagnification( float );

  //! Get Point Sprite Magnification.
  vtkGetMacro(PointSpriteMagnification, float);

  //! Set Point Sprite AlphaThreshold.
  void SetPointSpriteAlphaThreshold( float );

  //! Get Point Sprite AlphaThreshold.
  vtkGetMacro(PointSpriteAlphaThreshold, float);

  //! Set Point Sprite Opacity
  vtkSetMacro(PointSpriteOpacity, float);

  //! Get Point Sprite Opacity
  vtkGetMacro(PointSpriteOpacity, float);

  //! Set ImageData for Point Sprite Texture.
  void SetImageData(vtkImageData* theImageData);

  //! Get ImageData for Point Sprite Texture.
  vtkImageData* GetImageData();

protected:
  VISU_OpenGLPointSpriteMapper();
  ~VISU_OpenGLPointSpriteMapper();

  //! Initializing OpenGL extensions.
  bool              InitExtensions();

  //! Activate Point Sprites.
  void              InitPointSprites();

  //! Deactivate Point Sprites.
  void              CleanupPointSprites();

  //! Initializing textures for Point Sprites.
  void              InitTextures();

  //! Initializing of the Vertex Shader.
  void              InitShader();

  //! Set Vertex Shader variable.
  void              SetShaderVariable( const char* variable, float value );

  //! Getting information about Vertex Shader compiling and linking.
  void              PrintInfoLog( GLhandleARB );

private:
  bool              UseOpenGLMapper;

  bool              UsePointSprites;
  bool              UseTextures;
  bool              UseShader;

  int               RenderMode;
  int               ListId;
  vtkIdType         TotalCells;
  int               ExtensionsInitialized;
  float             DefaultPointSize;

  GLhandleARB       VertexProgram;

  int               PrimitiveType;

  int               PointSpriteMode;

  float             PointSpriteClamp;
  float             PointSpriteSize;
  float             PointSpriteMinSize;
  float             PointSpriteMaxSize;
  float             PointSpriteMagnification;

  GLuint            PointSpriteTexture;
  float             PointSpriteAlphaThreshold;
  float             PointSpriteOpacity;

  float             AverageCellSize;

  vtkSmartPointer<vtkImageData> ImageData;
};

#endif
